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

Concatenate strings from several rows using Pandas groupby

提问人:mattiasostmar 提问时间:12/4/2014 最后编辑:cottontailmattiasostmar 更新时间:11/2/2023 访问量:322854

问:

我想使用 groupby 在列中应用某种字符串串联。

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

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)

我希望最终结果如下所示:

enter image description here

python-3.x pandas group-by

评论


答:

343赞 EdChum 12/4/2014 #1

您可以按 和 列分组,然后调用 这将返回与原始 df 对齐的数据,并在文本条目中应用 lambda:'name''month'transformjoin

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

编辑实际上我可以打电话,然后:applyreset_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

评论

6赞 Matthias Fripp 5/30/2020
in 中,忽略索引,这可能会产生意外的结果。您可以通过使用 而不是 来避免这种情况。pandas < 1.0.drop_duplicates().agg(lambda x: ','.join(x)).transform().drop_duplicates()
0赞 Raghavan vmvs 9/8/2020
整洁而简单。也非常灵活
0赞 IAmBotmaker 9/23/2020
drop_duplicates()如果您不包含参数或只是将代码行重写为drop_duplicates(inplace=True)df = df[['name','text','month']].drop_duplicates()
0赞 Thomas 8/4/2021
如何确保第一列中的文本实际上是“hej du”而不是“du hej”?某处有隐含的排序吗?我怎样才能明确这一点,例如按日期列排序?
1赞 constantstranger 3/20/2022
为什么在“更新”部分中“hej,du”更改为“du”?
62赞 Rutger Hofste 8/29/2017 #2

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

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

评论

4赞 Alex Fedotov 6/28/2020
伙计,你刚刚为我节省了很多时间。谢谢。这是将按时间顺序排列的注册/用户 ID 列表组合成我所知道的“队列”的最佳方式。再次感谢你。
0赞 whydoesntwork 4/11/2022
这个解决方案对我来说也非常有效,可以获得独特的外观。我只是使用“set”而不是“list”,然后菊花链连接和presto。请注意,如果有 nan 值,它不起作用,所以我不得不先在文本字段上使用 fillna()。在我的情况下,命令结束了:df.groupby(['doc_id'])['author'].apply(set).apply(“, ”.join).reset_index()
0赞 Bill 4/12/2022
我不认为这会在字符串之间增加空格,是吗?
13赞 Nic Scozzaro 6/28/2018 #3

对我来说,上述解决方案很接近,但添加了一些不需要的,所以这里有一个修改后的版本:/n'sdtype:object

df.groupby(['name', 'month'])['text'].apply(lambda text: ''.join(text.to_string(index=False))).str.replace('(\\n)', '').reset_index()
138赞 Ram Prajapati 12/11/2019 #4

我们可以对 'name' 和 'month' 列进行分组然后调用 Panda 的 DataFrame 对象的 agg() 函数。

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

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

enter image description here

评论

1赞 kağan hazal koçdemir 9/15/2021
嗨,使用 AGG 函数删除重复项的任何想法?
10赞 Nicolas78 9/28/2021
@kağanhazalkoçdemiragg({'text': lambda x: ' '.join(set(x))})
1赞 Andrew 7/22/2022
在“text”列中允许 NULL 的情况下,如何使用此方法?
0赞 Andrew 7/22/2022
f = lambda x: func(x, *args, **kwargs) TypeError: sequence item 45: expected str instance, NoneType found数据库中的 NULL 或 None 值
1赞 fantabolous 9/13/2022
这还允许您保留其他列,例如通过添加到字典中, 'othercol': 'last'agg
17赞 Ismail 11/25/2020 #5

如果要在列表中连接“文本”:

df.groupby(['name', 'month'], as_index = False).agg({'text': list})
3赞 MMSA 3/30/2021 #6

虽然,这是一个老问题。但以防万一。我使用了下面的代码,它似乎像一个魅力一样工作。

text = ''.join(df[df['date'].dt.month==8]['text'])
6赞 Ashish Anand 10/28/2021 #7

请试试这行代码: -

df.groupby(['name','month'])['text'].apply(','.join).reset_index()
1赞 Paul Rougieux 12/1/2022 #8

多亏了所有其他答案,以下可能是最简洁的,感觉更自然。在一个或多个选定列上使用聚合。df.groupby("X")["A"].agg()

df = pandas.DataFrame({'A' : ['a', 'a', 'b', 'c', 'c'],
                       'B' : ['i', 'j', 'k', 'i', 'j'],
                       'X' : [1, 2, 2, 1, 3]})

  A  B  X
  a  i  1
  a  j  2
  b  k  2
  c  i  1
  c  j  3

df.groupby("X", as_index=False)["A"].agg(' '.join)

  X    A
  1  a c
  2  a b
  3    c

df.groupby("X", as_index=False)[["A", "B"]].agg(' '.join)

  X    A    B
  1  a c  i i
  2  a b  j k
  3    c    j