2012-04-04 14 views
6

è possibile calcolare direttamente il prodotto (o per esempio somma) di due colonne senza utilizzarefunzioni GroupBy in pitone Pandas come SUM (col_1 * col_2), media ponderata ecc

grouped.apply(lambda x: (x.a*x.b).sum() 

È molto (meno della metà del tempo sulla mia macchina) più veloce da usare

df['helper'] = df.a*df.b 
grouped= df.groupby(something) 
grouped['helper'].sum() 
df.drop('helper', axis=1) 

Ma non mi piace dover fare questo. È utile ad esempio per calcolare la media ponderata per gruppo. Qui l'approccio lambda sarebbe

grouped.apply(lambda x: (x.a*x.b).sum()/(df.b).sum()) 

e di nuovo è molto più lento di dividere l'helper per b.sum().

risposta

7

Voglio infine costruire un analizzatore di espressioni incorporato array (Numexpr sugli steroidi) per fare cose come questa. In questo momento stiamo lavorando con le limitazioni di Python-- se è stato implementato un aggregatore di Cython fare (x * y).sum() allora potrebbe essere collegato con groupby, ma idealmente si potrebbe scrivere l'espressione Python in funzione:

def weight_sum(x, y): 
    return (x * y).sum() 

e che otterrebbe "JIT-compilato" e sarà veloce come groupby (...). sum(). Quello che sto descrivendo è un progetto piuttosto significativo (molti mesi). Se ci fosse un'implementazione APL compatibile con BSD, potrei essere in grado di fare qualcosa di simile a prima piuttosto un po 'prima (solo pensando ad alta voce).

0

ne dite direttamente gruppo il risultato di x.a * x.b, ad esempio:

from pandas import * 
from numpy.random import randn 
df = DataFrame({'A' : ['foo', 'bar', 'foo', 'bar', 
       'foo', 'bar', 'foo', 'foo'], 
     'B' : ['one', 'one', 'two', 'three', 
       'two', 'two', 'one', 'three'], 
     'C' : randn(8), 'D' : randn(8)}) 

print (df.C*df.D).groupby(df.A).sum() 
+0

Questo funziona naturalmente. Ma sospetto che prima l'intero vettore C * D sia costruito in memoria, quindi viene raggruppato e quindi sommato. Non avrei dovuto farlo se riuscissi a camminare in modo efficiente tra le righe, sommando il c_i * d_i (o solo costruendo C * D per gruppo e poi sommandoli mentre si cammina tra i gruppi). –

0

La risposta arrivò molti anni dopo via pydata blaze

from blaze import * 
data = Data(df) 
somethings = odo(
by(data.something, 
    wm = (data.a * data.weights).sum()/data.weights.sum()), 
pd.DataFrame)