Starting with Pandas version 0.22, существует также альтернативу apply
: pipe
, который может быть значительно быстрее, чем при использовании apply
(вы также можете проверить this question для большего различия между двумя функциональными возможностями).
Для примера:
df = pd.DataFrame({"my_label": ['A','B','A','C','D','D','E']})
my_label
0 A
1 B
2 A
3 C
4 D
5 D
6 E
Версия apply
df.groupby('my_label').apply(lambda grp: grp.count()/df.shape[0])
дает
my_label
my_label
A 0.285714
B 0.142857
C 0.142857
D 0.285714
E 0.142857
и версия pipe
df.groupby('my_label').pipe(lambda grp: grp.size()/grp.size().sum())
дает
my_label
A 0.285714
B 0.142857
C 0.142857
D 0.285714
E 0.142857
Таким образом, эти значения идентичны, однако, тайминги отличаются довольно много (по крайней мере, для этого небольшого dataframe):
%timeit df.groupby('my_label').apply(lambda grp: grp.count()/df.shape[0])
100 loops, best of 3: 5.52 ms per loop
и
%timeit df.groupby('my_label').pipe(lambda grp: grp.size()/grp.size().sum())
1000 loops, best of 3: 843 µs per loop
Затем его включение в функцию также является простым:
def get_perc(grp_obj):
gr_size = grp_obj.size()
return gr_size/gr_size.sum()
Теперь вы можете позвонить
df.groupby('my_label').pipe(get_perc)
получая
my_label
A 0.285714
B 0.142857
C 0.142857
D 0.285714
E 0.142857
Однако для этого конкретного случая, вам не нужно даже groupby
, но вы можете просто использовать value_counts
так:
df['my_label'].value_counts(sort=False)/df.shape[0]
с получением
A 0.285714
C 0.142857
B 0.142857
E 0.142857
D 0.285714
Name: my_label, dtype: float64
Для этого небольшого dataframe это довольно быстро
%timeit df['my_label'].value_counts(sort=False)/df.shape[0]
1000 loops, best of 3: 770 µs per loop
Вы также можете использовать 'гисто = gg.size()' для простоты – Reservedegotist