J'ai un dataframe pandas comme ci-dessous:
A B C1 C2 C 0 1 2 C1 C2 C1 0 1 2 C1 C2 C2 1 2 17 NaN C2 C2 2 3 17 NaN NaN NaN
Dataframe:
A B C1 C2 C 0 1 2 C1 C2 C1,C2 1 2 17 NaN C2 C2 2 3 17 NaN NaN NaN
Je crée une variable "C" basée sur le sous la logique et le code
Si l'un des C (C1, C2, C3 ..) a la valeur "C" = valeur de C (C1, C2, C3 ....).
df['C'] = df.filter(regex='C\d+').stack().groupby(level=0).agg(','.join)
Résultat :
A B C1 C2 0 1 2 C1 C2 1 2 17 NaN C2 2 3 17 NaN NaN
Maintenant, je veux exécuter la logique ci-dessous
Si "C" a plus de 1 valeurs (par exemple C1, C2) pour n'importe quelle ligne, créez une nouvelle ligne et ajoutez la 2ème valeur. Je veux donc que ma sortie ressemble à celle ci-dessous:
data = {'A' : [1,2,3],
'B' : [2,17,17],
'C1' : ["C1", np.nan,np.nan],
'C2' : ["C2", "C2",np.nan]}
# Create DataFrame
df = pd.DataFrame(data)
3 Réponses :
Nous pouvons le faire en utilisant exploser puis concat
s=df.filter(regex='C\d+').stack().groupby(level=0).agg(list).explode().to_frame('C').join(df)
s=pd.concat([s,df[~df.index.isin(s.index)]],axis=0,join='outer',ignore_index=True,sort=False)
s
Out[62]:
C A B C1 C2
0 C1 1 2 C1 C2
1 C2 1 2 C1 C2
2 C2 2 17 NaN C2
3 NaN 3 17 NaN NaN
J'obtiens une erreur AttributeError: l'objet 'Series' n'a pas d'attribut 'explode'
@ShanooS c'est après pandas 0.25, veuillez mettre à jour vos pandas
vous pouvez faire:
df.merge(df.melt(['A','B'],value_name= 'C').dropna().drop('variable',axis = 1),how = "left")
A B C1 C2 C
0 1 2 C1 C2 C1
1 1 2 C1 C2 C2
2 2 17 NaN C2 C2
3 3 17 NaN NaN NaN
Je ne veux pas spécifier ['A', 'B'], car le dataframe a environ 30 vars.
@Shanoo vous pouvez simplement remplacer ['A', 'B'] par df.columns [~ df.columns.str.match ('^ C')] ou même df.columns.str.extract ('^ ([^ C])', expand = False) .dropna ()
Ya je peux utiliser df.columns.str.extract ('^ ([^ C])', expand = False) .dropna ()
Mais cela ne fonctionne pas si nous avons une autre colonne qui commence par C, dites `` CFG ''
@Shanoo puis utilisez df.columns [~ df.columns.str.match ('^ C \\ d +')]
@Shanoo df.columns.str.extract ('^ ([^ C] \\ D *)', expand = False) .dropna () fonctionne également
Vous pouvez simplement df.explode (...) , essayer:
A B C1 C2 C 0 1 2 C1 C2 C1 0 1 2 C1 C2 C2 1 2 17 NaN C2 C2 2 3 17 NaN NaN NaN
Sorties:
#please note I aggregate it into list, not string
df['C'] = df.filter(regex='C\d+').stack().groupby(level=0).agg(list)
df=df.explode("C")
pourquoi la première ligne
C1?Parce qu'avant la valeur de C était C1, C2, maintenant je veux avoir une ligne pour chaque C1 et C2