You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Arrow的open_dataset读取多CSV时,如何将int转为double?

解决Arrow读取CSV时int64与double类型不兼容问题

核心问题原因

  1. Arrow默认仅读取前N行(R默认1000行、Python默认1000行)推断CSV列类型,若某列前N行都是整数、后续出现浮点数,会被误判为int64类型。
  2. unify_schemas = TRUE默认不允许int64与double合并,Arrow认为这两种类型属于不兼容类型,需显式开启类型提升策略。

R 解决方案

方案1:读取全部行推断类型+自动类型提升

通过配置CSV读取选项,强制Arrow读取每个文件的所有行来推断类型,再通过自定义合并逻辑允许int64自动提升为double:

library(tidyverse)
library(arrow)

# 配置CSV读取规则:读取全部行推断类型
csv_options <- csv_format(infer_schema_length = -1)

# 自定义schema合并函数,允许类型提升
merge_schemas_with_promotion <- function(schemas) {
  reduce(schemas, function(a, b) {
    a$merge(b, promote = TRUE)
  })
}

# 获取每个CSV文件的独立schema
file_paths <- list.files("data/", pattern = "\\.csv$", full.names = TRUE)
file_schemas <- map(file_paths, ~read_csv_arrow(.x, format = csv_options)$schema)

# 合并所有schema,允许int转double
unified_schema <- merge_schemas_with_promotion(file_schemas)

# 使用合并后的schema读取数据集
csvs <- open_dataset(
  sources = "data/", 
  format = "csv",
  schema = unified_schema,
  format_options = csv_options
)

csvs |> glimpse()

方案2:仅修改特定列类型(无需枚举所有列)

如果不想读取全部行,可以先自动推断基础schema,再单独调整需要兼容的列类型:

library(tidyverse)
library(arrow)

# 获取所有文件的初始schema并合并
file_paths <- list.files("data/", pattern = "\\.csv$", full.names = TRUE)
file_schemas <- map(file_paths, ~read_csv_arrow(.x)$schema)
temp_schema <- reduce(file_schemas, function(a, b) {a$merge(b, promote = TRUE)})

# 修改指定列的类型(这里是列b改为double)
final_schema <- schema(
  a = temp_schema$a,  # 保留原类型
  b = float64()       # 强制设为double
)

# 使用调整后的schema读取数据集
csvs <- open_dataset(
  sources = "data/", 
  format = "csv",
  schema = final_schema
)

csvs |> glimpse()

Python 解决方案

方案1:读取全部行推断类型+自动类型提升

import os
import pyarrow as pa
import pyarrow.dataset as ds

# 配置CSV读取规则:读取全部行推断类型
csv_read_options = pa.csv.ReadOptions(infer_schema_length=-1)
csv_format = ds.CsvFormat()

# 获取每个CSV文件的独立schema
file_paths = [f"data/{f}" for f in os.listdir("data") if f.endswith(".csv")]
schemas = []
for path in file_paths:
    table = pa.csv.read_csv(path, read_options=csv_read_options)
    schemas.append(table.schema)

# 合并schema,允许int64提升为double
unified_schema = schemas[0]
for schema in schemas[1:]:
    unified_schema = unified_schema.merge(schema, promote=True)

# 使用合并后的schema读取数据集
dataset = ds.open_dataset(
    "data/",
    format="csv",
    schema=unified_schema,
    format_options=csv_format
)

# 查看结果
print(dataset.schema)
print(dataset.to_table().to_pandas())

方案2:仅修改特定列类型

import pyarrow as pa
import pyarrow.dataset as ds

# 先读取足够多的行推断基础schema
temp_dataset = ds.open_dataset("data/", format="csv", infer_schema_length=100000)
base_schema = temp_dataset.schema

# 调整指定列的类型(这里是列b改为float64)
new_fields = []
for field in base_schema.fields:
    if field.name == "b":
        new_fields.append(pa.field(field.name, pa.float64()))
    else:
        new_fields.append(field)
final_schema = pa.schema(new_fields)

# 使用调整后的schema读取数据集
dataset = ds.open_dataset(
    "data/",
    format="csv",
    schema=final_schema
)

print(dataset.schema)
print(dataset.to_table().to_pandas())

补充说明

  • infer_schema_length=-1会读取整个文件推断类型,若文件极大,可设置一个足够大的数值(如1000000)覆盖可能出现类型转换的行,平衡性能与准确性。
  • 合并schema时的promote=True是关键,它允许Arrow将兼容的数值类型自动提升(如int64→float64),避免类型不兼容错误。
  • 手动指定schema时,只需修改需要调整的列,其他列可保留自动推断的类型,无需枚举所有列。

内容的提问来源于stack exchange,提问作者falsePockets

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 13:43:10