分组/汇总数据的方法?

时间:2018-04-29 12:14:53

标签: python list grouping

我有一些数据存储在列表中,我希望根据值进行分组。

例如,如果我的数据是

data = [(1, 'a'), (2, 'x'), (1, 'b')]

我希望按每个元组中的第一个值对其进行分组

result = [(1, 'ab'), (2, 'x')]

我该怎么办呢?

更一般地说,推荐的在python中分组数据的方法是什么?有没有可以帮助我的食谱?

3 个答案:

答案 0 :(得分:2)

itertools.groupby

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')]

有时,extractKeyaggregate或两者都可以内联到一行(我们也省略了排序键,因为这个是多余的示例):

[(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)

Pandas groupby

这不是一个配方,而是一种使用功能对数据进行分组的直观而灵活的方式。在这种情况下,函数是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)

多解析列表理解

dictgroupby解决方案相比,效率低下。

但是,对于小型列表,其中性能不是一个问题,您可以执行列表解析,为每个唯一标识符解析列表。

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')]

解决方案可分为两部分:

  1. set(list(zip(*data))[0])提取我们通过列表推导中的for循环迭代的唯一标识符集。
  2. (i, ''.join([j[1] for j in data if j[0] == i]))将所需的逻辑应用于所需的输出。