为了账号安全,请及时绑定邮箱和手机立即绑定

对连接的熊猫 df 进行唯一的枚举

对连接的熊猫 df 进行唯一的枚举

天涯尽头无女友 2021-08-24 17:21:58
我有一些数据帧,其中数据被分组标记,让我们这样说:df1 = pd.DataFrame({'id':[1,3,7, 10,30, 70, 100, 300], 'name':[1,1,1,1,1,1,1,1], 'tag': [1,1,1, 2,2,2, 3,3]})df2 = pd.DataFrame({'id':[2,5,6, 20, 50, 200, 500, 600], 'name': [2,2,2,2,2,2,2,2], 'tag':[1,1,1, 2, 2, 3,3,3]})df3 = pd.DataFrame({'id':[4, 8, 9, 40, 400, 800, 900], 'name': [3,3,3,3,3,3,3], 'tag':[1,1,1, 2, 3, 3,3]})在每个数据帧中,标签按 id 的升序排列(因此更大的 id 将具有相等或更大的标签)。我的愿望是重新计算连接数据框中的标签,df = pd.concat([df1, df2, df3])这样每个组的标签将按每个组的第一个元素的 id 升序排列。所以,id=1开始的组会被标记为1(即ids 1,3,7),id=2开始的组会被标记为2(即ids 2,5,6),从 4 开始的组将被标记为 3,从 10 开始的组将被标记为 4,依此类推。我确实设法得到了一个(复杂的!)解决方案:1) 获取每组的第一行,将它们放入数据框中,按 id 排序并创建新标签:dff = pd.concat([df1.groupby('tag').first(), df2.groupby('tag').first(), df3.groupby('tag').first()])dff = dff.sort(['id'])dff = dff.reset_index()dff['new_tags'] = dff.index +12) 将此数据框与初始数据框 drop_duplicates 连接起来,以保留新标记的行,按组排序,然后传播新标记:df = pd.concat([dff, df1, df2, df3])df = df.drop_duplicates(subset=['id', 'tag', 'name'])df = df.sort(['name', 'tag'])df = df.fillna(method = 'pad')新标签正是需要的,但我的解决方案似乎太复杂了。你有什么关于如何更容易的建议吗?我想我一定是错过了什么!
查看完整描述

2 回答

?
慕森卡

TA贡献1806条经验 获得超8个赞

一旦连接起来,就可以使用groupby列“标签”和“名称”与transform及first在列“ID”。然后,sort_values这个系列cumsum的diff大于0,例如:


df = pd.concat([df1, df2, df3]).sort_values('id').reset_index(drop=True)

df['new'] = (df.groupby(['tag','name'])['id'].transform('first')

               .sort_values().diff().ne(0.).cumsum())

你会得到预期的输出:


     id  name  tag  new

0     1     1    1    1

1     2     2    1    2

2     3     1    1    1

3     4     3    1    3

4     5     2    1    2

5     6     2    1    2

6     7     1    1    1

7     8     3    1    3

8     9     3    1    3

9    10     1    2    4

10   20     2    2    5

11   30     1    2    4

12   40     3    2    6

...

编辑:避免使用groupby,你可以drop_duplicates和index获得第一IDS的索引,创建新列与增值利用loc和range再ffill后sort_values,以填补值:


df = pd.concat([df1, df2, df3]).sort_values('id').reset_index(drop=True)

list_ind = df.drop_duplicates(['name','tag']).index

df.loc[list_ind,'new'] = range(1,len(list_ind)+1)

df['new'] = df.sort_values(['tag','name'])['new'].ffill().astype(int)

你得到相同的结果


查看完整回答
反对 回复 2021-08-24
?
青春有我

TA贡献1784条经验 获得超8个赞

使用pd.concat+ keys,我分解了步骤


df=pd.concat([df1,df2,df3],keys=[0,1,2])

df=df.reset_index(level=0)#get the level=0 index 

df=df.sort_values(['tag','level_0']) # sort the value 


df['New']=(df['tag'].diff().ne(0)|df['level_0'].diff().ne(0)).cumsum()

df

Out[110]: 

   level_0   id  name  tag  New

0        0    1     1    1    1

1        0    3     1    1    1

2        0    7     1    1    1

0        1    2     2    1    2

1        1    5     2    1    2

2        1    6     2    1    2

0        2    4     3    1    3

1        2    8     3    1    3

2        2    9     3    1    3

3        0   10     1    2    4

4        0   30     1    2    4

5        0   70     1    2    4

3        1   20     2    2    5

4        1   50     2    2    5

3        2   40     3    2    6

6        0  100     1    3    7

7        0  300     1    3    7

5        1  200     2    3    8

6        1  500     2    3    8

7        1  600     2    3    8

4        2  400     3    3    9

5        2  800     3    3    9

6        2  900     3    3    9


查看完整回答
反对 回复 2021-08-24
  • 2 回答
  • 0 关注
  • 154 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信