Concatenar strings de várias linhas usando o grupo Pandas

100

Eu quero mesclar várias strings em um dataframe baseado em um agrupado no Pandas.

Este é o meu código até agora:

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)

Eu quero que o resultado final seja assim:

insira a descrição da imagem aqui

Não entendo como posso usar o groupby e aplicar algum tipo de concatenação das strings na coluna "texto". Qualquer ajuda apreciada!

Mattiasostmar
fonte

Respostas:

178

Você pode agrupar as colunas 'name'e 'month', em seguida, chamar transformque retornará os dados alinhados ao df original e aplicar um lambda onde colocamos joinas 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

Eu submeto o df original passando uma lista das colunas de interesse df[['name','text','month']]aqui e depois ligodrop_duplicates

EDIT, na verdade, posso apenas ligar applye então 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

atualizar

o lambdaé desnecessário aqui:

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
fonte
1
Em pandas < 1.0, .drop_duplicates()ignora o índice, o que pode gerar resultados inesperados. Você pode evitar isso usando em .agg(lambda x: ','.join(x))vez de .transform().drop_duplicates().
Matthias Fripp
Limpo e descomplicado. Eminentemente flexível também
Raghavan vmvs
drop_duplicates()pode não funcionar se você não incluir o parâmetro drop_duplicates(inplace=True)ou apenas reescrever a linha de código como df = df[['name','text','month']].drop_duplicates()
IAmBotmaker
49

podemos agrupar as colunas 'nome' e 'mês' e, em seguida , chamar as funções agg () dos objetos DataFrame do Panda.

A funcionalidade de agregação fornecida pela função agg () permite que várias estatísticas sejam calculadas por grupo em um cálculo.

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

insira a descrição da imagem aqui

Ram Prajapati
fonte
28

A resposta do EdChum fornece muita flexibilidade, mas se você quiser apenas concatear strings em uma coluna de objetos de lista, você também pode:

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

Rutger Hofste
fonte
Cara, você acabou de me economizar muito tempo. Obrigado. Esta é a melhor maneira de reunir as listas cronológicas de registros / IDs de usuário em 'coortes' que eu conheço. Agradeço novamente.
Alex Fedotov
6

Para mim, as soluções acima foram próximas, mas adicionaram alguns / n's e dtype: object indesejados, então aqui está uma versão modificada:

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

Se você deseja concatenar seu "texto" em uma lista:

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