2016-06-02 19 views
3

Ich habe einen Datenrahmen mit verschiedenen Spalten und möchten Mittelwerte von Gruppen unter der Bedingung berechnen, die jede Gruppe eine Mindestanzahl von gültigen Mitglieder hat. Ich habe folgendes mit groupby, Filter und Mean versucht. Es scheint zu funktionieren, aber ich frage mich, ob es eine effizientere Lösung gibt?pandas groupby: effiziente bedingte Aggregation?

import pandas as pd 
import numpy as np 

df = pd.DataFrame({'id' : ['one', 'one', 'two', 'three', 'two', 
          'two', 'two', 'one', 'three', 'one'], 
        'idprop' : [1., 1., 2., 3., 2., # property corresponding to id 
           2., 2., 1., 3., 1.], 
        'x' : np.random.randn(10), 
        'y' : np.random.randn(10)}) 

# set a couple of x values to nan 
s = df['x'].values 
s[s < -0.6] = np.nan 
df['x'] = s 

g = df.groupby('id', sort=False) 
# filter out small group(s) with less than 3 valid values in x 
# result is a new dataframe 
dff = g.filter(lambda d: d['x'].count() >= 3) 

# this means we must group again to obtain the mean value of each filtered group 
result = dff.groupby('id').mean() 
print result 
print type(result) 

Es ist eine weitere Frage auf how to get multiple conditional operations after a Pandas groupby?, die jedoch nur „Filter“ von Zeilenwerte nicht durch die Anzahl der Gruppenelemente. Umgerechnet in meinem Code dies wäre:

res2 = g.agg({'x': lambda d: df.loc[d.index, 'x'][d >= -0.6].sum()}) 

Als Seite Frage: Gibt es eine effizientere Art und Weise Werte unter oder über einer bestimmten Schwelle auf NaN gesetzt? Mein Gehirn wurde verdreht, als ich dies mit loc.

def mean_cond(dfg): 
    if dfg['x'].count() >= 3: 
     return dfg.mean() 
    return None 

print df.groupby('id').apply(mean_cond).dropna() 

Der Vorteil hierbei ist, dass der Gruppierungsprozess nur einmal durchgeführt wird, das effizienten sein könnte anderen groupby nach dem Filter als Laufen:

+1

Antwort auf Ihre Seite Frage: 'df.loc [df ['x'] <-0,6, 'x'] = np.nan' – IanS

+0

Ich bin versucht zu sagen, dass' df.filter (...) .groupby ('id'). mean() 'ist der effizienteste Weg, um zu bekommen, was Sie wollen. – jonchar

Antwort

1

Sie können dies die groupby apply Funktion erreichen. Das einzige Problem ist vielleicht, dass dies dazu führt, dass Gruppen, die die Kriterien nicht erfüllen, in der resultierenden Tabelle als NaNs dargestellt werden. Dies wird leicht gelöst, indem am Ende der Befehl dropna hinzugefügt wird.