【问题标题】:How to append successive calls to a single numpy file without losing precision?如何在不丢失精度的情况下将连续调用附加到单个 numpy 文件?
【发布时间】:2021-09-29 18:29:17
【问题描述】:

在应用了一些程序之后,我得到了数百万个 numpy 数组(在下面的例子中,程序将 e 转换为一个 numpy 数组):

for e in l:
    procedure(e)

如何将每次迭代正确保存到单个 numpy 文件中以供以后读取和加载?

到目前为止,我尝试了两个选项,使用 np.savez:

for i, e in enumerate(l):
    np.savez(f'/Users/user/array.npz',i=e)

还有熊猫:

(1) 保存到单个文件中:

for e in l:
   arr = pd.DataFrame(procedure(i)).T 
   arr.to_csv('/Users/user/Downloads/arr.csv', mode='a', index=False, header=False)

(2) 阅读:

arr = np.genfromtxt("/Users/user/Downloads/arr.csv", delimiter=',', dtype='float32', float_format='%.16f')

到目前为止,有效的解决方案是使用 pandas。但是,我想我在 numpy 矩阵中失去了精确度。因为没有像这样的值(使用 e):

-6.82821393e-01 -2.65419781e-01

我得到这样的值:

-0.6828214 , -0.26541978

但是,numpy 矩阵没有正确保存。

在 for 循环迭代之后将每个 numpy 矩阵转储到单个文件中的最有效和正确的方法是什么?

【问题讨论】:

  • 要加载savez,您需要先阅读savez 文档! savez 用于一次保存多个数组。它不会将连续调用附加到一个文件。我有一种感觉,您正在尝试编写代码而没有过多关注官方文档。
  • @hpaulj 我明白了,所以在这种情况下 savez 不适用,这就是我尝试使用 pandas 但数组似乎不同的原因。关于如何在迭代后将它们附加到单个文件中的任何想法?
  • csv 格式是文本,适用于二维表 - 多行和一致的列数。虽然您可以多次附加到文件,但如果列数发生变化,则加载很困难。但首先,请告诉我们一些关于您要保存的数组的信息。它们的形状(和 dtype)是否不同?如果它们的形状足够匹配,您可以将它们连接成一个数组,然后保存。如果它们不同,您需要一种文件格式来处理不同的对象集。 pickle 是一个,但我不记得它是否可以迭代使用。
  • 它们的形状都一样。它们在 dtype 或 shape 上没有区别,它们都具有相同的值。现在的问题是精度的损失@hpaulj
  • 您可以np.stack 它们(或集群)并使用np.save 来写入数组。 save 不会降低精度。 savetxt 这样做是因为 ir 写入字符串。

标签: python pandas numpy io


【解决方案1】:

我不知道在这种情况下csv是否是正确的格式,但您可以指定float格式以避免精度损失。

使用 pandas 追加到 CSV

import pandas as pd
import numpy as np
pd.set_option('precision', 16)  # for print command

fn = 'pandasfile.csv'
arr = np.linspace(1,100,10000).reshape(5000,2)
df = pd.DataFrame(arr)

df.to_csv(fn, mode='a', index=False, header=False, float_format='%.16f', sep='\t')

使用 numpy 追加到 CSV

import numpy as np
np.set_printoptions(precision=16)

fn = 'numpyfile.csv'
arr = np.linspace(1,100,10000).reshape(5000,2)
print(arr)

with open(fn, "a") as f:
    np.savetxt(f, arr, fmt='%.16f', delimiter='\t')

我使用制表符作为分隔符,它更具可读性(有人称之为 TSV 文件)。您可以使用 "," 或 " " 代替。

加载 CSV 到 numpy

arr2 = np.loadtxt(fn, delimiter='\t')
print(arr2)

加载 CSV 到 pandas

df = pd.read_csv(fn, header=None, sep='\t', dtype='float32')
print(df)

如果重要的话,numpy 版本会快一点。

m@o780:~$ time python3 pdsave.py 

real    0m0,473s
user    0m0,448s
sys 0m0,102s

m@o780:~$ time python3 npsave.py 

real    0m0,199s
user    0m0,214s
sys 0m0,072s
m@o780:~$ 

【讨论】:

  • 感谢您的帮助,但是,正如我在问题中提到的那样,我已经在使用 float_format='%.16f' 并且仍然失去精度。有没有其他不丢失的方法?如果我使用float_format='%.64f' 应该可以吗?
  • 我加了一个例子,你需要这个吗?
  • 所以你可以在 numpy 中用a 模式做savetxt 吗?通过这样做,我会将所有内容转储到一个文件中?
  • 是的,我用谷歌搜索了这个解决方案,它似乎工作正常。尝试多次运行该代码。 stackoverflow.com/questions/54361557/…
【解决方案2】:

np.savez 以 zip 格式保存数组,默认名称为 arr_0。如果您再次使用它,它将覆盖您当前的文件,这意味着保存后最新的文件将在那里。好处是您可以在 zip 中命名文件,因此您可以为每个 numpy 数组或仅索引使用自定义名称,如下例所示。

for i, e in enumerate(l):
 np.savez(f'/Users/user/array.npz',i=e)

【讨论】:

  • savez 用于编写多个数组,允许您单独检索它们
猜你喜欢
  • 2014-06-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-26
  • 1970-01-01
  • 1970-01-01
  • 2021-10-21
  • 1970-01-01
相关资源
最近更新 更多