3

我在一个文本文件中存储了超过 6500 万个数值。我需要计算最大值、最小值、平均值、标准差以及 25、50 和 75 个百分位数。

通常我会使用附加的代码,但我需要一种更有效的方法来计算这些指标,因为我无法将所有值 p 存储在列表中。如何在 Python 中更有效地计算这些值?

import numpy as np

np.average(obj)
np.min(mylist)
np.max(mylist)
np.std(mylist)
np.percentile(obj, 25)
np.percentile(obj, 50)
np.percentile(obj, 75)

maxx = float('-inf')
minx = float('+inf')
sumz = 0
for index, p in enumerate(open("foo.txt", "r")):
    maxx = max(maxx, float(p))
    minx = min(minx, float(p))
    sumz += float(p)
index += 1
my_max = maxx 
my_min = minx 
my_avg = sumz/index
4

5 回答 5

5

使用二进制文件。然后,您可以使用numpy.memmap将其映射到内存并执行各种算法,即使数据集大于 RAM。

您甚至可以使用 numpy.memmap 创建一个内存映射数组,并从文本文件中读取数据……您可以对其进行处理,完成后,您还可以获得二进制格式的数据。

于 2013-08-20T18:25:28.523 回答
3

我认为你在正确的轨道上,通过迭代文件并跟踪最大值和最小值。要计算标准差,您应该在循环内保留平方和:sum_of_squares += z**2. std = sqrt(sum_of_squares / n - (sumz / n)**2)然后您可以在循环之后进行计算,请参见此处的公式(但此公式可能会遇到数值问题)。为了提高性能,您可能希望在一些大小合适的数据块中迭代文件。

要以“连续”方式计算中位数和百分位数,您可以在循环内建立直方图。循环之后,您可以通过将直方图转换为CDF来获得近似的百分位数和中位数,误差将取决于 bin 的数量。

于 2013-08-20T18:23:35.567 回答
2

正如 Antti Haapala 所说,最简单和最有效的方法是坚持使用 numpy,并且只使用memmapped 二进制文件而不是文本文件。是的,从一种格式转换为另一种格式需要一些时间——但它几乎肯定会比成本节省更多的时间(因为你可以使用 numpy 向量化操作而不是循环),而且它也会让你的代码很多更简单。

如果你不能这样做,Python 3.4 将附带一个statistics模块。在 PEP 最终确定后,有望在某个时候提供到 2.6+ 的反向移植;目前我相信你只能得到stats它所基于的较早的模块,它需要3.1+。不幸的是,虽然stats确实在迭代器上执行单遍算法,但它没有任何方便的方法可以在同一个迭代器上并行运行多个算法,因此您必须巧妙itertools.teezip强制它交错工作而不是拉动整个记忆中的东西。

如果您在PyPI 中搜索“stats”和/或“statistics”和/或“statistical” ,当然还有很多其他模块。

无论哪种方式,使用预构建模块都意味着有人已经调试了您将遇到的所有问题,并且他们可能还优化了代码(甚至可能将其移植到 C)以启动。

于 2013-08-20T18:37:22.337 回答
1

大多数这些操作都可以用简单的算术来表示。awk在这种情况下,使用and直接从 Linux 命令行处理简单的统计数据实际上(令人惊讶地)非常有效sed,例如在这篇文章中:< http://www.unixcl.com/2008/09/sum-of -and-group-by-using-awk.html >。

如果您需要推广到更高级的操作,例如加权百分位数,那么我建议使用Python Pandas(尤其是HDFStore以后检索的功能)。我之前使用过带有超过 2500 万条记录的 DataFrame(10 列乘 2500 万不同行)的 Pandas。如果您的内存受到更多限制,您可以以块的形式读取数据,计算每个块的部分贡献,并存储中间结果,然后通过加载中间结果以序列化排序的 map-reduce 完成计算一种框架。

于 2013-08-20T19:17:14.990 回答
1

要获得百分位数,请使用命令行程序对文本文件进行排序。使用行数(index在您的程序中)查找百分位数的行号(index // 4等)然后从文件中检索这些行。

于 2013-08-20T18:32:23.497 回答