考虑以下数据集:
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)
答案 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()