将大量 .data 加载到数组中的最快方法
Posted
技术标签:
【中文标题】将大量 .data 加载到数组中的最快方法【英文标题】:Fastest way to load huge .dat into array 【发布时间】:2014-10-21 08:31:38 【问题描述】:我在 stackexchange 中广泛搜索了一个将巨大 (~2GB) .dat 文件加载到 numpy 数组中的巧妙解决方案,但没有找到合适的解决方案。到目前为止,我设法以非常快速的方式(
list=[]
f = open('myhugefile0')
for line in f:
list.append(line)
f.close()
使用 np.loadtxt 会冻结我的计算机并需要几分钟才能加载(约 10 分钟)。如何将文件作为数组打开,而不会出现似乎瓶颈 np.loadtxt 的分配问题?
编辑:
输入数据是一个浮点数 (200000,5181) 数组。一行示例:
2.27069e-15 2.40985e-15 2.22525e-15 2.1138e-15 1.92038e-15 1.54218e-15 1.30739e-15 1.09205e-15 8.53416e-16 7.715236e-16 7.5836 16 8.81664e-16 1.09204e-15 1.27305e-15 1.58008e-15
等等
谢谢
【问题讨论】:
你有64位python吗?你有多少内存? 是的,我有 Canopy 64 位 Enthought 发行版。我的内存是 8GB。我也在使用 Spyder,我也想知道这是否是个问题。 您能否向我们展示您的输入数据样本?至少有几行。 @cacosomoza 你试过np.genfromtxt
吗?
您是否考虑过将数据文件重写为更适合相对大数据(fits 或 hdf5 左右)的数据格式,因为对于这些东西,有专门编写的库来处理(相对) 大数据
【参考方案1】:
查看source,似乎numpy.loadtxt
包含很多代码来处理许多不同的格式。如果您有一个定义明确的输入文件,编写您自己的针对特定文件格式优化的函数并不难。像这样的东西(未经测试):
def load_big_file(fname):
'''only works for well-formed text file of space-separated doubles'''
rows = [] # unknown number of lines, so use list
with open(fname) as f:
for line in f:
line = [float(s) for s in line.split()]
rows.append(np.array(line, dtype = np.double))
return np.vstack(rows) # convert list of vectors to array
如果之前知道行数和列数,另一种解决方案可能是:
def load_known_size(fname, nrow, ncol)
x = np.empty((nrow, ncol), dtype = np.double)
with open(fname) as f:
for irow, line in enumerate(f):
for icol, s in enumerate(line.split()):
x[irow, icol] = float(s)
return x
这样,你不必分配所有的中间列表。
编辑:似乎第二种解决方案有点慢,列表理解可能比显式 for 循环更快。结合这两种解决方案,并使用 Numpy 进行从字符串到浮点数的隐式转换(现在才发现)的技巧,这可能会更快:
def load_known_size(fname, nrow, ncol)
x = np.empty((nrow, ncol), dtype = np.double)
with open(fname) as f:
for irow, line in enumerate(f):
x[irow, :] = line.split()
return x
要获得进一步的加速,您可能必须使用一些用 C 或 Cython 编写的代码。我很想知道这些函数打开您的文件需要多长时间。
【讨论】:
感谢 Blas,这是一个很大的改进。刚刚尝试使用 1.9 Gb dat 文件 (200000,864) 浮点数。对于未知大小:CPU 时间:用户 1 分钟 24 秒,系统:5 秒,总计:1 分钟 29 秒挂壁时间:4 分钟 14 秒 对于已知大小:CPU 时间:用户 1 分钟 45 秒,系统:2.52 秒,总计:1 分钟 47 秒挂壁时间:2 分钟 12 秒很奇怪,第二个函数花了更多时间 如果有人没有在几天内发布更快的方法,我会将答案标记为解决方案 第二个可能较慢的一个原因是内部循环 (for icol, s ...
) 是在 Python 中完成的,而对于第一个函数,内部循环是一个列表解析 ([float(s) for ...]
),它在 C 中实现。您可以尝试一些混合解决方案,首先使用列表推导转换为浮点列表,然后使用x[irow, :] = line
设置预分配矩阵x
的完整行。
运行时序比较的顺序可能很重要。您的文件系统具有缓存,因此无论您如何处理文件,第二次读取文件都可能比第一次更快。以上是关于将大量 .data 加载到数组中的最快方法的主要内容,如果未能解决你的问题,请参考以下文章
从 MySQL 将数值数据加载到 python/pandas/numpy 数组中的最快方法