2017-08-14 1 views
3

J'ai cherché SO et n'ai pas encore compris. En espérant que quelqu'un puisse aider ce python newb à résoudre mon problème.Pandas si/alors l'agrégation

J'essaie de comprendre comment écrire une instruction if/then en python et effectuer une agrégation de cette instruction if/then. Mon objectif final est de dire si la date = 1/7/2017 puis d'utiliser la valeur dans la colonne "faux". Si date = tout le reste, alors faites la moyenne des deux colonnes ensemble.

Voici ce que j'ai jusqu'à présent:

import pandas as pd 
import numpy as np 
import datetime 

np.random.seed(42) 
dte=pd.date_range(start=datetime.date(2017,1,1), end= datetime.date(2017,1,15)) 
fake=np.random.randint(15,100, size=15) 
fake2=np.random.randint(300,1000,size=15) 

so_df=pd.DataFrame({'date':dte, 
      'fake':fake, 
      'fake2':fake2}) 

so_df['avg']= so_df[['fake','fake2']].mean(axis=1) 
so_df.head() 

Répondre

2

En supposant que vous avez déjà calculé la colonne moyenne:

so_df['fake'].where(so_df['date']=='20170107', so_df['avg']) 
Out: 
0  375.5 
1  260.0 
2  331.0 
3  267.5 
4  397.0 
5  355.0 
6  89.0 
7  320.5 
8  449.0 
9  395.5 
10 197.0 
11 438.5 
12 498.5 
13 409.5 
14 525.5 
Name: fake, dtype: float64 

Sinon, vous pouvez remplacer la référence de la colonne avec le même calcul:

so_df['fake'].where(so_df['date']=='20170107', so_df[['fake','fake2']].mean(axis=1)) 

Pour vérifier plusieurs dates, vous devez utiliser la version élémentaire de l'opérateur or (qui est pipe: |). Sinon, cela provoquera une erreur.

so_df['fake'].where((so_df['date']=='20170107') | (so_df['date']=='20170109'), so_df['avg']) 

La vérification ci-dessus porte sur deux dates. Dans le cas de 3 ou plus, vous pouvez utiliser isin une liste:

so_df['fake'].where(so_df['date'].isin(['20170107', '20170109', '20170112']), so_df['avg']) 
Out[42]: 
0  375.5 
1  260.0 
2  331.0 
3  267.5 
4  397.0 
5  355.0 
6  89.0 
7  320.5 
8  38.0 
9  395.5 
10 197.0 
11  67.0 
12 498.5 
13 409.5 
14 525.5 
Name: fake, dtype: float64 
+0

Merci! Ce sont tous deux super utiles. Si je voulais faire plus de 1 date à savoir 1/7,1/9 et 1/11 je pourrais simplement l'écrire comme 'so_df ['faux']. Où ((so_df ['date'] == '20170107 ') ou (so_df [' date '] ==' 20170105 ') ou (so_df [' date '] ==' 20170111 '), so_df [[' faux ',' fake2 ']]. mean (axe = 1)) ' –

+0

@ P.Cummings Malheureusement, vous ne pouvez pas utiliser' ou' pour les structures de données pandas. Vous devez utiliser la version surchargée de bitwise ou ('|'). J'ai ajouté quelques exemples au poste. – ayhan

+1

Merci. C'est très utile! –

1

Utilisons np.where:

so_df['avg'] = np.where(so_df['date'] == pd.to_datetime('2017-01-07'), 
         so_df['fake'], so_df[['fake', 
         'fake2']].mean(1)) 

Sortie:

  date fake fake2 avg 
0 2017-01-01 66 685 375.5 
1 2017-01-02 29 491 260.0 
2 2017-01-03 86 576 331.0 
3 2017-01-04 75 460 267.5 
4 2017-01-05 35 759 397.0 
5 2017-01-06 97 613 355.0 
6 2017-01-07 89 321 89.0 
7 2017-01-08 89 552 320.5 
8 2017-01-09 38 860 449.0 
9 2017-01-10 17 774 395.5 
10 2017-01-11 36 358 197.0 
11 2017-01-12 67 810 438.5 
12 2017-01-13 16 981 498.5 
13 2017-01-14 44 775 409.5 
14 2017-01-15 52 999 525.5 
1

Une façon de faire si-else en pandas géants est par en utilisant np.where Il y a trois valeurs à l'intérieur, condition, si et sinon

so_df['avg']= np.where(so_df['date'] == '2017-01-07',so_df['fake'],so_df[['fake','fake2']].mean(axis=1)) 

    date  fake fake2 avg 
0 2017-01-01 66  685 375.5 
1 2017-01-02 29  491 260.0 
2 2017-01-03 86  576 331.0 
3 2017-01-04 75  460 267.5 
4 2017-01-05 35  759 397.0 
5 2017-01-06 97  613 355.0 
6 2017-01-07 89  321 89.0 
7 2017-01-08 89  552 320.5 
8 2017-01-09 38  860 449.0 
9 2017-01-10 17  774 395.5 
10 2017-01-11 36  358 197.0 
11 2017-01-12 67  810 438.5 
12 2017-01-13 16  981 498.5 
13 2017-01-14 44  775 409.5 
14 2017-01-15 52  999 525.5 
0

nous pouvons également utiliser la méthode Series.where():

In [141]: so_df['avg'] = so_df['fake'] \ 
    ...:     .where(so_df['date'].isin(['2017-01-07','2017-01-09'])) 
    ...:     .fillna(so_df[['fake','fake2']].mean(1)) 
    ...: 

In [142]: so_df 
Out[142]: 
     date fake fake2 avg 
0 2017-01-01 66 685 375.5 
1 2017-01-02 29 491 260.0 
2 2017-01-03 86 576 331.0 
3 2017-01-04 75 460 267.5 
4 2017-01-05 35 759 397.0 
5 2017-01-06 97 613 355.0 
6 2017-01-07 89 321 89.0 
7 2017-01-08 89 552 320.5 
8 2017-01-09 38 860 38.0 
9 2017-01-10 17 774 395.5 
10 2017-01-11 36 358 197.0 
11 2017-01-12 67 810 438.5 
12 2017-01-13 16 981 498.5 
13 2017-01-14 44 775 409.5 
14 2017-01-15 52 999 525.5