Menggabungkan string dari beberapa baris menggunakan Pandas groupby

92

Saya ingin menggabungkan beberapa string dalam dataframe berdasarkan groupedby in Pandas.

Ini adalah kode saya sejauh ini:

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)

Saya ingin hasil akhirnya terlihat seperti ini:

masukkan deskripsi gambar di sini

Saya tidak mengerti bagaimana saya bisa menggunakan groupby dan menerapkan semacam penggabungan string di kolom "teks". Setiap bantuan dihargai!

mattiasostmar
sumber

Jawaban:

160

Anda dapat mengelompokkan berdasarkan kolom 'name'dan 'month', lalu memanggil transformyang akan mengembalikan data yang selaras dengan df asli dan menerapkan lambda di mana kita joinmemasukkan teks:

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

Saya sub df asli dengan melewatkan daftar kolom yang menarik di df[['name','text','month']]sini dan kemudian memanggildrop_duplicates

EDIT sebenarnya saya bisa menelepon applydan kemudian 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

memperbarui

yang lambdatidak perlu di sini:

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
sumber
1
Dalam pandas < 1.0, .drop_duplicates()mengabaikan indeks, yang mungkin memberikan hasil yang tidak diharapkan. Anda dapat menghindari ini dengan menggunakan .agg(lambda x: ','.join(x))sebagai pengganti .transform().drop_duplicates().
Matthias Fripp
Rapi dan tidak rumit. Sangat mudah diubah juga
Raghavan vmvs
drop_duplicates()mungkin tidak berfungsi jika Anda tidak menyertakan parameter drop_duplicates(inplace=True)atau hanya menulis ulang baris kode sebagai df = df[['name','text','month']].drop_duplicates()
IAmBotmaker
44

kita bisa mengelompokkan berdasarkan kolom 'nama' dan 'bulan', lalu memanggil fungsi agg () dari objek DataFrame Panda.

Fungsionalitas agregasi yang disediakan oleh fungsi agg () memungkinkan beberapa statistik dihitung per grup dalam satu penghitungan.

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

masukkan deskripsi gambar di sini

Ram Prajapati
sumber
27

Jawaban oleh EdChum memberi Anda banyak fleksibilitas, tetapi jika Anda hanya ingin menggabungkan string ke dalam kolom objek daftar, Anda juga dapat:

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

Rutger Hofste
sumber
Sobat, kamu baru saja menghemat banyak waktu. Terima kasih. Ini adalah cara terbaik untuk menyusun daftar kronologis pendaftaran / id pengguna menjadi 'kelompok' yang saya ketahui. Terima kasih sekali lagi.
Alex Fedotov
5

Bagi saya solusi di atas sudah dekat tetapi menambahkan beberapa / n yang tidak diinginkan dan dtype: object, jadi inilah versi yang dimodifikasi:

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