1
votes

Manipuler une colonne dans pandas dataframe

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) 


2 commentaires

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


3 Réponses :


0
votes

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


2 commentaires

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



0
votes

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


6 commentaires

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



0
votes

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")


0 commentaires