3 votes

Étant donné la même valeur dans une colonne, concaténer les lignes restantes ?

Étant donné le DataFrame pandas :

name   hobby   since
paul   A       1995 
john   A       2005 
paul   B       2015
mary   G       2013
chris  E       2005
chris  D       2001
paul   C       1986

J'aimerais obtenir :

name   hobby1   since1    hobby2   since2    hobby3   since3
paul   A        1995      B        2015      C        1986 
john   A        2005      NaN      NaN       NaN      NaN
mary   G        2013      NaN      NaN       NaN      NaN
chris  E        2005      D        2001      NaN      NaN

Par exemple, j'aimerais avoir une ligne par nom. Je connais à l'avance le nombre maximum de loisirs qu'une personne peut avoir, disons 3 dans ce cas. Quelle serait la façon la plus élégante et la plus courte de procéder ?

3voto

anky_91 Points 26311

Vous pouvez d'abord melt et ensuite , groupby.cumcount() à ajouter à la variable puis pivoter en utilisant pivot_table() :

m=df.melt('name')
(m.assign(variable=m.variable+(m.groupby(['name','variable']).cumcount()+1).astype(str))
 .pivot_table(index='name',columns='variable',values='value',aggfunc='first')
.rename_axis(None,axis=1))

      hobby1 hobby2 hobby3 since1 since2 since3
name                                           
chris      E      D    NaN   2005   2001    NaN
john       A    NaN    NaN   2005    NaN    NaN
mary       G    NaN    NaN   2013    NaN    NaN
paul       A      B      C   1995   2015   1986

2voto

Andy L. Points 11730

Utilisation cumcount y unstack . Enfin, utilisez multiindex.map pour relier des colonnes à 2 niveaux à un niveau

df1 = df.set_index(['name', df.groupby('name').cumcount().add(1)]) \
        .unstack().sort_index(1,level=1)

df1.columns = df1.columns.map('{0[0]}{0[1]}'.format)

Out[812]:
      hobby1  since1 hobby2  since2 hobby3  since3
name
chris      E  2005.0      D  2001.0    NaN     NaN
john       A  2005.0    NaN     NaN    NaN     NaN
mary       G  2013.0    NaN     NaN    NaN     NaN
paul       A  1995.0      B  2015.0      C  1986.0

1voto

Nakor Points 1426

Peut-être quelque chose comme ça ? Mais vous devrez renommer les colonnes après cette solution.

df["combined"] = [ "{}_{}".format(x,y) for x,y in zip(df.hobby,df.since)]
df.groupby("name")["combined"]
  .agg(lambda x: "_".join(x))
  .str.split("_",expand=True)

Le résultat est le suivant :

       0     1     2     3     4     5
name
chris  E  2005     D  2001  None  None
john   A  2005  None  None  None  None
mary   G  2013  None  None  None  None
paul   A  1995     B  2015     C  1986

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