Starting with Pandas version 0.22, esiste anche un'alternativa alla apply
: pipe
, che può essere notevolmente più veloce rispetto all'utilizzo di apply
(è possibile anche controllare this question per maggiori differenze tra le due funzionalità).
Per esempio:
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
La versione apply
df.groupby('my_label').apply(lambda grp: grp.count()/df.shape[0])
dà
my_label
my_label
A 0.285714
B 0.142857
C 0.142857
D 0.285714
E 0.142857
e la versione pipe
df.groupby('my_label').pipe(lambda grp: grp.size()/grp.size().sum())
cede
my_label
A 0.285714
B 0.142857
C 0.142857
D 0.285714
E 0.142857
Così i valori sono identici, tuttavia, i tempi differiscono parecchio (almeno per questo piccolo dataframe):
%timeit df.groupby('my_label').apply(lambda grp: grp.count()/df.shape[0])
100 loops, best of 3: 5.52 ms per loop
e
%timeit df.groupby('my_label').pipe(lambda grp: grp.size()/grp.size().sum())
1000 loops, best of 3: 843 µs per loop
Anche il suo inserimento in una funzione è semplice:
def get_perc(grp_obj):
gr_size = grp_obj.size()
return gr_size/gr_size.sum()
Ora è possibile chiamare
df.groupby('my_label').pipe(get_perc)
cedendo
my_label
A 0.285714
B 0.142857
C 0.142857
D 0.285714
E 0.142857
Tuttavia, per questo caso particolare, non avrete nemmeno bisogno di un groupby
, ma si può semplicemente utilizzare value_counts
come questo:
df['my_label'].value_counts(sort=False)/df.shape[0]
resa
A 0.285714
C 0.142857
B 0.142857
E 0.142857
D 0.285714
Name: my_label, dtype: float64
Per questo piccolo dataframe si è abbastanza veloce
%timeit df['my_label'].value_counts(sort=False)/df.shape[0]
1000 loops, best of 3: 770 µs per loop
È inoltre possibile utilizzare 'isto = gg.size()' per semplicità – Reservedegotist