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

如何用Python读取Parquet元数据中R存储的data.table?

在Python中解析R写入Parquet的元数据(data.table属性)

问题背景

我用R的data.table和arrow包创建了一个Parquet文件,其中主数据是一个data.table,同时给它附加了另一个作为元数据的data.table。R环境下可以轻松读取这份元数据,但在Python中用pyarrow读取时,拿到的是无法直接识别的二进制数据,想知道如何解析这份元数据并转为DataFrame。

R中创建带元数据的Parquet文件

library(data.table)
library(arrow)
dt = data.table(x = c(1, 2, 3), y = c("a", "b", "c"))
dt2 = data.table(a = 22222, b = 45555)

attr(dt, "dt_meta") = dt2
tb = arrow_table(dt)
tb$metadata

write_parquet(tb, "file.parquet")

R中读取元数据的方式

# 方式1:通过open_dataset读取
dt = open_dataset("file.parquet")
dt$metadata$r$attributes$dt_meta

# 方式2:直接读取文件
dt2 = read_parquet("file.parquet")
attributes(dt2)$dt_meta

Python中遇到的问题

用pyarrow读取Parquet元数据时,r字段返回的是二进制数据,无法直接解析:

import pyarrow.parquet as pq
mt = pq.read_metadata("file.parquet")
metadata = mt.metadata[b'r']
metadata

输出的二进制内容:

b'A\n3\n263169\n197888\n5\nUTF-8\n531\n2\n531\n3\n16\n2\n262153\n10\ndata.table\n262153\n10\ndata.frame\n22\n22\n254\n254\n16\n2\n262153\n1\nx\n262153\n1\ny\n787\n2\n14\n1\n22222\n14\n1\n45555\n1026\n1\n262153\n5\nnames\n16\n2\n262153\n1\na\n262153\n1\nb\n1026\n1\n262153\n9\nrow.names\n13\n2\nNA\n-1\n1026\n1\n262153\n5\nclass\n16\n2\n262153\n10\ndata.table\n262153\n10\ndata.frame\n1026\n1\n262153\n17\n.internal.selfref\n22\n22\n254\n254\n16\n2\n262153\n1\na\n262153\n1\nb\n254\n1026\n1023\n16\n3\n262153\n5\nclass\n262153\n17\n.internal.selfref\n262153\n7\ndt_meta\n254\n531\n2\n254\n254\n1026\n1023\n16\n2\n262153\n1\nx\n262153\n1\ny\n254\n1026\n1023\n16\n2\n262153\n10\nattributes\n262153\n7\ncolumns\n254\n'

解析方案

这份二进制数据是R用serialize()函数生成的序列化对象,不是普通文本编码,必须用支持R反序列化的工具处理,以下是两种可行方法:

方法1:用rpy2直接解析

rpy2可以在Python中调用R的反序列化逻辑,无需临时文件:

  1. 先安装依赖:pip install rpy2
  2. 执行代码:
import pyarrow.parquet as pq
from rpy2.robjects import r, pandas2ri

# 读取Parquet元数据
mt = pq.read_metadata("file.parquet")
r_serialized = mt.metadata[b'r']

# 开启R与pandas的数据转换支持
pandas2ri.activate()

# 调用R的unserialize解析二进制,再转为DataFrame
r_obj = r['unserialize'](r_serialized)
dt_meta_df = pandas2ri.rpy2py(r_obj.rx2('attributes').rx2('dt_meta'))

print(dt_meta_df)

输出结果:

a      b
0  22222  45555

方法2:用pyreadr解析

pyreadr专门处理R相关文件,需要通过临时文件中转:

  1. 安装依赖:pip install pyreadr
  2. 执行代码:
import pyarrow.parquet as pq
import pyreadr
import tempfile
import os

# 读取元数据二进制
mt = pq.read_metadata("file.parquet")
r_serialized = mt.metadata[b'r']

# 将二进制写入临时RDS文件
with tempfile.NamedTemporaryFile(delete=False, suffix='.rds') as tmp:
    tmp.write(r_serialized)
    tmp_path = tmp.name

# 读取并解析临时文件
result = pyreadr.read_r(tmp_path)
# 提取dt_meta属性
dt_meta_df = result[None].attrs['dt_meta']

# 清理临时文件
os.unlink(tmp_path)

print(dt_meta_df)

同样能得到目标DataFrame。

关键说明

  • R的arrow包写入Parquet时,会把R对象的属性用serialize()序列化后存入元数据的r字段,所以Python无法直接解码,必须借助R的反序列化逻辑。
  • rpy2需要本地有R环境支持,操作更直接;pyreadr对环境依赖稍弱,但需要临时文件中转。

内容的提问来源于stack exchange,提问作者julien.leroux5

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 12:57:14