lapply找到不按预期工作的行的最大值

时间:2017-03-23 18:06:38

标签: r data.table lapply

我试图使用lapply在data.table的行中找到最大日期。我有一些行,其中行中的所有值都是NA,在这种情况下,我想返回一个特定的日期。我写了一个函数来做到这一点,但我没有得到我期望的结果。

library(data.table)

my.max = function(x){
  if(all(is.na(x))){
    return(as.Date("9999-12-01")) #we can use this to identify which BPIDs have no end date
  }else{
    return(max(x, na.rm = T))
  }
}

DT = data.table("Date1" = c(as.Date("2015-12-30"),NA, NA), "Date2" = c(as.Date("2013-02-04"), as.Date("2014-01-01"), NA))
DT[ , "Row" := 1:.N]

DT[ , "Max_Date" := lapply(.SD, my.max), by = .(Row), .SDcols = c("Date1", "Date2")]

返回

> DT
        Date1      Date2 Row   Max_Date
1: 2015-12-30 2013-02-04   1 2015-12-30
2:       <NA> 2014-01-01   2 9999-12-01
3:       <NA>       <NA>   3 9999-12-01

因此,如果所有值都是NA,它确实有效,但如果其中一个值为NA,则它也返回9999-12-01。我将打印函数放入my.max中以查明发生了什么,看起来它一次传入一个x值。这解释了为什么all(is.na(x))是真的,但我希望它传递给行中两个日期的向量。否则,它将如何知道最大值是多少?

如何更改我的功能,只有当其他两个日期都是NA时才返回9999-12-01?

2 个答案:

答案 0 :(得分:1)

试试这个:

std::hash()

答案 1 :(得分:1)

这是一种可行的方法。它在{}中封装了多个语句,形成一个代码块:

DT[, "this" := {temp=pmax(Date1, Date2, na.rm=TRUE);
                temp[is.na(temp)] = as.Date("9999-12-01"); temp}]

返回

DT
        Date1      Date2       this
1: 2015-12-30 2013-02-04 2015-12-30
2:       <NA> 2014-01-01 2014-01-01
3:       <NA>       <NA> 9999-12-01

数据

DT = data.table("Date1" = c(as.Date("2015-12-30"),NA, NA),
                "Date2" = c(as.Date("2013-02-04"), as.Date("2014-01-01"), NA))

这样,你不必遍历每一行都很慢。

虽然我不建议按行处理......

DT[ , "Row" := 1:.N]
DT[ , "Max_Date" := my.max(unlist(.SD)), by = .(Row), .SDcols = c("Date1", "Date2")]

将为此示例生成相同的输出。