2013-06-21 30 views
5

在熊猫中,如何添加一个新的列,该列根据给定的分组枚举?枚举DataFrame中每个组的每一行

例如,假设下面的数据框:

import pandas as pd 
import numpy as np 

a_list = ['A', 'B', 'C', 'A', 'A', 'C', 'B', 'B', 'A', 'C'] 
df = pd.DataFrame({'col_a': a_list, 'col_b': range(10)}) 
df 
    col_a col_b 
0  A  0 
1  B  1 
2  C  2 
3  A  3 
4  A  4 
5  C  5 
6  B  6 
7  B  7 
8  A  8 
9  C  9 

我想补充一个col_c,让我的基础上col_a分组和排序col_b的“组”的第N行。

所需的输出:

col_a col_b col_c 
0  A  0  1 
3  A  3  2 
4  A  4  3 
8  A  8  4 
1  B  1  1 
6  B  6  2 
7  B  7  3 
2  C  2  1 
5  C  5  2 
9  C  9  3 

我挣扎去col_c。您可以使用.sort_index(by=['col_a', 'col_b'])进行正确的分组和排序,现在可以进入新列并为每行添加标签。

回答

12

cumcount,正是这个情况:

df['col_c'] = g.cumcount() 

因为它在文档中说:

数各组中的每个项目从0到该组的长度 - 1


原始回答(之前cumcount被定义)。

您可以创建一个辅助函数来做到这一点:

def add_col_c(x): 
    x['col_c'] = np.arange(len(x)) 
    return x 

首先按列排序为col_a:

In [12]: g = df.groupby('col_a', as_index=False) 

In [13]: g.apply(add_col_c) 
Out[13]: 
    col_a col_b col_c 
3  A  3  0 
8  A  8  1 
0  A  0  2 
4  A  4  3 
6  B  6  0 
1  B  1  1 
7  B  7  2 
9  C  9  0 
2  C  2  1 
5  C  5  2 

In [11]: df.sort('col_a', inplace=True) 

然后在每一组应用此功能为了得到1,2,...你可以让你se np.arange(1, len(x) + 1)

+0

这基本上回答了这个问题 - 虽然gjreda要求枚举按col_b排序的col_a。 – gabe

+0

@gabe这很奇怪,不知道我是如何管理的:)\ –

+0

太棒了,谢谢@AndyHayden。知道这将是一个groupby,但无法弄清楚如何正确应用它。 –

1

你可以定义自己的函数来处理是:

In [58]: def func(x): 
    ....:  x['col_c'] = x['col_a'].argsort() + 1 
    ....:  return x 
    ....: 

In [59]: df.groupby('col_a').apply(func) 
Out[59]: 
    col_a col_b col_c 
0  A  0  1 
3  A  3  2 
4  A  4  3 
8  A  8  4 
1  B  1  1 
6  B  6  2 
7  B  7  3 
2  C  2  1 
5  C  5  2 
9  C  9  3 
2

给出的答案都涉及到要求每个组一个Python函数,如果你有很多团体向量化的方法应该是更快(我没有检查)。

这里是我的纯numpy的建议:

In [5]: df.sort(['col_a', 'col_b'], inplace=True, ascending=(False, False)) 
In [6]: sizes = df.groupby('col_a', sort=False).size().values 
In [7]: df['col_c'] = np.arange(sizes.sum()) - np.repeat(sizes.cumsum() - sizes, sizes) 
In [8]: print df 
    col_a col_b col_c 
9  C  9  0 
5  C  5  1 
2  C  2  2 
7  B  7  0 
6  B  6  1 
1  B  1  2 
8  A  8  0 
4  A  4  1 
3  A  3  2 
0  A  0  3 
+0

对我来说更快。非常感谢。 – DanT

0

您可以使用转换函数为1

#Create a column of ones 
df['col_c'] = 1 
#Add them sequentially within the group and apply that column to the dataset. 
df['col_c'] = df.groupby('col_a')['col_c'].transform('cumsum') 

唯一的潜在优势,开始枚举使用这种过度cumcount()是熊猫数据框对象中的枚举从1开始,而不是从0开始。虽然说这是一种好处很有意思:D

相关问题