重复数据删除多变量数据的最快方法是什么?

时间:2018-03-09 04:38:56

标签: python performance duplicates time-complexity

让我们假设一个非常简单的数据结构。在下面的示例中,ID是唯一的。 “date”和“id”是字符串,“amount”是整数。

data = [[date1, id1, amount1], [date2, id2, amount2], etc.]

如果date1 == date2id1 == id2,我想将这两个条目合并为一个,基本上将amount1和amount2相加,以便数据变为:

data = [[date1, id1, amount1 + amount2], etc.]

有许多重复。

由于数据非常大(超过100,000个条目),我希望尽可能高效地完成这项工作。我所做的是创建了一个新的“常用”字段,基本上将date + id组合成一个带有元数据的字符串,允许我稍后将其拆分(date + id + "_" + str(len(date))。

就复杂性而言,我有四个循环:

  1. 从外部源解析并加载数据(它不在列表中)|为O(n)
  2. 循环数据并创建和存储“常用”字符串(日期+ id +元数据) - 我称之为“准备好的数据”,其中“common”是我的编码字段为O(n)
  3. 使用Counter()对象重复数据删除“准备好的数据”|为O(n)
  4. 解码“常见”|为O(n)
  5. 我不关心这里的记忆,我只关心速度。我可以做一个嵌套循环并避免步骤2,3和4,但这将是一个时间复杂性的灾难(O(n²))。

    最快的方法是什么?

3 个答案:

答案 0 :(得分:3)

考虑使用defaultdict按唯一键聚合数据:

<强>鉴于

一些随机数据

import random
import collections as ct


random.seed(123)

# Random data
dates = ["2018-04-24", "2018-05-04", "2018-07-06"]
ids = "A B C D".split()
amounts = lambda: random.randrange(1, 100)

ch = random.choice
data = [[ch(dates), ch(ids), amounts()] for _ in range(10)]
data

输出

[['2018-04-24', 'C', 12],
 ['2018-05-04', 'C', 14],
 ['2018-04-24', 'D', 69],
 ['2018-07-06', 'C', 44],
 ['2018-04-24', 'B', 18],
 ['2018-05-04', 'C', 90],
 ['2018-04-24', 'B', 1],
 ['2018-05-04', 'A', 77],
 ['2018-05-04', 'A', 1],
 ['2018-05-04', 'D', 14]]

<强>代码

dd = ct.defaultdict(int)
for date, id_, amt in data:
    key = "{}{}_{}".format(date, id_, len(date))
    dd[key] += amt
dd

输出

defaultdict(int,
            {'2018-04-24B_10': 19,
             '2018-04-24C_10': 12,
             '2018-04-24D_10': 69,
             '2018-05-04A_10': 78,
             '2018-05-04C_10': 104,
             '2018-05-04D_10': 14,
             '2018-07-06C_10': 44})

<强>详情

defaultdict是一个字典,可以为任何缺失的键调用default factory(指定的函数)。在这种情况下,每个date + id组合都会唯一地添加到dict中。如果找到现有密钥,则会将amounts添加到值中。否则,整数(0)初始化dict的新条目。

为了便于说明,您可以使用list作为默认工厂来显示聚合值。

dd = ct.defaultdict(list)
for date, id_, val in data:
    key = "{}{}_{}".format(date, id_, len(date))
    dd[key].append(val)
dd

输出

defaultdict(list,
            {'2018-04-24B_10': [18, 1],
             '2018-04-24C_10': [12],
             '2018-04-24D_10': [69],
             '2018-05-04A_10': [77, 1],
             '2018-05-04C_10': [14, 90],
             '2018-05-04D_10': [14],
             '2018-07-06C_10': [44]})

我们看到三次出现重复键,其值正确相加。关于效率,请注意:

  1. 密钥是使用format()创建的,字符串连接和调用str()
  2. 应该更好一点
  3. 每个键和值都在同一次迭代中计算

答案 1 :(得分:1)

使用pandas使这非常简单:

import pandas as pd
df = pd.DataFrame(data, columns=['date', 'id', 'amount'])
df.groupby(['date','id']).sum().reset_index()

要获得更多控制权,您可以使用agg代替sum()

df.groupby(['date','id']).agg({'amount':'sum'})

根据您对数据的处理方式,这样做可能更容易/更快,因为大量的pandas都是基于编译的C扩展和优化的例程构建的,这使得转换和操作非常容易。

答案 2 :(得分:0)

您可以将数据导入到防止重复的结构中,然后将其转换为列表。

data = {
    date1: {
        id1: amount1,
        id2: amount2,
    },
    date2: {
        id3: amount3,
        id4: amount4,
        ....
}

该计划的骨架:

ddata = collections.defaultdict(dict)
for date, id, amount in DATASOURCE:
    ddata[date][id] = amount
data = [[d, i, a] for d, subd in ddata.items() for i, a in subd.items()]