2017-10-05 6 views
0

j'ai numéro: J'ai des données (~ rangées de 300k)calculer et diviser en fonction de critères multiples Pandas

Date Column 1 Column 2 Column 3 Value 
1/1/2017 A  Jonas  Station1 8 
1/1/2017 A  Greg  Station1 5 
1/1/2017 A  Anton  Station1 1 
1/1/2017 B  Jonas  Station1 4 
1/1/2017 B  Greg  Station1 4 
1/1/2017 B  Mick  Station2 8 
1/1/2017 B  Anton  Station3 7 
1/1/2017 C  Jonas  Station4 2 
1/1/2017 C  Greg  Station1 7 

Je dois calculer pour les prochaines étapes: par chaque date, par la colonne 2, par Colonne3: i ai exemple Greg ':

Date Column 1 Column 2 Column 3 Value 
1/1/2017 A  Greg  Station1 5 
1/1/2017 B  Greg  Station1 4 
1/1/2017 C  Greg  Station1 7 

Somme toute C/Count (A, B), pour cet exemple 7/2 = 3,5 valeur Add '3.5' pour chaque ligne.

Date Column 1 Column 2 Column 3 Value 
1/1/2017 A  Greg  Station1 5+3.5 = 8.5 
1/1/2017 B  Greg  Station1 4+3.5 = 7.5 

Comment faire cela dans pandas/python? Mise à jour: élément comme un 'Greg' j'ai ~ 100, jours ~ 500 et Column1, Colonne2 ~ 1k

+0

Pouvez-vous ajouter des dates différentes dans la base de données et afficher la sortie attendue? – Dark

Répondre

1

Utilisation:

#filter values A, B 
df1 = df[df['Column 1'].isin(['A','B'])] 
#get count per groups, reindex by original index for original size 
b = (df1.groupby(['Date','Column 2', 'Column 3'])['Column 1'] 
     .transform('size') 
     .reindex(df.index)) 

#filter value C and rename for merge 
df2 = df.loc[df['Column 1'] == 'C', ['Date','Column 2','Column 3','Value']] 
     .rename(columns={'Value':'a'}) 

#merge to original a select only new column a 
a = pd.merge(df, df2, 'left')['a'] 
#divide and add column Value - if divide return NaN let original values 
df['Value'] = a.div(b).add(df['Value'], fill_value=0) 
print (df) 
     Date Column 1 Column 2 Column 3 Value 
0 1/1/2017  A Jonas Station1 8.0 
1 1/1/2017  A  Greg Station1 8.5 
2 1/1/2017  A Anton Station1 1.0 
3 1/1/2017  B Jonas Station1 4.0 
4 1/1/2017  B  Greg Station1 7.5 
5 1/1/2017  B  Mick Station2 8.0 
6 1/1/2017  B Anton Station3 7.0 
7 1/1/2017  C Jonas Station4 2.0 
8 1/1/2017  C  Greg Station1 7.0 

Utilisez la fonction personnalisée doit être slowier:

def f(x): 
    a = x.loc[x['Column 1'] == 'C', 'Value'] 
    #mask of all A, B values per group 
    m = x['Column 1'].isin(['A','B']) 
    c = a/m.sum() 
    #if-else, because if no C exist per group get empty Series 
    c = 0 if c.empty else c.item() 
    x.loc[b, 'Value'] +=c 
    return x 


df = df.groupby(['Date','Column 2', 'Column 3']).apply(f) 
print (df) 
     Date Column 1 Column 2 Column 3 Value 
0 1/1/2017  A Jonas Station1 8.0 
1 1/1/2017  A  Greg Station1 8.5 
2 1/1/2017  A Anton Station1 1.0 
3 1/1/2017  B Jonas Station1 4.0 
4 1/1/2017  B  Greg Station1 7.5 
5 1/1/2017  B  Mick Station2 8.0 
6 1/1/2017  B Anton Station3 7.0 
7 1/1/2017  C Jonas Station4 2.0 
8 1/1/2017  C  Greg Station1 7.0 
+0

oui, cette fonction est très lente –