Groupby在pandas数据帧中

时间:2017-11-01 22:08:40

标签: python pandas pandas-groupby

考虑以下数据集:

a        b
0        23
0        21
1        25
1        20
1        19
2        44
2        11

如何在b列中找到大于20的值的百分比,并且根据列a位于同一个群集中。 我的代码为每个组提供了相同的值。

NN20 = [x for x in b if (x > 20)]
percent_20 = lambda x: float(len(NN20)) / float(len(b))
pnn20=data.groupby('a').apply(percent_20) 

3 个答案:

答案 0 :(得分:4)

IIUC:

In [179]: df.groupby('a')['b'].apply(lambda x: x.gt(20).mean())
Out[179]:
a
0    1.000000
1    0.333333
2    0.500000
Name: b, dtype: float64

In [183]: df.groupby('a')['b'].transform(lambda x: x.gt(20).mean())
Out[183]:
0    1.000000
1    1.000000
2    0.333333
3    0.333333
4    0.333333
5    0.500000
6    0.500000
Name: b, dtype: float64

答案 1 :(得分:2)

如果你需要快速的东西,np.bincount可能是一个很好的解决方案而不是Pandas groupby。

np.bincount(df.loc[df.b > 20, 'a']) / np.bincount(df.a))

返回

array([ 1.        ,  0.33333333,  0.5       ])

或者,如果您想将输出转换回系列,则可以随后使用np.take

pd.Series((np.bincount(df.loc[df.b > 20, 'a']) / np.bincount(df.a)).take(df.a))

# 0    1.000000
# 1    1.000000
# 2    0.333333
# 3    0.333333
# 4    0.333333
# 5    0.500000
# 6    0.500000
# dtype: float64

在任何一种情况下,这似乎都很快。

较小的案例:提供数据集

来自MaxU的

groupby方法

%timeit df.groupby('a')['b'].transform(lambda x: x.gt(20).mean())
2.51 ms ± 65.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

np.bincount方法

%timeit pd.Series((np.bincount(df.loc[df.b > 20, 'a']) / np.bincount(df.a)).take(df.a))
271 µs ± 5.28 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

更大的案例:生成的数据集

df = pd.DataFrame({'a': np.random.randint(0, 10, 100000), 
                   'b': np.random.randint(0, 100, 100000)}).sort_values('a')
来自MaxU的

groupby方法

%timeit df.groupby('a')['b'].transform(lambda x: x.gt(20).mean())
11.3 ms ± 40.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

np.bincount方法

%timeit pd.Series((np.bincount(df.loc[df.b > 20, 'a']) / np.bincount(df.a)).take(df.a))
1.56 ms ± 5.47 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

答案 2 :(得分:1)

这是一种方法(为0%添加了另一个值):

data = pd.DataFrame({'a': [0,0,1,1,1,2,2,3],
                     'b': [23,21,25,20,19,44,11,15]})

data['c'] = data['b'].apply(lambda x: int(x>20))
shareOf20 = data.groupby('a')['c'].sum() / data.groupby('a')['c'].count()