web-dev-qa-db-fra.com

Concaténer des chaînes de plusieurs lignes en utilisant Pandas groupby

Je veux fusionner plusieurs chaînes dans une trame de données basée sur un groupé par dans Pandas.

Voici mon code jusqu'à présent:

import pandas as pd
from io import StringIO

data = StringIO("""
"name1","hej","2014-11-01"
"name1","du","2014-11-02"
"name1","aj","2014-12-01"
"name1","oj","2014-12-02"
"name2","fin","2014-11-01"
"name2","katt","2014-11-02"
"name2","mycket","2014-12-01"
"name2","lite","2014-12-01"
""")

# load string as stream into dataframe
df = pd.read_csv(data,header=0, names=["name","text","date"],parse_dates=[2])

# add column with month
df["month"] = df["date"].apply(lambda x: x.month)

Je veux que le résultat final ressemble à ceci:

enter image description here

Je ne sais pas comment utiliser groupby et appliquer une sorte de concaténation des chaînes dans la colonne "texte". Toute aide appréciée!

29
mattiasostmar

Vous pouvez grouper par 'name' et 'month' colonnes, puis appelez transform qui renverra des données alignées sur le df d'origine et appliquera un lambda où nous join les entrées de texte:

In [119]:

df['text'] = df[['name','text','month']].groupby(['name','month'])['text'].transform(lambda x: ','.join(x))
df[['name','text','month']].drop_duplicates()
Out[119]:
    name         text  month
0  name1       hej,du     11
2  name1        aj,oj     12
4  name2     fin,katt     11
6  name2  mycket,lite     12

Je soumets le df d'origine en passant une liste des colonnes d'intérêt df[['name','text','month']] ici puis appelez drop_duplicates

MODIFIER en fait, je peux simplement appeler apply puis reset_index:

In [124]:

df.groupby(['name','month'])['text'].apply(lambda x: ','.join(x)).reset_index()

Out[124]:
    name  month         text
0  name1     11       hej,du
1  name1     12        aj,oj
2  name2     11     fin,katt
3  name2     12  mycket,lite

mise à jour

le lambda n'est pas nécessaire ici:

In[38]:
df.groupby(['name','month'])['text'].apply(','.join).reset_index()

Out[38]: 
    name  month         text
0  name1     11           du
1  name1     12        aj,oj
2  name2     11     fin,katt
3  name2     12  mycket,lite
54
EdChum

La réponse d'EdChum vous offre beaucoup de flexibilité, mais si vous souhaitez simplement concaténer des chaînes dans une colonne d'objets de liste, vous pouvez également:

output_series = df.groupby(['name','month'])['text'].apply(list)

6
Rutger Hofste

Pour moi, les solutions ci-dessus étaient proches mais ont ajouté des/n et un dtype: object indésirables, voici donc une version modifiée:

df.groupby(['name', 'month'])['text'].apply(lambda text: ''.join(text.to_string(index=False))).str.replace('(\\n)', '').reset_index()
1
Nic Scozzaro