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

segmentio/parquet无法读取Julia或Python生成的Parquet文件问题

问题:Go读取Julia生成的Parquet文件返回零值(无错误但无有效数据)

我基于segmentio/arrow仓库实现的Go代码,读取Python或Julia生成的Parquet文件时出现异常:调用parquet.ReadFile("file")后,返回的行中int64字段全为0,字符串字段全为空字符串,ZSTD、GZIP、SNAPPY三种压缩编码下均出现此问题。

Go读取代码如下:

type FiRowType struct{ x1, x2, x3 int64 }
func RdFiFile() {
    rows, err := parquet.ReadFile[FiRowType]("fileName_ZSTD.parquet")
    if err != nil {
        log.Fatal(err)
    }
    for _, c := range rows {
        fmt.Printf("%+v\n", c)
    }
}

type FsRowType struct{ x1, x2, x3 string }
func RdFsFile() {
    rows, err := parquet.ReadFile[FsRowType]("fileName_ZSTD.parquet")
    if err != nil {
        log.Fatal(err)
    }
    for _, c := range rows {
        fmt.Printf("%+v\n", c)
    }
}

代码无错误返回(err == nil),行数、列数与文件一致,元数据(创建者、日期等)也能正常读取。

生成Parquet文件的Julia代码:

using Parquet
function WrForGo( )
  min = 1 
  max = 10
  # 大小为(10,3)的数组,ai为整数类型,as为字符串类型
  ai = Array{Int64, 2}(undef, 10,3)
  as = Array{String, 2}(undef, 10,3)
  for i =1:max
      for j=1:3
        as[i,j] = string(i, pad=2) * "_" * string(j,pad=2)
        ai[i,j] = (j-1)*10 + i
      end
    end

    dfi = DataFrame(ai, :auto) ; dfs = DataFrame(as, :auto)
    print( dfi ) ;  print( dfs )
    Parquet.write_parquet( prqDir * "fi_ZSTD.parquet", compression_codec = "ZSTD", dfi)
    Parquet.write_parquet( prqDir * "fs_ZSTD.parquet", compression_codec = "ZSTD", dfs)

    Parquet.write_parquet( prqDir * "fi_GZIP.parquet", compression_codec = "GZIP", dfi)
    Parquet.write_parquet( prqDir * "fs_GZIP.parquet", compression_codec = "GZIP", dfs)

    Parquet.write_parquet( prqDir * "fi_SNAPPY.parquet", compression_codec = "SNAPPY", dfi)
    Parquet.write_parquet( prqDir * "fs_SNAPPY.parquet", compression_codec = "SNAPPY", dfs)

end

核心原因

字段名称不匹配:

  • Julia中DataFrame(ai, :auto)从二维数组创建DataFrame时,默认生成的列名是Column1、Column2、Column3,而非预期的x1、x2、x3。
  • segmentio/arrow的parquet库默认将Go结构体字段名直接映射为Parquet列名(大小写敏感),找不到对应列时会填充类型零值(int64为0,string为空)。

修复方案

方案1:修改Julia代码,指定匹配的列名

调整DataFrame创建逻辑,显式指定列名为x1、x2、x3:

# 将二维数组拆分为列向量,再指定列名
dfi = DataFrame([ai[:,1], ai[:,2], ai[:,3]], ["x1", "x2", "x3"])
dfs = DataFrame([as[:,1], as[:,2], as[:,3]], ["x1", "x2", "x3"])

生成的Parquet文件列名会与Go结构体字段完全匹配,读取时即可正确映射数据。

方案2:修改Go结构体,添加字段标签匹配Julia默认列名

若无法修改Julia代码,可为Go结构体字段添加parquet标签,对应Julia生成的默认列名:

type FiRowType struct{
    X1 int64  `parquet:"Column1"`
    X2 int64  `parquet:"Column2"`
    X3 int64  `parquet:"Column3"`
}

type FsRowType struct{
    X1 string `parquet:"Column1"`
    X2 string `parquet:"Column2"`
    X3 string `parquet:"Column3"`
}

注意:可通过Parquet查看工具(如parquet-tools)确认文件中的实际列名,确保标签与列名完全一致。

额外说明

segmentio/arrow的parquet库原生支持ZSTD、GZIP、SNAPPY压缩,字段匹配问题解决后,压缩相关的读取问题会自动消失。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 21:05:22