4

我有一个大文件,每行有两个数字,按第二列排序。我制作了一个以第一列为键的列表字典。

我的代码看起来像

from collections import defaultdict
d = defaultdict(list)
for line in fin.readline():
    vals = line.split()
    d[vals[0]].append(vals[1])
process(d)

但是,输入文件太大,因此d不适合内存。

为了解决这个问题,我原则上可以一次读取文件的块,但我需要在块之间进行重叠,这样process(d) 就不会错过任何东西。

在伪代码中,我可以执行以下操作。

  1. 阅读 100 行创建字典d
  2. 处理字典d
  3. 删除 d目前为止不在最大值 10 以内的所有内容。
  4. d重复但确保我们在任何时候都没有超过 100 行的数据。

在 python 中有没有很好的方法来做到这一点?

更新。 问题的更多细节。我将d在读取第二个成对文件时使用,如果取决于列表中有多少值与第一个值相关联的值在d10 以内,我将在该文件中输出该对。第二个文件也按第二列排序。

假数据。 假设我们可以将 5 行数据放入内存中,并且我们需要值的重叠也为 5。

1 1
2 1
1 6
7 6
1 16

所以现在 d 是 {1:[1,6,16],2:[1],7:[6]}。

对于下一个块,我们只需要保留最后一个值(如 16-6 > 5)。所以我们会设置

d 为 {1:[16]} 并继续阅读接下来的4行。

4

3 回答 3

2

您是否尝试过Pandas 库,特别是将您的数据读入 DataFrame 然后在第一列上使用groupby ?

Pandas 可以让你有效地对数据进行大量批量操作,如果你愿意,你可以懒惰地读取它。

于 2013-07-25T20:27:19.627 回答
0

除非文件发生奇怪的事情,否则您不需要默认字典,但您没有提到那是什么。取而代之的是,使用一个列表,使您的数据按行顺序排列,这样您就可以使用适当的切片来处理它:

d = []
for line in fin.readline():
    vals = line.split()
    d.append(vals)
    if not len(d)%100:
        process(d)
        d = d[90:]
process(d)
于 2013-07-25T19:19:31.850 回答
0

你可以这样做:

n_process = 100
n_overlap = 10
data_chunk = []
for line in fin.readline():
    vals = line.split()
    data_chunk.append(vals)
    if len(data_chunk) == n_process:
        process(data_chunk)
        data_chunk = data_chunk[-n_overlap:]

使用字典时,如果数据样本中第一列中出现多次数字,则数据可能会被覆盖。另请注意,您需要使用OrderedDict,因为 adict在 python 中没有订单。但是,在我看来,OrderedDict在大多数情况下,这是糟糕的代码设计的标志。

顺便说一句:我们仍然不知道你为什么要这样做……</p>

于 2013-07-25T19:19:51.230 回答