使用rbind向数据框追加行时为何某一值被修改?
问题:rbind追加带时区的POSIXct数据时出现值异常
处理带时区的datetime向量时,需将错误时区的时间调整到正确时区后输出为数据框,但使用rbind向空数据框逐行追加时,发现第三条观测的outTime值被错误修改(原应为2001-04-05 16:00:00 CDT,追加后变成2001-04-05 17:00:00)。
复现代码
toy_problem <- function(){ require("tidyverse") DateTime <- c("2001-04-06 01:20:00", # 输入日期时间 "2001-04-05 19:20:00", "2001-04-05 16:00:00", "2001-04-06 01:15:00") listZones <- c("America/Chicago", # 记录的时区(有误) "America/Chicago", "America/Chicago", "America/Chicago") trueZones <- c("America/Detroit", # 正确时区 "America/Detroit", "America/Chicago", "America/Detroit") # 创建空数据框 outFrame <- data.frame(inTime=NULL, outTime=NULL) for (i in 1:4) { # 循环处理每条观测 tReg <- ymd_hms(DateTime[i], tz=listZones[i]) # 转换为POSIXct格式 localTime <- with_tz(tReg,tzone=trueZones[i]) # 调整到正确时区 print(tReg) # 打印原始时间 print(localTime) # 打印调整后的时间 # 生成单行数据框 thisFrame <- data.frame(inTime=tReg, outTime=localTime) print(str(thisFrame)) # 检查单行数据结构 outFrame <- rbind(outFrame,thisFrame) # 追加到输出数据框 } print(outFrame) # 打印最终输出 }
问题输出
[1] "2001-04-06 01:20:00 CDT" [1] "2001-04-06 02:20:00 EDT" # 正确 'data.frame': 1 obs. of 2 variables: # 结构正常 $ inTime : POSIXct, format: "2001-04-06 01:20:00" $ outTime: POSIXct, format: "2001-04-06 02:20:00" NULL [1] "2001-04-05 19:20:00 CDT" [1] "2001-04-05 20:20:00 EDT" # 正确 'data.frame': 1 obs. of 2 variables: # 结构正常 $ inTime : POSIXct, format: "2001-04-05 19:20:00" $ outTime: POSIXct, format: "2001-04-05 20:20:00" NULL [1] "2001-04-05 16:00:00 CDT" [1] "2001-04-05 16:00:00 CDT" # 正确 'data.frame': 1 obs. of 2 variables: # 结构正常 $ inTime : POSIXct, format: "2001-04-05 16:00:00" $ outTime: POSIXct, format: "2001-04-05 16:00:00" NULL [1] "2001-04-06 01:15:00 CDT" [1] "2001-04-06 02:15:00 EDT" # 正确 'data.frame': 1 obs. of 2 variables: # 结构正常 $ inTime : POSIXct, format: "2001-04-06 01:15:00" $ outTime: POSIXct, format: "2001-04-06 02:15:00" NULL inTime outTime 1 2001-04-06 01:20:00 2001-04-06 02:20:00 # 正确 2 2001-04-05 19:20:00 2001-04-05 20:20:00 # 正确 3 2001-04-05 16:00:00 2001-04-05 17:00:00 # 错误!!! 4 2001-04-06 01:15:00 2001-04-06 02:15:00 # 正确
原因分析
- 核心问题是
data.frame结合rbind处理POSIXct对象时的时区强制一致性:前两条观测的outTime时区为EDT(America/Detroit),首次rbind后,outTime列的时区被固定为EDT。 - 第三条观测的
outTime时区为CDT(America/Chicago),rbind会强制将该值转换为列已有的EDT时区,但显示时未正确映射时区偏移,导致视觉上的时间值错误(底层时间戳实际正确,只是时区显示被强制替换)。
解决方案
方案1:用tibble替代data.frame
tibble支持同一列中存在不同时区的POSIXct对象,避免rbind强制统一时区:
# 修改空数据框创建部分 outFrame <- tibble(inTime = as.POSIXct(character()), outTime = as.POSIXct(character()))
方案2:向量化操作替代循环rbind
直接批量处理所有数据,避免逐行追加的问题,同时更符合tidyverse风格:
toy_problem_fixed <- function(){ require("tidyverse") DateTime <- c("2001-04-06 01:20:00", "2001-04-05 19:20:00", "2001-04-05 16:00:00", "2001-04-06 01:15:00") listZones <- c("America/Chicago", "America/Chicago", "America/Chicago", "America/Chicago") trueZones <- c("America/Detroit", "America/Detroit", "America/Chicago", "America/Detroit") # 向量化处理所有数据 outFrame <- tibble( inTime = ymd_hms(DateTime, tz = listZones), outTime = map2(inTime, trueZones, ~with_tz(.x, tzone = .y)) %>% do.call(c, .) ) print(outFrame) }
内容的提问来源于stack exchange,提问作者user23451421
相关产品推荐
相关产品推荐

