我有一些数据存储在列表中,我希望根据值进行分组。
例如,如果我的数据是
data = [(1, 'a'), (2, 'x'), (1, 'b')]
我希望按每个元组中的第一个值对其进行分组
result = [(1, 'ab'), (2, 'x')]
我该怎么办呢?
更一般地说,推荐的在python中分组数据的方法是什么?有没有可以帮助我的食谱?
答案 0 :(得分:2)
itertools
及其groupby()
中有一个通用的食谱。
此配方的模式可以这种形式给出:
[(k, aggregate(g)) for k, g in groupby(sorted(data, key=extractKey), extractKey)]
配方中要更改的两个相关部分是:
定义分组键( extractKey ):在这种情况下获取元组的第一项:
lambda x: x[0]
汇总分组结果(如果需要)(汇总):g
包含每个密钥k
的所有匹配元组(例如(1, 'a')
,密钥(1, 'b')
为1
,密钥(2, 'x')
为2
,我们只想获取元组的第二项并将所有这些项连接在一个字符串中:
''.join(x[1] for x in g)
示例:
from itertools import groupby
extractKey = lambda x: x[0]
aggregate = lambda g: ''.join(x[1] for x in g)
[(k, aggregate(g)) for k, g in groupby(sorted(data, key=extractKey), extractKey)]
# [(1, 'ab'), (2, 'x')]
有时,extractKey
,aggregate
或两者都可以内联到一行(我们也省略了排序键,因为这个是多余的示例):
[(k, ''.join(x[1] for x in g)) for k, g in groupby(sorted(data), lambda x: x[0])]
# [(1, 'ab'), (2, 'x')]
使用defaultdict
将此食谱与食谱进行比较,两种情况都有利弊。
groupby()
往往比defaultdict
配方慢(在我的测试中慢两倍)。
另一方面,groupby()
在内存受限的情况下具有优势,其中值是在运行中生成的;您可以以流方式处理组,而无需存储它们; defaultdict
将需要内存来存储所有。
答案 1 :(得分:0)
这不是一个配方,而是一种使用功能对数据进行分组的直观而灵活的方式。在这种情况下,函数是str.join
。
import pandas as pd
data = [(1, 'a'), (2, 'x'), (1, 'b')]
# create dataframe from list of tuples
df = pd.DataFrame(data)
# group by first item and apply str.join
grp = df.groupby(0)[1].apply(''.join)
# create list of tuples from index and value
res = list(zip(grp.index, grp))
print(res)
[(1, 'ab'), (2, 'x')]
<强>优点强>
list
输出的工作流程。''.join
更改为list
或其他缩减功能,轻松适应。<强>缺点强>
list
- &gt; pd.DataFrame
- &gt; list
转化。答案 2 :(得分:-3)
但是,对于小型列表,其中性能不是一个问题,您可以执行列表解析,为每个唯一标识符解析列表。
res = [(i, ''.join([j[1] for j in data if j[0] == i]))
for i in set(list(zip(*data))[0])]
[(1, 'ab'), (2, 'x')]
解决方案可分为两部分:
set(list(zip(*data))[0])
提取我们通过列表推导中的for
循环迭代的唯一标识符集。(i, ''.join([j[1] for j in data if j[0] == i]))
将所需的逻辑应用于所需的输出。