J'ai du mal à savoir comment obtenir transform ()
pour renvoyer le résultat souhaité. Je voudrais vérifier si dans chaque groupe si "manqué" est unique dans un groupe donné.
Tenez compte de ce qui suit:
a = ['correct', 'incorrect'] m = ['missed'] df['only_missed'] = df.groupby('key')['type'].transform(lambda x: 'no' if all(x.isin(a)) else ('yes' if all(x.isin(m)) else 'pass')) df key type only_missed 0 1 correct no 1 1 incorrect no 2 2 missed pass 3 2 incorrect pass 4 3 missed yes 5 3 missed yes 6 2 correct pass 7 4 pass pass
J'essaie d'obtenir l'original dataframe pour ressembler à ceci. Où only_missed
est oui
si manqué
est le seul type du groupe.
key type only_missed 0 1 correct no 1 1 incorrect no 2 2 missed no 3 2 incorrect no 4 3 missed yes 5 3 missed yes 6 2 correct no 7 4 pass pass
J'ai essayé ceci mais le résultat est inattendu:
df = pd.DataFrame({'key': [1, 1, 2, 2, 3, 3, 2, 4], 'type': ['correct', 'incorrect', 'missed', 'incorrect', 'missed', 'missed', 'correct', 'pass']}) df key type 0 1 correct 1 1 incorrect 2 2 missed 3 2 incorrect 4 3 missed 5 3 missed 6 2 correct 7 4 pass
Celui-ci m'a vraiment déconcerté car j'ai parcouru plusieurs itérations ici pour essayer de comprendre ce qui se passe. p>
L'aide est grandement appréciée.
3 Réponses :
Essayez :
key type only_misses 0 1 correct No 1 1 incorrect No 2 2 missed No 3 2 incorrect No 4 3 missed Yes 5 3 missed Yes 6 2 correct No 7 4 pass pass
Output:
df['only_misses'] = df.groupby('key')['type']\ .transform(lambda x: (x.nunique() == 1) & (x.iloc[0] == 'missed'))\ .replace({False:'No',True:'Yes'})\ .mask(df.type == 'pass','pass') df
Et, vous pouvez masquer le 'pass':
0 No 1 No 2 No 3 No 4 Yes 5 Yes 6 No 7 pass Name: type, dtype: object
Résultat:
df.groupby('key')['type']\ .transform(lambda x: (x.nunique() == 1) & (x.iloc[0] == 'missed'))\ .replace({False:'No',True:'Yes'})\ .mask(df.type == 'pass','pass')
Et, remplacez True / False par oui / non:
0 False 1 False 2 False 3 False 4 True 5 True 6 False 7 pass Name: type, dtype: object
Sortie:
df.groupby('key')['type']\ .transform(lambda x: (x.nunique() == 1) & (x.iloc[0] == 'missed'))\ .mask(df.type == 'pass','pass')
Attribuer à la colonne dataframe:
0 False 1 False 2 False 3 False 4 True 5 True 6 False 7 False Name: type, dtype: bool
Sortie:
df.groupby('key')['type'].transform(lambda x: (x.nunique() == 1) & (x.iloc[0] == 'missed'))
df.groupby('key')['type'].transform( lambda x: 'yes' if (x == 'missed').all() else ('pass' if (x == 'pass').all() else 'no') )
Cela a fait l'affaire. J'étais à l'envers sur la logique et je n'ai pas utilisé correctement a.all ()
. Idem pour ce que @RamGhadiyaram a dit - je ne sais pas pourquoi ce n'était pas directement évident pour moi. Merci!
Une façon est d'utiliser des booléens et de les additionner pour créer un catégoriel:
In [21]: p = pd.Series((df.type == 'pass').values, df.key).groupby(level=0).transform('all') In [22]: pd.Categorical.from_codes(m + 2 * p, ['no', 'yes', 'pass']) Out[22]: [no, no, no, no, yes, yes, no, pass] Categories (3, object): [no, yes, pass] In [23]: df['only_missed'] = pd.Categorical.from_codes(m + 2 * p, ['no', 'yes', 'pass']) In [24]: df Out[24]: key type only_missed 0 1 correct no 1 1 incorrect no 2 2 missed no 3 2 incorrect no 4 3 missed yes 5 3 missed yes 6 2 correct no 7 4 pass pass
Cela semble un petit piratage avec le .values code> (pour éviter la réindexation) mais devrait être assez efficace ...
En regardant à nouveau, c'était la sortie "incorrecte", mais je vais le laisser là car c'est essentiellement le même. Afin d'obtenir le bon, vous devriez regarder tous les "pass":
In [11]: a = pd.Series(df.type.str.match('correct|incorrect').values, df.key).groupby(level=0).transform('all') In [12]: m = pd.Series((df.type == 'missed').values, df.key).groupby(level=0).transform('all') In [13]: pd.Categorical.from_codes(a + 2 * m, ['pass', 'no', 'yes']) Out[13]: [no, no, pass, pass, yes, yes, pass, pass] Categories (3, object): [pass, no, yes] In [14]: df["only_missed"] = pd.Categorical.from_codes(a + 2 * m, ['pass', 'no', 'yes']) In [15]: df Out[15]: key type only_missed 0 1 correct no 1 1 incorrect no 2 2 missed pass 3 2 incorrect pass 4 3 missed yes 5 3 missed yes 6 2 correct pass 7 4 pass pass
Je suppose que je suis confus. Quel est votre résultat attendu? Le dataframe avec 1 "pass" ou le dataframe avec 4 "pass"?