使用pyarrow读取CSV文件时,如何为所有列指定数据类型



我想用pyarrow读取一个大的CSV文件。我所有的专栏都是float64。但pyarrow似乎在推断int64。

如何为所有列指定数据类型?

import gcsfs
import pyarrow.dataset as ds
fs = gcsfs.GCSFileSystem(project='my-google-cloud-project')
my_dataset = ds.dataset("bucket/foo/bar.csv", format="csv", filesystem=fs)
my_dataset.to_table()

其产生:

ArrowInvalid                              Traceback (most recent call last)
........py in <module>
----> 65 my_dataset.to_table()
File /opt/conda/envs/py39/lib/python3.9/site-packages/pyarrow/_dataset.pyx:491, in pyarrow._dataset.Dataset.to_table()
File /opt/conda/envs/py39/lib/python3.9/site-packages/pyarrow/_dataset.pyx:3235, in pyarrow._dataset.Scanner.to_table()
File /opt/conda/envs/py39/lib/python3.9/site-packages/pyarrow/error.pxi:143, in pyarrow.lib.pyarrow_internal_check_status()
File /opt/conda/envs/py39/lib/python3.9/site-packages/pyarrow/error.pxi:99, in pyarrow.lib.check_status()
ArrowInvalid: In CSV column #172: Row #28: CSV conversion error to int64: invalid value '6.58841482364418'
Pyarrow的数据集模块以块的形式读取CSV文件(我认为默认值为1MB(,并并行处理这些块。这使得列推断有点棘手,它通过使用第一个块来推断数据类型来处理这一问题。因此,当文件的第一个区块有一个看起来是整数的列,但在未来的区块中,该列有十进制值时,您会遇到非常常见的错误。

如果您事先知道列名称,则可以指定列的数据类型:

import pyarrow as pa
import pyarrow.csv as csv
import pyarrow.dataset as ds
column_types = {'a': pa.float64(), 'b': pa.float64(), 'c': pa.float64()}
convert_options = csv.ConvertOptions(column_types=column_types)
custom_csv_format = ds.CsvFileFormat(convert_options=convert_options)
dataset = ds.dataset('/tmp/foo.csv', format=custom_csv_format)

如果您不知道列名,那么事情就有点棘手了。然而,听起来所有列都是float64。在这种情况下,由于您只有一个文件,您可能可以做这样的事情作为变通方法:

dataset = ds.dataset('/tmp/foo.csv', format='csv')
column_types = {}
for field in dataset.schema:
column_types[field.name] = pa.float64()
# Now use column_types as above

这是因为我们调用pa.dataset(...)两次,它会有一点开销。这是因为每次我们调用pa.dataset(...)时,pyarrow都会打开数据集中第一个文件的第一个块来确定模式(这就是为什么我们可以使用dataset.schema(

如果您有多个具有不同列的文件,那么这种方法将不起作用。在这种情况下,我建议邮寄Arrow用户@mailing列表,我们可以就解决问题的不同方法进行更全面的讨论。

最新更新