为何使用data.table与dplyr处理日期时部分结果变为NA?
问题:data.table/dplyr创建日期列时出现NA,base R无此问题
数据背景
数据存储在.txt文件中,格式如下:
"A" "M" "D" "Tmax" "Tmin" "1" 1931 1 1 35.4 19.7 "2" 1931 1 2 35.8 20.7 "3" 1931 1 3 37.7 23.9 "4" 1931 1 4 39.5 25.8 "5" 1931 1 5 29 22.8 "6" 1931 1 6 27.5 18.6 "7" 1931 1 7 20.4 15.6 "8" 1931 1 8 28.2 15.1 "9" 1931 1 9 31.2 14.6 "10" 1931 1 10 31 18.5
其中:A=年份,M=月份,D=日期。
问题重现
使用data.table处理出现NA
用read.table加载数据后,通过data.table语法创建fecha日期列:
datos_diarios <- data.table(subset(datos_diarios, A >= 1971)) datos_diarios[, fecha := strptime(paste0(A,'-',M,'-',D), format= '%Y-%m-%d', tz = 'America/Argentina/Buenos_Aires')]
结果部分日期解析为NA:
which(is.na(datos_diarios$fecha)) [1] 1119 6545 6863 7234 7598 7962 13513 13807 datos_diarios[1118:1120,] A M D Tmax Tmin fecha 1: 1974 1 22 25.0 21.9 1974-01-22 2: 1974 1 23 25.4 20.6 <NA> 3: 1974 1 24 29.7 20.5 1974-01-24
dplyr存在同样异常,base R无问题
使用dplyr处理时也会出现相同的NA,但用base R直接赋值则所有日期都能正常解析:
datos_diarios <- subset(datos_diarios, A >= 1971) datos_diarios$fecha <- strptime(paste0(datos_diarios$A,'-',datos_diarios$M,'-',datos_diarios$D),format= '%Y-%m-%d', tz = 'America/Argentina/Buenos_Aires') > which(is.na(datos_diarios$fecha)) integer(0) > datos_diarios[1118:1120,] A M D Tmax Tmin fecha 15728 1974 1 22 25.0 21.9 1974-01-22 15729 1974 1 23 25.4 20.6 1974-01-23 15730 1974 1 24 29.7 20.5 1974-01-24
问题原因
核心原因是时区America/Argentina/Buenos_Aires的夏令时切换规则:
这些NA对应的日期,是阿根廷当年夏令时开始/结束的过渡日期。以1974年1月23日为例,当时阿根廷的夏令时切换导致该日期的00:00:00时间点不存在(时钟从1月22日23:59直接跳到1月23日01:00)。
- data.table和dplyr在执行
strptime时,严格按照指定时区的规则解析时间字符串,当目标时间点在该时区不存在时,直接返回NA。 - base R直接赋值时,
strptime的解析逻辑存在差异:它会先将字符串解析为无时区的日期,再默认以UTC时区为基准转换到目标时区,或自动跳过时区有效性检查,从而避免了NA的产生。
解决方法
如果只需要日期信息而非精确时间,可以先通过as.Date解析(不涉及时区),再转换为带时区的POSIXct类型:
# data.table写法 datos_diarios[, fecha := as.POSIXct(as.Date(paste0(A,'-',M,'-',D)), tz = 'America/Argentina/Buenos_Aires')] # base R写法同理 datos_diarios$fecha <- as.POSIXct(as.Date(paste0(datos_diarios$A,'-',datos_diarios$M,'-',datos_diarios$D)), tz = 'America/Argentina/Buenos_Aires')
这种方式会自动将日期映射到该时区的有效时间点,不会产生NA。
内容的提问来源于stack exchange,提问作者ezequiel elias
相关产品推荐
相关产品推荐

