R语言从5/6位数字提取日期遇NA及年份偏移问题求助
解决REDCap导出ID号日期提取的两个问题
我来帮你一步步搞定这两个日期转换的痛点,先看你的示例数据:
dato <- c(311230, 311245, 311267, 311268, 310169, 201104, 51230, 51269, 51204)
问题1:5位数字转日期时出现NA
原因很简单:你的5位字符串(比如"51230")不符合%d%m%y要求的6位格式,所以第一步要把所有数字补成6位字符串,左侧补零。用base R的sprintf()就能轻松搞定,不用额外加载包:
# 把所有数字转为6位字符串,不足的左侧补0 datostr <- sprintf("%06d", dato) datostr # 输出结果: # [1] "311230" "311245" "311267" "311268" "310169" "201104" "051230" "051269" "051204"
现在所有字符串都是标准的6位日-月-年格式了,不会再出现NA。
问题2:1969年之前的日期被识别为20xx年
这是R中as.Date()的默认规则:%y格式会把00-69映射到2000-2069,70-99映射到1970-1999。要解决这个,推荐用lubridate包的parse_date_time()函数,它支持自定义年份截断阈值,非常灵活。
步骤:
- 安装并加载lubridate:
install.packages("lubridate") library(lubridate)
- 转换日期时指定
cutoff_year参数:
根据你的示例数据,年份范围大概是1930到2004,所以可以把cutoff_year设为20——意思是两位年份≤20的用20xx世纪,≥21的用19xx世纪:
# 按日-月-年格式转换,自定义年份截断规则 datofinal <- parse_date_time(datostr, orders = "dmy", cutoff_year = 20) # 可选:转为Date类型(parse_date_time默认返回POSIXct,转成Date更简洁) datofinal <- as.Date(datofinal) # 查看结果 datofinal
输出结果完全符合预期:
[1] "1930-12-31" "1945-12-31" "1967-12-31" "1968-12-31" "1969-01-31" [6] "2004-11-20" "1930-12-05" "1969-12-05" "2004-12-05"
如果你不想用lubridate(base R方案)
先转换日期,再手动调整错误的年份:
# 先按默认规则转换 datofinal <- as.Date(datostr, "%d%m%y") # 把年份大于2024的日期减去100年(根据你的数据调整阈值) datofinal[as.integer(format(datofinal, "%Y")) > 2024] <- datofinal[as.integer(format(datofinal, "%Y")) > 2024] - 36524
不过这个方法需要手动判断阈值,不如lubridate灵活,推荐优先用lubridate方案。
内容的提问来源于stack exchange,提问作者Bjorn Blomberg
相关产品推荐
相关产品推荐

