2 votes

En Python, comment faire un group by + mutate + ifelse comme en R?

Je utilise généralement R. Si j'ai des données comme :

Produit    Indice   Valeur
   a         1       0.5
   a         1       0.4
   c         1       1.4
   c         2       0.75
   e         2       0.6
   f         3       0.9

Si mon code R est :

a <- data %>%
  group_by(Produit) %>%
   mutate(Drapeau=ifelse(all(Indice==1),'correct','incorrect'))

Cela signifie que je regroupe les données par Produit d'abord. Ensuite, pour chaque groupe, je lui attribuerai un nouveau champ appelé Drapeau. Si l'indice dans ce groupe est entièrement de 1, alors le Drapeau est correct, sinon il est incorrect. En même temps, tous les enregistrements sont conservés. Donc, le résultat devrait ressembler à :

Produit    Indice   Valeur    Drapeau
   a         1       0.5    correct
   a         1       0.4    correct
   c         1       1.4    incorrect
   c         2       0.75   incorrect
   e         2       0.6    incorrect
   f         3       0.9    incorrect

Ma question est : comment faire les mêmes opérations en python ? J'ai essayé, np.where, groupby, transform et d'autres fonctions. Je les ai probablement combinées de la mauvaise manière.

Est-ce que quelqu'un pourrait m'aider ici, s'il vous plaît?

5voto

datapug Points 364

Utiliser transform est une option.

import pandas as pd

df = pd.DataFrame({'Produit': ['a', 'a', 'c', 'c', 'e', 'f'],
               'Index': [1, 1, 1, 2, 2, 3], 
              'Valeur': [0.5, 0.4, 1.4, 0.75, 0.6, 0.9]})
df['Drapeau'] = df.groupby('Produit')['Index'].transform(lambda x: 'juste' if sum(x)/len(x) == 1 else 'faux')
df

À noter que si les valeurs du Drapeau sont simplement 'juste' et 'faux', les remplacer par des valeurs 0,1 pourrait être plus efficace.

2voto

user3483203 Points 28606

Vous pouvez utiliser unique() et groupby() pour vous assurer que tous les produits ont un index de 1, puis mapper sur votre nouvelle colonne :

In [51]: df['Flag'] = df['Product'].map(df.groupby('Product')['Index'].unique().apply(lambda row: 'right' if all(row==[1]) else 'wrong'))

In [52]: df
Out[52]:
  Product  Index  Value   Flag
0       a      1   0.50  right
1       a      1   0.40  right
2       c      1   1.40  wrong
3       c      2   0.75  wrong
4       e      2   0.60  wrong
5       f      3   0.90  wrong

1voto

jezrael Points 290608

Utilisez GroupBy.transform avec mean, comparez avec 1 et utilisez numpy.where pour les valeurs selon la condition :

df['Flag'] = np.where(df.groupby('Product')['Index'].transform('mean')== 1, 'right', 'Wrong')
print (df)
  Product  Index  Value   Flag
0       a      1   0.50  right
1       a      1   0.40  right
2       c      1   1.40  Wrong
3       c      2   0.75  Wrong
4       e      2   0.60  Wrong
5       f      3   0.90  Wrong

Détail:

print (df.groupby('Product')['Index'].transform('mean'))
0    1.0
1    1.0
2    1.5
3    1.5
4    2.0
5    3.0
Name: Index, dtype: float64

Une autre solution :

Comparez d'abord avec 1 avec eq puis utilisez GroupBy.transform avec all pour vérifier si tous les True par groupe et numpy.where pour les valeurs selon la condition :

df['Flag'] = np.where(df['Index'].eq(1).groupby(df['Product']).transform('all'), 
                      'right', 'Wrong')
print (df)
  Product  Index  Value   Flag
0       a      1   0.50  right
1       a      1   0.40  right
2       c      1   1.40  Wrong
3       c      2   0.75  Wrong
4       e      2   0.60  Wrong
5       f      3   0.90  Wrong

Détail:

print (df['Index'].eq(1).groupby(df['Product']).transform('all'))
0     True
1     True
2    False
3    False
4    False
5    False
Name: Index, dtype: bool

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X