【问题标题】:Speed of writing a numpy array to a text file将 numpy 数组写入文本文件的速度
【发布时间】:2019-05-18 03:42:32
【问题描述】:

我需要将一个非常“高”的两列数组写入文本文件,而且速度非常慢。我发现如果我将数组重新整形为更宽的数组,写入速度会快得多。 例如

import time
import numpy as np
dataMat1 = np.random.rand(1000,1000)
dataMat2 = np.random.rand(2,500000)
dataMat3 = np.random.rand(500000,2)
start = time.perf_counter()
with open('test1.txt','w') as f:
    np.savetxt(f,dataMat1,fmt='%g',delimiter=' ')
end = time.perf_counter()
print(end-start)

start = time.perf_counter()
with open('test2.txt','w') as f:
    np.savetxt(f,dataMat2,fmt='%g',delimiter=' ')
end = time.perf_counter()
print(end-start)

start = time.perf_counter()
with open('test3.txt','w') as f:
    np.savetxt(f,dataMat3,fmt='%g',delimiter=' ')
end = time.perf_counter()
print(end-start)

三个数据矩阵中的元素数量相同,为什么最后一个比其他两个更耗时?有什么办法可以加快“高”数据数组的写入速度?

【问题讨论】:

  • 你真的需要它作为文本吗?
  • 您可能需要检查this post 以获得高效的阵列 I/O
  • 不幸的是,我需要将其写为文本而不是二进制文件。

标签: python performance numpy


【解决方案1】:

作为hpaulj pointed outsavetxtlooping through the rows of X 并单独格式化每一行:

for row in X:
    try:
        v = format % tuple(row) + newline
    except TypeError:
        raise TypeError("Mismatch between array dtype ('%s') and "
                        "format specifier ('%s')"
                        % (str(X.dtype), format))
    fh.write(v)

我认为这里的主要时间杀手是所有字符串插值调用。 如果我们将所有字符串插值打包到一个调用中,事情会变得更快:

with open('/tmp/test4.txt','w') as f:
    fmt = ' '.join(['%g']*dataMat3.shape[1])
    fmt = '\n'.join([fmt]*dataMat3.shape[0])
    data = fmt % tuple(dataMat3.ravel())
    f.write(data)

import io
import time
import numpy as np

dataMat1 = np.random.rand(1000,1000)
dataMat2 = np.random.rand(2,500000)
dataMat3 = np.random.rand(500000,2)
start = time.perf_counter()
with open('/tmp/test1.txt','w') as f:
    np.savetxt(f,dataMat1,fmt='%g',delimiter=' ')
end = time.perf_counter()
print(end-start)

start = time.perf_counter()
with open('/tmp/test2.txt','w') as f:
    np.savetxt(f,dataMat2,fmt='%g',delimiter=' ')
end = time.perf_counter()
print(end-start)

start = time.perf_counter()
with open('/tmp/test3.txt','w') as f:
    np.savetxt(f,dataMat3,fmt='%g',delimiter=' ')
end = time.perf_counter()
print(end-start)

start = time.perf_counter()
with open('/tmp/test4.txt','w') as f:
    fmt = ' '.join(['%g']*dataMat3.shape[1])
    fmt = '\n'.join([fmt]*dataMat3.shape[0])
    data = fmt % tuple(dataMat3.ravel())        
    f.write(data)
end = time.perf_counter()
print(end-start)

报告

0.1604848340011813
0.17416274400056864
0.6634929459996783
0.16207673999997496

【讨论】:

    【解决方案2】:

    savetxt 的代码是 Python 并且可以访问。基本上它为每一行/行进行格式化写入。实际上是这样的

    for row in arr:
       f.write(fmt%tuple(row))
    

    其中fmt 源自您的fmt 和数组的形状,例如

    '%g %g %g ...'
    

    所以它正在为数组的每一行写入文件。行格式也需要一些时间,但它是使用 Python 代码在内存中完成的。

    我预计loadtxt/genfromtxt 将显示相同的时间模式 - 读取多行需要更长的时间。

    pandas 的 csv 加载速度更快。我还没有看到任何关于它的写入速度的讨论。

    【讨论】:

    • 这如何回答所提出的问题?
    • @ScottHunter,它回答了why 的问题,不是吗?
    • 现在回答它。
    • 只是评论,我发现pandas的写入速度实际上比numpy慢。如果不需要 csv 格式,np.save() 比两者都快一个数量级。
    猜你喜欢
    • 1970-01-01
    • 2017-12-23
    • 2017-07-15
    • 2023-03-31
    • 2017-04-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-30
    相关资源
    最近更新 更多