将两位数年份转换为正确世纪的四位数年份

问题描述 投票:0回答:3

如果日期向量有两位数的年份,

mdy()
将 00 到 68 之间的年份转换为 21 世纪,将 69 到 99 之间的年份转换为 20 世纪。例如:

library(lubridate)    
mdy(c("1/2/54","1/2/68","1/2/69","1/2/99","1/2/04"))

给出以下输出:

Multiple format matches with 5 successes: %m/%d/%y, %m/%d/%Y.
Using date format %m/%d/%y.
[1] "2054-01-02 UTC" "2068-01-02 UTC" "1969-01-02 UTC" "1999-01-02 UTC" "2004-01-02 UTC"

事后我可以通过从不正确的日期中减去 100 将 2054 和 2068 变成 1954 和 1968 来解决这个问题。但是有没有更优雅、更不容易出错的解析两位数日期的方法,以便它们在解析过程本身?

更新: 在@JoshuaUlrich 向我指出

strptime
之后,我发现了this question,它处理的问题与我的类似,但使用的是基础R。

这似乎是对 R 中日期处理的一个很好的补充,可以通过某种方式来处理日期解析函数中两位数日期的世纪选择截止值。

r date lubridate
3个回答
38
投票

这是一个允许您执行此操作的函数:

library(lubridate)
x <- mdy(c("1/2/54","1/2/68","1/2/69","1/2/99","1/2/04"))


foo <- function(x, year=1968){
  m <- year(x) %% 100
  year(x) <- ifelse(m > year %% 100, 1900+m, 2000+m)
  x
}

试试看:

x
[1] "2054-01-02 UTC" "2068-01-02 UTC" "1969-01-02 UTC" "1999-01-02 UTC"
[5] "2004-01-02 UTC"

foo(x)
[1] "2054-01-02 UTC" "2068-01-02 UTC" "1969-01-02 UTC" "1999-01-02 UTC"
[5] "2004-01-02 UTC"

foo(x, 1950)
[1] "1954-01-02 UTC" "1968-01-02 UTC" "1969-01-02 UTC" "1999-01-02 UTC"
[5] "2004-01-02 UTC"

这里的神奇之处在于使用模运算符

%%
返回除法的小数部分。所以
1968 %% 100
产生 68.


3
投票

我刚刚遇到了这个完全相同的错误/功能。

我最终编写了以下两个快速函数来帮助将 excel 类型的日期(这是我得到最多的)转换为 R 可以使用的东西。

接受的答案没有错——只是我不想加载太多包。

首先是拆分替换岁月的帮手……

year1900 <- function(dd_y, yrFlip = 50)
{
    dd_y <- as.numeric(dd_y)
    dd_y[dd_y > yrFlip] <- dd_y[dd_y > yrFlip] + 1900
    dd_y[dd_y < yrFlip] <- dd_y[dd_y < yrFlip] + 2000
    return(dd_y)
}

由根据类型“修复”您的 Excel 日期的函数使用:

XLdate <- function(Xd, type = 'b-Y')
{
    switch(type,
        'b-Y' = as.Date(paste0(substr(Xd, 5, 9), "-", substr(Xd, 1, 3), "-01"), format = "%Y-%b-%d"),
        'b-y' = as.Date(paste0(year1900(substr(Xd, 5, 6)), "-", substr(Xd, 1, 3), "-01"), 
                        format = "%Y-%b-%d"),
        'Y-b' = as.Date(paste0(substr(Xd, 1, 3), "-", substr(Xd, 5, 9), "-01"), format =     "%Y-%b-%d")
        )
}

希望这有帮助。


0
投票

另一种选择是:

xxx <- c("01-Jan-54","01-Feb-68","01-Aug-69","01-May-99","01-Jun-04", "
       31-Dec-68","01-Jan-69", "31-Dec-99")

.

dmy(paste0(sub("\\d\\d$","",xxx) , ifelse( (tt <- 
   sub("\\d\\d-\\D\\D\\D-","",xxx)  ) > 20 ,paste0("19",tt),paste0("20",tt))))

虽然没有解决方案是优雅的或简短的。 我认为如果 lubridate 只是添加一个选项来指定截止日期会更好。

© www.soinside.com 2019 - 2024. All rights reserved.