使用Pandas groupby连接来自多行的字符串


92

我想基于Pandas中的groupedby合并数据框中的几个字符串。

到目前为止,这是我的代码:

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并在“文本”列中应用某种形式的字符串连接。任何帮助表示赞赏!

Answers:


159

您可以对'name''month'列进行分组,然后调用transform,它将返回与原始df对齐的数据,并在我们join输入文本的位置应用lambda :

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[['name','text','month']]在此处传递感兴趣的列的列表来替换原始df ,然后调用drop_duplicates

编辑实际上我可以打电话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()
Matthias Fripp

整洁而简单。突出地也fleixible
拉加VMVS

drop_duplicates()可能无法正常工作,如果你不包括参数drop_duplicates(inplace=True)或只是重写代码行 df = df[['name','text','month']].drop_duplicates()
IAmBotmaker

44

我们可以GROUPBY的“名”和“月”列,然后调用AGG()熊猫的数据框对象的功能。

agg()函数提供的聚合功能允许在一次计算中为每个组计算多个统计信息。

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

在此处输入图片说明


27

EdChum的答案为您提供了很大的灵活性,但是如果您只想将字符串连接到列表对象的列中,则还可以:

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


伙计,您刚刚节省了我很多时间。谢谢。这是将注册/用户ID的时间顺序列表组合成我所知道的“同类群组”的最佳方法。再一次感谢你。
Alex Fedotov

5

对我来说,以上解决方案很接近,但添加了一些不必要的/ n和dtype:object,因此这是修改后的版本:

df.groupby(['name', 'month'])['text'].apply(lambda text: ''.join(text.to_string(index=False))).str.replace('(\\n)', '').reset_index()
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.