我试图使用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?
答案 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")]
将为此示例生成相同的输出。