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
相关产品推荐
相关产品推荐

