Połącz ciągi z kilku wierszy przy użyciu Pandas Groupby

92

Chcę scalić kilka ciągów w ramce danych opartej na zgrupowaniu w Pandas.

To jest mój kod do tej pory:

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)

Chcę, żeby efekt końcowy wyglądał tak:

wprowadź opis obrazu tutaj

Nie rozumiem, jak mogę używać funkcji Groupby i zastosować jakieś połączenie ciągów w kolumnie „tekst”. Każda pomoc doceniona!

mattiasostmar
źródło

Odpowiedzi:

159

Możesz pogrupować kolumny 'name'i 'month', a następnie wywołać, transformco zwróci dane wyrównane do oryginalnego df i zastosuje lambdę, w której mamy joinwpisy tekstowe:

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

Podpisuję oryginalny df, przekazując tutaj listę interesujących kolumn df[['name','text','month']], a następnie wywołujędrop_duplicates

EDYTUJ właściwie mogę po prostu zadzwonić, applya następnie 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

aktualizacja

lambdajest niepotrzebna tutaj:

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
źródło
1
W pandas < 1.0, .drop_duplicates()ignoruje indeks, który może dać nieoczekiwane rezultaty. Możesz tego uniknąć, używając .agg(lambda x: ','.join(x))zamiast .transform().drop_duplicates().
Matthias Fripp
Schludny i nieskomplikowany. Eminently fleixible also
Raghavan vmvs
drop_duplicates()może nie działać, jeśli nie drop_duplicates(inplace=True)df = df[['name','text','month']].drop_duplicates()
dołączysz
44

możemy pogrupować według kolumn 'name' i 'month', a następnie wywołać funkcje agg () obiektów DataFrame Pandy.

Funkcja agregacji zapewniana przez funkcję agg () pozwala na obliczenie wielu statystyk na grupę w jednym obliczeniu.

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

wprowadź opis obrazu tutaj

Ram Prajapati
źródło
27

Odpowiedź EdChum zapewnia dużą elastyczność, ale jeśli chcesz po prostu połączyć ciągi znaków w kolumnę obiektów list, możesz również:

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

Rutger Hofste
źródło
Stary, właśnie zaoszczędziłeś mi dużo czasu. Dziękuję Ci. To najlepszy sposób na zestawienie chronologicznych list rejestracji / identyfikatorów użytkowników w znane mi „kohorty”. Dziękuję raz jeszcze.
Alex Fedotov
5

Dla mnie powyższe rozwiązania były bliskie, ale dodałem trochę niechcianych / n i dtype: obiekt, więc oto zmodyfikowana wersja:

df.groupby(['name', 'month'])['text'].apply(lambda text: ''.join(text.to_string(index=False))).str.replace('(\\n)', '').reset_index()
Nic Scozzaro
źródło