如何将.csv
文件高效转换为.npy
文件?
我试过了:
import numpy as np
filename = "myfile.csv"
vec =np.loadtxt(filename, delimiter=",")
np.save(f"{filename}.npy", vec)
虽然上面的方法适用于较小的文件,但我正在处理的实际.csv
文件有大约1200万行、1024列,在转换为.npy
之前,需要将所有内容加载到RAM中。
Q(Part 1):对于大型CSV文件,有没有办法高效地将.csv
加载/转换为.npy
?
上面的代码片段类似于Convert CSV to numpy的答案,但它不适用于~12M x 1024矩阵。
Q(第2部分):如果没有办法高效地将.csv
加载/转换成.npy
,有没有办法高效地迭代地将.csv
文件读入.npy
?
另外,https://stackoverflow.com/a/53558856/610569给出了迭代地将CSV文件保存为NumPy数组的答案。但在读取文件时,np.vstack
似乎不是最佳解决方案。公认的答案是hdf5,但格式不是这个问题的主要目标,在我的用例中也不需要hdf5格式,因为之后我必须将其读回一个数字数组中。
Q(Part 3):如果Part 1和Part 2都不行,是否有其他高效的存储(如tensorstore)可以存储并在加载保存的存储格式时高效地转换为NumPy数组?
还有另一个库tensorstore
似乎可以有效地处理在读取时支持转换为NumPy数组的数组,即https://google.github.io/tensorstore/python/tutorial.html。但不知何故,没有任何关于如何在没有确切维度的情况下保存tensor
/数组的信息,所有的示例似乎都包括像'dimensions': [1000, 20000],
这样的配置。
与HDF5不同,tensorstore在从文档转换为NumPy时似乎不存在读取开销问题:
转换为numpy.ndarray还隐式地执行同步读取(由于刚刚检索到相同的区域,因此会命中内存中的缓存)
5条答案
按热度按时间55ooxyrt1#
问得好;本身就很有见地。
我知道您希望将整个数据集/数组最终作为NumPy数组存储在内存中。那么,我假设您有足够的(RAM)内存来存放这样的阵列--12Mx1K。
我不知道
np.loadtxt
(genfromtxt
)在幕后是如何操作的,所以我会告诉您我会如何做(在像您一样尝试之后)。记忆推理...
请注意,一个简单的布尔数组需要大约12 GB的内存:
这是针对布尔数据类型的。最有可能的是,你有--什么--一个整型、浮点型的数据集?其大小可能会显著增加:
在这一点上,我想指出工作记忆的一种可能的“交换”。您的计算机中可能有足够的物理(RAM)内存,但如果没有足够的空闲内存,您的系统将使用交换内存(即磁盘)来保持系统稳定并完成工作。您付出的代价是显而易见的:从磁盘读取/写入磁盘非常慢。
到目前为止,我的观点是:检查数据集的数据类型,估计未来数组的大小,并确保您有最小的可用RAM内存。
I/O文本
考虑到您确实拥有托管整个NumPy数组所需的所有(RAM)内存:然后我将遍历整个(大约1200万行)文本文件,逐行填充先前存在的数组。
更准确地说,我应该在开始读取文件之前示例化(大)数组。只有这样,我才会读取每一行,拆分列,并将其赋给
np.asarray
,然后将这些(1024)值赋给输出数组的每一行。是的,在文件上循环的速度很慢。这里的问题是您限制(和控制)使用的内存量。粗略地说,消耗内存的大对象是“输出”(大)数组和“行”(1024)数组。当然,在阅读期间,临时对象中的每个循环都消耗了相当大的内存量(文本!)值,拆分为列表元素并转换为数组。尽管如此,在整个约1200万条生产线上,这一数字将基本保持不变。
所以,我要经历的步骤是:
当然,您甚至可以将其并行化:一方面,如果文本文件不能被随机(R/W)访问,另一方面,您可以很容易地将它们拆分(参见How can I split one text file into multiple *.txt files?),以便--如果FUN在谈判桌上--并行阅读它们,如果那个时间是关键的话。
希望这能帮上忙。
nhaq1z212#
TL;DR
除非您的机器能够按照@Brandt Answer中的描述处理内存中的数据大小,否则导出到
.npy
以外的其他函数似乎是不可避免的。读取数据并进行处理(Kinda Answer Q Part下)
要处理超过RAM可以处理的数据量,通常会求助于执行“核外”计算的库,例如
turicreate.SFrame
、vaex
或dask
。这些库将能够延迟地将.csv
文件加载到 Dataframe 中,并在评估时按块处理它们。或
将读取的数据转换为NumPy数组(有点答问第一部分)
虽然核外库可以高效地读取和处理数据,但将其转换为NumPy是一项“内存中”的操作,机器需要有足够的RAM来容纳所有数据。
turicreate.SFrame.to_numpy
文档写道:将此SFrame转换为Numy数组
此操作将在内存中构造一个Numy数组。当返回的对象很大时,必须小心。
vaex
文档写道:内存中数据表示法
可以从各种内存中的数据表示构造Vaex DataFrame。
和
dask
最佳实践实际上重新实现了它们自己的数组对象,这些数组对象比NumPy数组更简单,请参阅https://docs.dask.org/en/stable/array-best-practices.html。但在浏览文档时,他们保存Dask数组的格式似乎不是.npy
,而是各种其他格式。将文件写入非
.npy
版本(回答QPart 3)考虑到NumPy数组不可避免地在内存中,尝试将数据保存到一个
.npy
中不是最可行的选择。不同的库似乎有不同的存储解决方案。例如。
vaex.from_csv()
读取数据时设置了convert=True
参数,则vaex
默认情况下将数据保存到hdf5
中sframe
将数据保存为自己的二进制格式dask
export functions保存to_hdf()
和to_parquet()
iklwldmw3#
它的最新版本(4.14)VAEX支持“流”,即CSV文件的延迟加载。它在引擎盖下使用了箭,所以晚餐很快。试试像这样的东西
然后,您可以根据需要导出为多种格式,或者继续使用它(它的速度快得令人惊讶)。当然,最好是转换成某种二进制格式。
wwwo4jvm4#
ruarlubt5#
我不知道有任何现有的函数或实用程序可以直接高效地将CSV文件转换为NPY文件。我猜,高效的主要意思是内存需求低。
迭代地编写NPY文件确实是可能的,只需付出一些额外的努力。上已经有一个问题,所以这就解决了这个问题,请参见:save numpy array in append mode
例如,使用Michael's answer中的
NpyAppendArray
类,您可以执行以下操作:NpyAppendArray
类在每次调用append
时更新NPY文件头,这对于您的1200万行来说有点多了。也许您可以将类更新为(可选)仅在close
上写入头。或者,您也可以轻松地批量写入:(代码未经过测试)