【问题标题】:ifelse with data.tableifelse 与 data.table
【发布时间】:2017-10-01 00:06:52
【问题描述】:

这是我的数据:

BuyDate       SellDate     Number
2015-01-01    NA           1
2015-01-01    2015-01-03   1
2015-01-01    2015-01-03   -1
2016-12-09    NA           -1

我想创建一个新列Start,所以我可以得到以下结果。

BuyDate       SellDate     Number    Start
2015-01-01    NA           1         2015-01-01
2015-01-01    2015-01-03   1         2015-01-01
2015-01-01    2015-01-03   -1        2015-01-03
2016-12-09    NA           -1        2016-12-09

代码是:

data[,Start:=ifelse(Number=="1",BuyDate,ifelse(is.na(SellDate),BuyDate,SellDate))]

但是,我得到:

BuyDate       SellDate     Number    Start
2015-01-01    NA           1         1420070400
2015-01-01    2015-01-03   1         1420070400
2015-01-01    2015-01-03   -1        1420243200
2016-12-09    NA           -1        1481241600

我该如何解决这个问题?

str(data)
Classes ‘data.table’ and 'data.frame':
 $BuyDate : POSIXct, format: "2015-01-01" "2015-01-01" "2015-01-01" "2016-12-09"
 $SellDate: POSIXct, format: NA "2015-01-03" "2015-01-03" NA
 $Number  : chr  "1" "1" "-1" "-1"

【问题讨论】:

    标签: r date if-statement data.table


    【解决方案1】:

    Start 变量必须转换为 POSIXct:

    require(dplyr)
    data[, Start:= (ifelse(Number=="1",BuyDate,ifelse(is.na(SellDate),BuyDate,SellDate)) %>% 
             as.POSIXct(origin = "1970-01-01"))]
    

    添加:

    以下代码使用dplyr 运行。我不确定为什么 dplyr 不能与上面的示例一起使用。

    library(dplyr)
    library(data.table)
    
    dates <- as.POSIXct(Sys.Date() + 1:20)
    dates2 <- as.POSIXct(Sys.Date() + 21:40)
    
    tmp <- data.table(date = dates, date2 = dates2)
    tmp[runif(20)>.8, date2 := NA]
    tmp[, date3 := (ifelse(is.na(date2), date, date2) %>% as.POSIXct(origin = "1970-01-01"))]
    

    【讨论】:

    • 加载整个包只是为了避免做as.POSIXct(ifelse(...), origin="1970-01-01")?...
    • 我猜,如果你加载 magrittr,这将运行。我发现它更适合 data.table。
    • @Frank 你的意思是magrittr 包?
    • @PeterChen 是的。它支持%&gt;% 运算符等。所以像Start := replace(Number==1, Buydate) %&gt;% replace(is.na(SellDate), BuyDate) %&gt;% as.POSIXct(origin = "1970-01-01") 这样的东西应该可以工作。
    • 或者Start := SellDate %&gt;% replace(Number==1, Buydate) %&gt;% replace(is.na(SellDate), BuyDate) %&gt;% as.POSIXct(origin = "1970-01-01"),我想。 (尚未测试。)
    【解决方案2】:

    最好不要使用ifelse,因为'Date'可能会被强制转换为integer存储值,相反,我们将(:=)'Start'分配为'SellDate',然后指定逻辑条件in 'i' 用于识别 'Start' 中的 'NA' 元素或 'Number' 中的 1 并将 (:=) 'BuyDate' 中对应于 'i' 的元素分配给 'Start'

    data[, Start := SellDate][Number==1, Start := BuyDate
              ][is.na(Start), Start := BuyDate][]
    

    正如@Cath 在 cmets 中提到的,这可以分两步完成

    data[, Start := SellDate][(Number==1) | is.na(Start), Start := BuyDate][]
    

    【讨论】:

    • 你能解释一下你的答案吗,我觉得很好但我不能完全理解。
    • 为什么不只是data[, Start := SellDate][(Number==1) | is.na(Start), Start := BuyDate][]
    • @Cath 感谢 cmets。电话有点忙,没能早点回复
    • @Cath Minor plus 可能是自动索引,尤其是在github.com/Rdatatable/data.table/issues/1068 之后,再一次,在github.com/Rdatatable/data.table/issues/1453 之后,你的方式也会使用它。
    猜你喜欢
    • 2016-10-13
    • 2017-03-11
    • 1970-01-01
    • 1970-01-01
    • 2020-04-20
    • 1970-01-01
    • 1970-01-01
    • 2016-05-21
    • 2019-10-27
    相关资源
    最近更新 更多