2 votes

diviser une chaîne de caractères en colonnes séparées dans pandas

J'ai un cadre de données avec beaucoup de données et une colonne qui est structurée comme ceci :

index    var_1
1        a=3:b=4:c=5:d=6:e=3
2        b=3:a=4:c=5:d=6:e=3
3        e=3:a=4:c=5:d=6
4        c=3:a=4:b=5:d=6:f=3

J'essaie de structurer les données de cette colonne pour qu'elles ressemblent à ceci :

index    a   b   c   d   e   f
1        3   4   5   6   3   0
2        4   3   5   6   3   0
3        4   0   5   6   3   0
4        4   5   3   6   0   3

J'ai fait ce qui suit jusqu'à présent :

df1 = df['var1'].str.split(':', expand=True)

Je peux ensuite parcourir en boucle les colonnes de df1 et faire une autre division sur '=', mais je n'aurai alors qu'une multitude de colonnes d'étiquettes et de colonnes de valeurs désorganisées.

3voto

jezrael Points 290608

Utiliser la compréhension de liste avec des dictionnaires pour chaque valeur et passer à DataFrame constructeur :

comp = [dict([y.split('=') for y in x.split(':')]) for x in df['var_1']]
df = pd.DataFrame(comp).fillna(0).astype(int)
print (df)
   a  b  c  d  e  f
0  3  4  5  6  3  0
1  4  3  5  6  3  0
2  4  0  5  6  3  0
3  4  5  3  6  0  3

Ou utilisez Series.str.split con expand=True pour DataFrame , remodeler par DataFrame.stack Encore une fois, divisez, enlevez le premier niveau de MultiIndex et ajouter un nouveau niveau par 0 colonne, dernier remodelage par Series.unstack :

df = (df['var_1'].str.split(':', expand=True)
                 .stack()
                 .str.split('=', expand=True)
                 .reset_index(level=1, drop=True)
                 .set_index(0, append=True)[1]
                 .unstack(fill_value=0)
                 .rename_axis(None, axis=1))
print (df)
   a  b  c  d  e  f
1  3  4  5  6  3  0
2  4  3  5  6  3  0
3  4  0  5  6  3  0
4  4  5  3  6  0  3

1voto

yatu Points 39897

Voici une approche utilisant str.get_dummies :

out = df.var_1.str.get_dummies(sep=':')
out = out * out.columns.str[2:].astype(int).values
out.columns = pd.MultiIndex.from_arrays([out.columns.str[0], out.columns])

print(out.max(axis=1, level=0))

       a  b  c  d  e  f
index                  
1      3  4  5  6  3  0
2      4  3  5  6  3  0
3      4  0  5  6  3  0
4      4  5  3  6  0  3

0voto

kantal Points 1791

Vous pouvez appliquer "extractall" et "pivot".
Après "extractall", on obtient :

             0  1
index match      
1     0      a  3
      1      b  4
      2      c  5
      3      d  6
      4      e  3
2     0      b  3
      1      a  4
      2      c  5
      3      d  6
      4      e  3
3     0      e  3
      1      a  4
      2      c  5
      3      d  6
4     0      c  3
      1      a  4
      2      b  5
      3      d  6
      4      f  3

Et en une seule étape :

rslt= df.var_1.str.extractall(r"([a-z])=(\d+)") \
                .reset_index(level="match",drop=True) \
                .pivot(columns=0).fillna(0)                     

         1               
    0      a  b  c  d  e  f
    index                  
    1      3  4  5  6  3  0
    2      4  3  5  6  3  0
    3      4  0  5  6  3  0
    4      4  5  3  6  0  3

#rslt.columns= rslt.columns.levels[1].values

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