En utilisant des exemples de données:
df = pd.DataFrame({'key1' : ['a','a','b','b','a'],
'key2' : ['one', 'two', 'one', 'two', 'one'],
'data1' : np.random.randn(5),
'data2' : np. random.randn(5)})
df
data1 data2 key1 key2
0 0.361601 0.375297 a one
1 0.069889 0.809772 a two
2 1.468194 0.272929 b one
3 -1.138458 0.865060 b two
4 -0.268210 1.250340 a one
J'essaie de comprendre comment grouper les données par clé1 et additionner uniquement les valeurs de données1 où clé2 est égal à «un».
Voici ce que j'ai essayé
def f(d,a,b):
d.ix[d[a] == b, 'data1'].sum()
df.groupby(['key1']).apply(f, a = 'key2', b = 'one').reset_index()
Mais cela me donne un cadre de données avec des valeurs 'Aucune'
index key1 0
0 a None
1 b None
Des idées ici? Je cherche l'équivalent en Pandas du code SQL suivant:
SELECT Key1, SUM(CASE WHEN Key2 = 'one' then data1 else 0 end)
FROM df
GROUP BY key1
Pour votre information - j'ai vu des sommes conditionnelles pour des pandas agrégés mais je ne pouvais pas transformer la réponse fournie pour travailler avec des sommes plutôt que des comptes.
Merci d'avance
Première groupe par la colonne clé1:
In [11]: g = df.groupby('key1')
puis, pour chaque groupe, prenez le sous-fichier DataFrame où key2 est égal à «un» et additionnez la colonne data1:
In [12]: g.apply(lambda x: x[x['key2'] == 'one']['data1'].sum())
Out[12]:
key1
a 0.093391
b 1.468194
dtype: float64
Pour expliquer ce qui se passe, regardons le groupe 'a':
In [21]: a = g.get_group('a')
In [22]: a
Out[22]:
data1 data2 key1 key2
0 0.361601 0.375297 a one
1 0.069889 0.809772 a two
4 -0.268210 1.250340 a one
In [23]: a[a['key2'] == 'one']
Out[23]:
data1 data2 key1 key2
0 0.361601 0.375297 a one
4 -0.268210 1.250340 a one
In [24]: a[a['key2'] == 'one']['data1']
Out[24]:
0 0.361601
4 -0.268210
Name: data1, dtype: float64
In [25]: a[a['key2'] == 'one']['data1'].sum()
Out[25]: 0.093391000000000002
Cela peut être légèrement plus facile/plus clair en limitant le cadre de données à ceux avec key2 égal à un:
In [31]: df1 = df[df['key2'] == 'one']
In [32]: df1
Out[32]:
data1 data2 key1 key2
0 0.361601 0.375297 a one
2 1.468194 0.272929 b one
4 -0.268210 1.250340 a one
In [33]: df1.groupby('key1')['data1'].sum()
Out[33]:
key1
a 0.093391
b 1.468194
Name: data1, dtype: float64
Je pense qu'aujourd'hui avec les pandas 0,23, vous pouvez le faire:
import numpy as np
df.assign(result = np.where(df['key2']=='one',df.data1,0))\
.groupby('key1').agg({'result':sum})
L'avantage de ceci est que vous pouvez l'appliquer à plus d'une colonne du même dataframe
df.assign(
result1 = np.where(df['key2']=='one',df.data1,0),
result2 = np.where(df['key2']=='two',df.data1,0)
).groupby('key1').agg({'result1':sum, 'result2':sum})
Vous pouvez filtrer votre base de données avant vous effectuez votre opération groupby
. Si cela réduit votre index de série du fait que toutes les valeurs sont hors de portée, vous pouvez utiliser reindex
avec fillna
:
res = df.loc[df['key2'].eq('one')]\
.groupby('key1')['data1'].sum()\
.reindex(df['key1'].unique()).fillna(0)
print(res)
key1
a 3.631610
b 0.978738
c 0.000000
Name: data1, dtype: float64
J'ai ajouté une ligne supplémentaire à des fins de démonstration.
np.random.seed(0)
df = pd.DataFrame({'key1': ['a','a','b','b','a','c'],
'key2': ['one', 'two', 'one', 'two', 'one', 'two'],
'data1': np.random.randn(6),
'data2': np.random.randn(6)})