r语言 - 尝试从 5 位或 6 位数字中提取日期



我正在尝试从数字中提取日期。日期存储为 11 位个人 ID 号(日期-月-年(的前 6 位数字。不幸的是,基于云的数据库(REDCap(输出被格式化为数字,因此在当月的前九天出生的人中,前导零最终以10位ID号而不是11位ID号结束。我设法提取了与日期相对应的 6 或 5 位数字,即 311230 年 12 月 31 日,或 11230 年 1230 月 1930 日。我最终遇到了两个我无法解决的问题。

假设我们使用以下数字:

dato <- c(311230, 311245, 311267, 311268, 310169, 201104, 51230, 51269, 51204)

我将它们转换为字符串,然后应用 as。Date(( 函数:

datostr <- as.character(dato)
datofinal <- as.Date(datostr, "%d%m%y")
datofinal

我遇到的问题是:

  • 五位数字(例如 11230(报告为 NA。
  • 识别六位数字,但 1.1.1969 之前出生的数字将报告并添加 100 年,即 010160 转换为 2060.01.01

我相信对于那些更了解 R 的人来说,这肯定很容易,但是,我有点努力解决这个问题。任何帮助将不胜感激。

问候 比约恩

如果您的 5 位数字真的只需要用零填充,那么

dato_s <- sprintf("%06d", dato)
dato_s
# [1] "311230" "311245" "311267" "311268" "310169" "201104" "051230" "051269" "051204"

从那里,您关于"1969 年之前的日期">的问题,请查看'%y'模式?strptime

'%y' Year without century (00-99).  On input, values 00 to 68 are
prefixed by 20 and 69 to 99 by 19 - that is the behaviour
specified by the 2018 POSIX standard, but it does also say
'it is expected that in a future version the default century
inferred from a 2-digit year will change'.

因此,如果您有特定的隔年,则需要在发送到as.Date之前添加世纪(使用strptime-模式(。

dato_d <- as.Date(gsub("([0-4][0-9])$", "20\1",
gsub("([5-9][0-9])$", "19\1", dato_s)),
format = "%d%m%Y")
dato_d
# [1] "2030-12-31" "2045-12-31" "1967-12-31" "1968-12-31" "1969-01-31" "2004-11-20"
# [7] "2030-12-05" "1969-12-05" "2004-12-05"

在这种情况下,我假设 50-99 将是 1900,其他一切都是 2000。如果您需要 40 秒或 30 秒,请随意调整模式:在第二个模式中添加数字(例如,[3-9](并从第一个模式中删除(例如,[0-2](,确保所有十年都包含在一个模式中,而不是"两者都不是"也不是"也不是"两个"。

借用艾伦的回答,我喜欢now()的假设(因为你确实提到了"生于">(。如果没有lubridate,请尝试以下操作:

dato_s <- sprintf("%06d", dato)
dato_d <- as.Date(dato_s, format = "%d%m%y")
dato_d[ dato_d > Sys.Date() ] <-
as.Date(sub("([0-9]{2})$", "19\1", dato_s[ dato_d > Sys.Date() ]), format = "%d%m%Y")
dato_d
# [1] "1930-12-31" "1945-12-31" "1967-12-31" "1968-12-31" "1969-01-31" "2004-11-20"
# [7] "1930-12-05" "1969-12-05" "2004-12-05"

您可以使用lubridate来简化此操作,并注意没有人可以拥有当前时间的未来出生日期:

library(lubridate)
dato <- dmy(sprintf("%06d", dato))
dato[dato > now()] <- dato[dato > now()] - years(100)
dato
#> [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"

当然,如果没有进一步的信息,这种方法将无法(任何其他方法(能够挑选出 100 岁以上人群的边缘情况。这可能很容易从上下文中确定。

创建于 2020-06-29 由 reprex 软件包 (v0.3.0(

将五位数的"数字"转换为六位数很简单:x <- stringr::str_pad(x, 6, pad="0")或类似的方法就可以了。

你多年的问题是重新审视千年虫。 您必须咨询编译您的数据的人,以了解他们使用了哪些假设。

我怀疑1970年12月31日或之前的所有日期都会受到影响,而不仅仅是1960年1月1日之前的日期。 这是因为as.Date在决定如何处理两位数年份时使用默认原点 01Jan1970。 因此,您的解决方案是在转换中选择合适的来源来修复此数据集。 像d <- as.Date(x, origin="1900-01-01"). 然后开始使用四位数的年份!;)

最新更新