如何使用 itertools 提取 groupby 值?
Posted
技术标签:
【中文标题】如何使用 itertools 提取 groupby 值?【英文标题】:How to use itertools to extract groupby values? 【发布时间】:2019-07-24 02:40:07 【问题描述】:data = [[12345,"AAA"],[12345,"BBB"],[12345,"CCC"],[98765,"KKK"],[98765,"MMM"],[56321,"JJJ"],[56321,"SSS"],[56321,"PPP"]]
df = pd.DataFrame(data,columns=['Sales_ID','Company_Name'])
大家好,我有上面的数据框,我想在每个 groupby Sales_ID 中创建一个匹配项。我如何在 python 中做到这一点?
我尝试按 df 分组并提取每个 sales_ID 的所有公司,但不知道下一步该怎么做。
df.groupby('Sales_ID').apply(lambda x:x['Company_Name'].tolist())
预期结果:
Sales_ID Company Company
12345 AAA BBB
12345 AAA CCC
12345 BBB CCC
98765 KKK MMM
56321 JJJ SSS
56321 JJJ PPP
56321 SSS PPP
感谢您的帮助。
【问题讨论】:
【参考方案1】:我正在使用itertools
s=df.groupby('Sales_ID',sort=False)['Company_Name'].apply(list)
l=[list(itertools.combinations(x,2)) for x in s]
Newdf=pd.DataFrame('Sales_ID':s.index.repeat(list(map(len,l))))
Newdf=pd.concat([Newdf,pd.DataFrame(sum(l,[]))],axis=1)
Newdf
Sales_ID 0 1
0 12345 AAA BBB
1 12345 AAA CCC
2 12345 BBB CCC
3 98765 KKK MMM
4 56321 JJJ SSS
5 56321 JJJ PPP
6 56321 SSS PPP
【讨论】:
【参考方案2】:编辑:@brentertainer 指出笛卡尔积后跟<
查询是您删除自合并和重复项所需的全部内容,而不管顺序如何。
df.merge(df, on='Sales_ID').query('Company_Name_x < Company_Name_y')
原始的、更复杂的解决方案排序以删除重复项,而与排序无关
import pandas as pd
import numpy as np
res = df.merge(df, on='Sales_ID').query('Company_Name_x != Company_Name_y')
cols = ['Company_Name_x', 'Company_Name_y']
res[cols] = np.sort(res[cols].to_numpy(), axis=1)
res = res.drop_duplicates()
输出:
Sales_ID Company_Name_x Company_Name_y
1 12345 AAA BBB
2 12345 AAA CCC
5 12345 BBB CCC
10 98765 KKK MMM
14 56321 JJJ SSS
15 56321 JJJ PPP
18 56321 PPP SSS
【讨论】:
我今天通过.query()
学到了一些东西。在我看来,您可以通过将查询条件从 !=
更改为 <
来使其成为一条线,对吧?
@brentertainer 是的,这是一个非常聪明的方法。【参考方案3】:
并不总是需要使用pandas
*。我更喜欢使用toolz
或funcy
来完成工作(在屏幕后面使用itertools
和其他python 原生模块和方法)
import itertools
import toolz # pip install toolz
import toolz.curried as tc
from operator import itemgetter
grouped_data = toolz.groupby(itemgetter(0), data)
12345: [[12345, 'AAA'], [12345, 'BBB'], [12345, 'CCC']],
98765: [[98765, 'KKK'], [98765, 'MMM']],
56321: [[56321, 'JJJ'], [56321, 'SSS'], [56321, 'PPP']]
现在要获取您想要的数据,您需要执行一系列步骤:
result = toolz.thread_first(data, # thread first pipes the data through series of functions
tc.groupby(itemgetter(0)), # group by first element
tc.valmap(tc.map(itemgetter(1))), # for each group extract the second element from a list of lists
tc.valmap(tc.partial(itertools.combinations, r=2)), # for each group make pairs
tc.valmap(list)) # this statement creates a list from the combinations generator function (it is howver not nescessary.)
结果:
12345: [('AAA', 'BBB'), ('AAA', 'CCC'), ('BBB', 'CCC')],
98765: [('KKK', 'MMM')],
56321: [('JJJ', 'SSS'), ('JJJ', 'PPP'), ('SSS', 'PPP')]
如果你想把它装帧成熊猫,你可以。否则,如果这是您所寻求的,您可以继续使用函数式编程方法。
*根据我自己的经验,尤其是在具有无服务器应用程序的云环境中 - 但这不是重点
【讨论】:
以上是关于如何使用 itertools 提取 groupby 值?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 python itertools.groupby() 按字符串的第一个字符对字符串列表进行分组?
《笔记》python itertools的groupby分组数据处理