对级联熊猫df进行唯一枚举

时间:2018-11-21 16:41:19

标签: python pandas

我有一些数据框,其中数据按组标记,比如这样:

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标记(即id 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 +1

2)将此数据帧与初始数据帧连接,并放置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')

新标签正是需要的,但是我的解决方案似乎太复杂了。您对如何简化变得有建议吗?我想我一定很想念东西!

预先感谢

M。

2 个答案:

答案 0 :(得分:1)

使用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

答案 1 :(得分:1)

连接起来后,可以将{tag}和name列中的groupby和{id}列中的transformfirst一起使用。然后sort_values这个系列和cumsum的{​​{1}}大于0,例如:

diff

您将获得预期的输出:

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 ... ,您可以groupbydrop_duplicates获取第一个id的索引,使用index创建具有增量值的new列和loc,然后在range之后的ffill来填充值:

sort_values

您将得到相同的结果