39

如果日期向量有两位数的年份,则将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我发现了这个问题,它处理的问题与我的类似,但使用的是基础 R。

似乎 R 中日期处理的一个很好的补充是在日期解析函数中处理两位数日期的世纪选择截止值。

4

3 回答 3

35

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

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。

于 2012-10-18T15:12:31.667 回答
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")
        )
}

希望这可以帮助。

于 2013-06-01T09:27:33.120 回答
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 只是添加一个选项来指定截止日期会更好。

于 2017-06-28T14:51:44.330 回答