如何通过Parquet存储无时区日期实现R与Python数据帧跨语言互通
问题根因
R中未指定时区的POSIXct类型默认关联系统本地时区,Arrow跨语言序列化框架的默认规则会将这类未明确声明时区的时间值先转换为UTC时间戳再写入Parquet/Feather文件。pandas读取时会直接将该UTC时间戳映射为无时区的datetime64[ns]类型,最终导致时间数值出现本地时区与UTC的偏移差。
解决方案
方案1:R侧写入前转换无时区时间类型(推荐,一次修改双向无需额外处理)
在R侧写入文件前,将无时区属性的POSIXct列显式转换为Arrow原生的无时区时间戳类型,即可避免自动转UTC的逻辑,修改后的R代码如下:
rm(list=ls()) library(arrow) library(data.table) library(lubridate) outputFile <- 'D:/Temp/Test.parquet' outputFileFeather <- 'D:/Temp/Test.feather' dt <- data.table(Row=1:10, NoTZ = as.POSIXct('2021-10-22'), TZBris = as.POSIXct('2021-10-22', tz = 'Australia/Brisbane'), TZNY = as.POSIXct('2021-10-22', tz = 'America/New_York')) dt[, `:=`(NoTZ = NoTZ + hours(Row-1), TZBris = TZBris + hours(Row-1), TZNY = TZNY + hours(Row-1))] # 新增:将无时区的POSIXct列转换为Arrow无时区时间戳,禁止自动转UTC dt$NoTZ <- as_arrow_array(dt$NoTZ, type = timestamp(unit = "ns", timezone = NULL)) write_parquet(dt, outputFile) write_feather(dt, outputFileFeather)
修改后Python侧直接用原有代码读取,得到的NoTZ列就是无时区的datetime64[ns]类型,数值与R侧原始值完全一致,不会出现偏移。
方案2:批量处理多列无时区时间
如果存在多列无指定时区的POSIXct,可以批量转换:
# 找出所有无时区的POSIXct列 no_tz_cols <- names(dt)[sapply(dt, function(x) inherits(x, "POSIXct") && is.null(attr(x, "tzone")))] # 批量转换为Arrow无时区时间戳 dt[, (no_tz_cols) := lapply(.SD, function(x) as_arrow_array(x, type = timestamp(unit = "ns", timezone = NULL))), .SDcols = no_tz_cols]
双向互通说明
如果是Python侧生成的无时区datetime64[ns]列写入Parquet/Feather,R侧使用arrow包读取时会自动识别为无时区的POSIXct类型,数值完全匹配,无需额外转换。
内容的提问来源于stack exchange,提问作者Mark
相关产品推荐
相关产品推荐

