Об’єднайте рядки з декількох рядків за допомогою Pandas groupby


92

Я хочу об'єднати кілька рядків у фреймі даних на основі згрупованого в Pandas.

Наразі це мій код:

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)

Я хочу, щоб кінцевий результат виглядав так:

введіть тут опис зображення

Я не розумію, як я можу використовувати groupby і застосувати якусь конкатенацію рядків у стовпці "текст". Будь-яка допомога оцінена!

Відповіді:


160

Ви можете згрупувати за стовпцями 'name'та 'month', а потім викликати, transformякий поверне дані, вирівняні за вихідним df, і застосує лямбда, де ми вводимо joinтекстові записи:

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

Я додаю оригінальний df, передаючи тут список колонок, що цікавлять, df[['name','text','month']]а потім викликаюdrop_duplicates

EDIT насправді я можу просто зателефонувати, applyа потім 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

оновлення

lambdaнепотрібно тут:

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

1
В pandas < 1.0, .drop_duplicates()ігнорує індекс, що може дати несподівані результати. Ви можете уникнути цього, використовуючи .agg(lambda x: ','.join(x))замість .transform().drop_duplicates().
Маттіас Фріпп,

Охайний і нескладний. Також надзвичайно гнучкий
Raghavan vmvs

drop_duplicates()може не працювати, якщо ви не включите параметр drop_duplicates(inplace=True)або просто перепишете рядок коду як df = df[['name','text','month']].drop_duplicates()
IAmBotmaker

44

ми можемо згрупувати за стовпцями "ім'я" та "місяць", а потім викликати функції agg () об'єктів DataFrame Panda.

Функціонал агрегування, наданий функцією agg (), дозволяє обчислювати кілька статистичних даних для кожної групи за один розрахунок.

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

введіть тут опис зображення


27

Відповідь EdChum надає вам велику гнучкість, але якщо ви просто хочете об'єднати рядки у стовпець об'єктів списку, ви також можете:

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


Чоловіче, ти щойно заощадив мені багато часу. Дякую. Це найкращий спосіб зібрати хронологічні списки реєстрацій / ідентифікаторів користувачів у "когорти", про які я знаю. Дякую ще раз.
Олексій Федотов

5

Для мене вищезазначені рішення були близькими, але додали небажані / n та dtype: object, тож ось модифікована версія:

df.groupby(['name', 'month'])['text'].apply(lambda text: ''.join(text.to_string(index=False))).str.replace('(\\n)', '').reset_index()
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.