读取和写入 CSV 文件#
Arrow 支持从/向 CSV 文件读取和写入列式数据。当前提供的功能如下:
多线程或单线程读取
自动解压输入文件(基于文件名扩展名,例如
my_data.csv.gz
)从 CSV 文件的第一行获取列名
逐列类型推断和转换为
null
、int64
、float64
、date32
、time32[s]
、timestamp[s]
、timestamp[ns]
、string
或binary
数据对
string
和binary
列进行机会主义字典编码(默认禁用)检测 null 值的各种拼写,例如
NaN
或#N/A
写入 CSV 文件,并提供配置精确输出格式的选项
用法#
CSV 读取和写入功能可通过 pyarrow.csv
模块获得。 在许多情况下,您只需调用 read_csv()
函数,并提供要从中读取的文件路径。
>>> from pyarrow import csv
>>> fn = 'tips.csv.gz'
>>> table = csv.read_csv(fn)
>>> table
pyarrow.Table
total_bill: double
tip: double
sex: string
smoker: string
day: string
time: string
size: int64
>>> len(table)
244
>>> df = table.to_pandas()
>>> df.head()
total_bill tip sex smoker day time size
0 16.99 1.01 Female No Sun Dinner 2
1 10.34 1.66 Male No Sun Dinner 3
2 21.01 3.50 Male No Sun Dinner 3
3 23.68 3.31 Male No Sun Dinner 2
4 24.59 3.61 Female No Sun Dinner 4
要写入 CSV 文件,只需调用 write_csv()
函数,并提供一个 pyarrow.RecordBatch
或 pyarrow.Table
以及一个路径或类似文件的对象。
>>> import pyarrow as pa
>>> import pyarrow.csv as csv
>>> csv.write_csv(table, "tips.csv")
>>> with pa.CompressedOutputStream("tips.csv.gz", "gzip") as out:
... csv.write_csv(table, out)
注意
写入器尚未支持所有 Arrow 类型。
自定义解析#
要更改读取具有不寻常结构的 CSV 文件时的默认解析设置,您应该创建一个 ParseOptions
实例并将其传递给 read_csv()
import pyarrow as pa
import pyarrow.csv as csv
table = csv.read_csv('tips.csv.gz', parse_options=csv.ParseOptions(
delimiter=";",
invalid_row_handler=skip_handler
))
可用的解析选项有
用于分隔 CSV 数据中各个单元格的字符。 |
|
用于可选地引用 CSV 值的字符(如果不允许引用,则为 False)。 |
|
如果一个带引号的 CSV 值中出现两个引号,是否表示数据中的单个引号。 |
|
用于可选地转义特殊字符的字符(如果不允许转义,则为 False)。 |
|
是否允许 CSV 值中包含换行符。 |
|
是否忽略 CSV 输入中的空行。 |
|
无效行的可选处理程序。 |
另请参阅
更多示例请参见 ParseOptions
。
自定义转换#
要更改 CSV 数据转换为 Arrow 类型和数据的方式,您应该创建一个 ConvertOptions
实例并将其传递给 read_csv()
import pyarrow as pa
import pyarrow.csv as csv
table = csv.read_csv('tips.csv.gz', convert_options=csv.ConvertOptions(
column_types={
'total_bill': pa.decimal128(precision=10, scale=2),
'tip': pa.decimal128(precision=10, scale=2),
}
))
可用的转换选项有
是否检查字符串列的 UTF8 有效性。 |
|
显式地将列名映射到列类型。 |
|
表示数据中 null 的字符串序列。 |
|
表示数据中 true 布尔值的字符串序列。 |
|
表示数据中 false 布尔值的字符串序列。 |
|
用作浮点数和十进制数据中小数点的字符。 |
|
一个与 strptime() 兼容的格式字符串序列,在尝试推断或转换时间戳值时按顺序尝试(也可以给出特殊值 ISO8601())。 |
|
字符串/二进制列是否可以具有 null 值。 |
|
带引号的值是否可以为 null。 |
|
是否尝试自动对字符串/二进制数据进行字典编码。 |
|
auto_dict_encode 的最大字典基数。 |
|
要包含在表中的列的名称。 |
|
如果为 false,则 include_columns 中但 CSV 文件中不存在的列将导致错误。 |
另请参阅
更多示例请参见 ConvertOptions
。
增量读取#
对于内存受限的环境,也可以一次读取一个批次的 CSV 文件,使用 open_csv()
。
有一些注意事项
目前,增量读取器始终是单线程的(无论
ReadOptions.use_threads
如何)类型推断在第一个块上完成,之后类型会被冻结;为了确保推断出正确的数据类型,请将
ReadOptions.block_size
设置为足够大的值,或者使用ConvertOptions.column_types
显式设置所需的数据类型。
字符编码#
默认情况下,CSV 文件应以 UTF8 编码。对于 binary
列,接受非 UTF8 数据。 可以使用 ReadOptions
类更改编码。
import pyarrow as pa
import pyarrow.csv as csv
table = csv.read_csv('tips.csv.gz', read_options=csv.ReadOptions(
column_names=["animals", "n_legs", "entry"],
skip_rows=1
))
可用的读取选项有
是否使用多线程来加速读取。 |
|
每次从输入流处理多少字节。 |
|
在列名(如果有)和 CSV 数据之前要跳过的行数。 |
|
在列名之后要跳过的行数。 |
|
目标表的列名。 |
|
如果 column_names 为空,是否自动生成列名。 |
|
编码:对象 |
另请参阅
更多示例请参见 ReadOptions
。
自定义写入#
要更改使用不同约定写入 CSV 文件时的默认写入设置,您可以创建一个 WriteOptions
实例并将其传递给 write_csv()
。
>>> import pyarrow as pa
>>> import pyarrow.csv as csv
>>> # Omit the header row (include_header=True is the default)
>>> options = csv.WriteOptions(include_header=False)
>>> csv.write_csv(table, "data.csv", options)
增量写入#
要一次写入一个批次的 CSV 文件,请创建一个 CSVWriter
。 这需要输出(路径或类文件对象)、要写入的数据的模式,以及可选的如上所述的写入选项。
>>> import pyarrow as pa
>>> import pyarrow.csv as csv
>>> with csv.CSVWriter("data.csv", table.schema) as writer:
>>> writer.write_table(table)
性能#
由于 CSV 文件的结构,人们不能期望与读取专用二进制格式(如 Parquet)时相同的性能水平。 但是,Arrow 致力于减少读取 CSV 文件的开销。 一个合理的期望是在性能良好的台式机或笔记本电脑上,每个核心至少达到 100 MB/s 的速度(以源 CSV 字节数衡量,而不是目标 Arrow 数据字节数)。
性能选项可以通过 ReadOptions
类进行控制。 默认情况下,为了获得最佳性能,会采用多线程读取,从而有效地将工作负载分配到所有可用的核心上。
注意
并发线程的数量由 Arrow 自动推断。 您可以使用 cpu_count()
和 set_cpu_count()
函数分别检查和更改它。