【问题标题】:Easy way to compute Large data file python计算大数据文件python的简单方法
【发布时间】:2014-08-25 16:04:58
【问题描述】:

我必须从一个大文件中计算数据。文件有大约 100000 行和 3 列。 下面的程序适用于小测试文件,但是当尝试使用大文件运行时,即使显示一个结果也需要很长时间。任何加快大数据文件加载和计算的建议。

代码:小测试文件完美计算,输入格式如下

from collections import defaultdict
paircount = defaultdict(int)
pairtime = defaultdict(float)
pairper = defaultdict(float)

#get number of pair occrences and total time 
with open('input.txt', 'r') as f:
  with open('output.txt', 'w') as o: 
    numline = 0
    for line in f:
        numline += 1
            line = line.split()
        pair = line[0], line[1]
        paircount[pair] += 1
        pairtime[pair] += float(line[2])
        pairper = dict((pair, c * 100.0 / numline) for (pair, c) in paircount.iteritems())

    for pair, c in paircount.iteritems():
        #print pair[0], pair[1], c, pairper[pair], pairtime[pair]
        o.write("%s, %s, %s, %s, %s\n" % (pair[0], pair[1], c, pairper[pair], pairtime[pair]))

输入文件:

5372 2684 460.0
1885 1158 351.0
1349 1174 6375.0
1980 1174 650.0
1980 1349 650.0
4821 2684 469.0
4821 937  459.0
2684 937  318.0
1980 606  390.0
1349 606  750.0
1174 606  750.0

【问题讨论】:

  • 与其构建一个字典然后对其进行迭代以将结果写入文件,只需将它们当场写入文件即可。
  • 我无法理解pairper 背后的逻辑,您是否会在第一个 for 循环的每次迭代中覆盖它?另外,我认为有一些错误,因为您在该行中使用了变量c,但它实际上是稍后定义的。最后,正确缩进代码也会有所帮助。
  • 我和@javidcf 在一起-您正在为每一行重新创建pairper dict,并且只使用最后一个。那是为了丢弃而创建的 99999 个字典。随着paircount的增加,构建dict的成本也会上升。我也不确定它应该做什么。
  • 我知道我们曾经在 70 年代后期吹嘘拥有 100,000 行和 3 列的文件。无论如何,您实际上想做什么?请用文字解释。
  • @SitzBlogz 我在发布时没有仔细阅读您的代码。我没有注意到你的 for 循环中有“字典理解”。这在 O(n.log n) 中。不是吗?

标签: python data-files


【解决方案1】:

配对计算正在杀死你并且不需要。您可以使用 enumerate 来计算输入行,并在最后使用该值。这类似于 martineau 的答案,只是它不会将整个输入列表拉入内存(坏主意),甚至根本不会计算配对器。

from collections import defaultdict
paircount = defaultdict(int)
pairtime = defaultdict(float)

#get number of pair occrences and total time 
with open('input.txt', 'r') as f:
  with open('output.txt', 'w') as o: 
    for numline, line in enumerate(f, 1):
        line = line.split()
        pair = line[0], line[1]
        paircount[pair] += 1
        pairtime[pair] += float(line[2])

    for pair, c in paircount.iteritems():
        #print pair[0], pair[1], c, pairper[pair], pairtime[pair]
        o.write("%s, %s, %s, %s, %s\n" % (pair[0], pair[1], c, c * 100.0 / numline, pairtime[pair]))

【讨论】:

  • 我的回答不是“将整个输入列表拉入内存”。
  • @tdelaney 在找到时间总和后,您能否在相同的代码中建议我如何获得时间和频率的平均值。
【解决方案2】:

缓慢的主要原因是因为您从paircountdictionary 中的每一行重新创建perpairdictionary,它变得越来越大,这是没有必要的,因为只有在处理完所有行之后计算的值是曾经使用过。

我不完全理解所有的计算是什么,但这里有一个等价的东西,它应该运行得更快,因为它只创建一次pairperdictionary。我还稍微简化了逻辑,虽然这可能不会对运行时间产生太大影响,但我认为它更容易理解。

from collections import defaultdict
paircount = defaultdict(int)
pairtime = defaultdict(float)

#get number of pair occurrences and total time
with open('easy_input.txt', 'r') as f, open('easy_output.txt', 'w') as o:
    for numline, line in enumerate((line.split() for line in f), start=1):
        pair = line[0], line[1]
        paircount[pair] += 1
        pairtime[pair] += float(line[2])

    pairper = dict((pair, c * 100.0 / numline) for (pair, c)
                                                in paircount.iteritems())
    for pair, c in paircount.iteritems():
        #print pair[0], pair[1], c, pairper[pair], pairtime[pair]
        o.write("%s, %s, %s, %s, %s\n" % (pair[0], pair[1], c,
                                          pairper[pair], pairtime[pair]))
print 'done'

【讨论】:

  • 您的代码运行完美,对于像我这样对 Python 非常陌生的人来说看起来并不复杂。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-06-27
  • 1970-01-01
  • 2010-11-20
相关资源
最近更新 更多