Concatenar cadenas de varias filas usando Pandas groupby

92

Quiero fusionar varias cadenas en un marco de datos basado en un grupo en Pandas.

Este es mi código hasta ahora:

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)

Quiero que el resultado final se vea así:

ingrese la descripción de la imagen aquí

No entiendo cómo puedo usar groupby y aplicar algún tipo de concatenación de las cadenas en la columna "texto". ¡Cualquier ayuda apreciada!

Mattiasostmar
fuente

Respuestas:

159

Puede agrupar por las columnas 'name'y 'month', luego llamar a transformlo que devolverá datos alineados con el df original y aplicar una lambda donde tenemos joinlas entradas de texto:

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

Subo el df original pasando una lista de las columnas de interés df[['name','text','month']]aquí y luego llamodrop_duplicates

EDITAR en realidad puedo llamar applyy luego 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

actualizar

el lambdaes innecesario aquí:

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
EdChum
fuente
1
En pandas < 1.0, .drop_duplicates()ignora el índice, que puede dar resultados inesperados. Puede evitar esto usando en .agg(lambda x: ','.join(x))lugar de .transform().drop_duplicates().
Matthias Fripp
Limpio y sin complicaciones. Eminentemente flexible también
Raghavan vmvs
drop_duplicates()podría no funcionar si no incluye el parámetro drop_duplicates(inplace=True)o simplemente reescribe la línea de código como df = df[['name','text','month']].drop_duplicates()
IAmBotmaker
44

podemos agrupar por las columnas 'nombre' y 'mes', luego llamar a las funciones agg () de los objetos DataFrame de Panda.

La funcionalidad de agregación proporcionada por la función agg () permite calcular múltiples estadísticas por grupo en un cálculo.

df.groupby(['name', 'month'], as_index = False).agg({'text': ' '.join})

ingrese la descripción de la imagen aquí

Ram Prajapati
fuente
27

La respuesta de EdChum le brinda mucha flexibilidad, pero si solo desea concatenar cadenas en una columna de objetos de lista, también puede:

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

Rutger Hofste
fuente
Hombre, me acabas de ahorrar mucho tiempo. Gracias. Esta es la mejor manera de reunir las listas cronológicas de registros / identificadores de usuario en 'cohortes' que conozco. Gracias otra vez.
Alex Fedotov
5

Para mí, las soluciones anteriores estaban cerca, pero agregaron algunos / n y dtype: object no deseados, así que aquí hay una versión modificada:

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