【问题标题】:error with lubridate formatting when performing conditional assignment with data.table in R在 R 中使用 data.table 执行条件赋值时,lubridate 格式出现错误
【发布时间】:2016-09-02 16:00:06
【问题描述】:

我有一个带有日期列的 data.table。我需要创建一个新列,根据原始日期是在某个日期之前还是之后添加 1 年或 2 年。

library(data.table); library(lubridate)

name  = c("A", "B", "C")
paid  = c("5/30/2016", "6/30/2016", "7/30/2016")
data  = data.table(name,paid)

new_release = mdy("6/1/2017")

data[, paid := mdy(paid)]

data[, change_date:= ifelse(paid + years(1) < new_release, 
                            paid + years(2), paid +years(1)) ]

我得到下面的结果。 lubridate 无法将其转换为日期。我试过用mdy 包装ifelse 语句,但这也不起作用。我知道条件语句正在工作,因为如果您用TRUE/FALSE 替换分配,它会正确分配值。

> data
   name       paid change_date
1:    A 2016-05-30  1527638400
2:    B 2016-06-30  1498780800
3:    C 2016-07-30  1501372800
> str(data)
Classes ‘data.table’ and 'data.frame':  3 obs. of  3 variables:
 $ name       : chr  "A" "B" "C"
 $ paid       : POSIXct, format: "2016-05-30" "2016-06-30" "2016-07-30"
 $ change_date: num  1.53e+09 1.50e+09 1.50e+09
 - attr(*, ".internal.selfref")=<externalptr>

【问题讨论】:

    标签: r data.table conditional lubridate


    【解决方案1】:

    我只是将 lubdridate 排除在外,并使用基本的 Date 类型来完成这一切:

    library(data.table)
    
    name  <- c("A", "B", "C")
    paid  <- as.Date(c("2016-05-30", "2016-06-30", "2016-07-30"))
    data  <- data.table(name,paid)
    
    new_release <- as.Date("2017-06-01")
    year <- 365.25
    
    data[, change_date:= as.Date(ifelse(paid + year < new_release, 
                                        paid + year*2, 
                                        paid + year)) ]
    

    然后:

    R> data[]
       name       paid change_date
    1:    A 2016-05-30  2018-05-30
    2:    B 2016-06-30  2017-06-30
    3:    C 2016-07-30  2017-07-30
    R> 
    

    但是ifelse()data.table 的上下文中感觉很奇怪。这是一个替代方案:

    R> data[, cdate := paid+year ]                              # baseline
    R> data[paid + year < new_release, cdate := paid + 2*year]  # 
    R> data[]
       name       paid change_date      cdate
    1:    A 2016-05-30  2018-05-30 2018-05-30
    2:    B 2016-06-30  2017-06-30 2017-06-30
    3:    C 2016-07-30  2017-07-30 2017-07-30
    R> 
    

    【讨论】:

      【解决方案2】:

      问题在于ifelse 去除了属性并因此删除了日期格式(请参阅:?ifelse)。要恢复日期格式,您可以使用 origin = '1970-01-01'ifelse 语句包装在 as.Date 中:

      data[, change_date := as.Date(ifelse(paid + years(1) < new_release, 
                                           paid + years(2), 
                                           paid + years(1)), 
                                    origin = '1970-01-01')]
      

      给出:

      > data
         name       paid change_date
      1:    A 2016-05-30  2018-05-30
      2:    B 2016-06-30  2017-06-30
      3:    C 2016-07-30  2017-07-30
      

      或者通过将paid 列的类分配给change_date 列来更正它:

      data[, change_date := ifelse(paid + years(1) < new_release, 
                                   paid + years(2), 
                                   paid + years(1))]
      class(data$change_date) <- class(data$paid)
      

      这会给你同样的结果。


      ifelse 的替代方案可以实现相同的效果(仍然使用lubridate):

      data[, change_date := paid + years(as.numeric((paid + years(1) < new_release) + 1))]
      

      给予:

      > data
         name       paid change_date
      1:    A 2016-05-30  2018-05-30
      2:    B 2016-06-30  2017-06-30
      3:    C 2016-07-30  2017-07-30
      

      【讨论】:

        猜你喜欢
        • 2020-07-16
        • 2022-11-25
        • 1970-01-01
        • 2023-01-31
        • 2021-12-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多