我在data.table中使用lapply
时遇到问题。下面是两个示例:
library(data.table)
library(lubridate)
test <- function(x)
{
if(is.na(x)) return(NA)
if(x=="") return(NA)
if(substr(x,3,3)=="/") return(as_date(x,"%d/%m/%Y"))
return(2)
}
x1<-data.table(v1=c("","07/06/2016","",NA), v2=c("2004-06-18","","2004-06-18","2004-06-18"))
x1[,lapply(.SD,test)]
x2<-data.table(v1=c("2004-06-19","2004-06-18","",NA),v2=c("2004-06-18","","2004-06-18","2004-06-18"))
x2[,lapply(.SD,test)]
在第一个例子中,lapply
后的第一列充满了NA
,但我想得到的是NA, 2016-06-07, NA, NA
。
在第二个示例中,第一列的最后两行是错误的,因为每行包含 2 但在我看来应该包含 NA
。
我不明白 R 如何考虑这里的NA
。我错过了什么才能得到我想要的东西?
经过多次尝试,答案是data.table
将列视为变量,而.SD
是一个列表,其元素是列作为变量,因此在应用函数时,作为此处的测试,该函数必须将列表作为参数。
以下是您应该更改的内容:
testList <- function(x)
{
lapply(x,test)
}
x1[,lapply(.SD,testList)]
如果有人知道其他解决方案,请不要犹豫,分享。
首先,我无法在不抛出错误的情况下运行您的示例。data.tables 的第二列属于类"Date",但""
条目不是日期。打印时,它的格式看起来像NA
。尝试运行 is.na(x1$v2[2])
并x1$v2[2] == ""
。
此外,您似乎在矢量化方面存在问题。
尝试运行test(x1$v1)
。请注意警告消息。 is.na(x)
返回逻辑向量,但if
仅使用向量中的第一个元素。
In addition: Warning message:
In if (is.na(x)) return(NA) :
the condition has length > 1 and only the first element will be used
您可以通过应用于每一行来修复它:
x1[, lapply(.SD, test), by = 1:nrow(x1)]
否则,您需要修改 test
函数以接受字符串向量并返回结果向量。但是您确实应该考虑返回单个类型的向量。
最后,我不明白在这个例子中lubridate
的目的。为什么不使用as.Date(x,"%d/%m/%Y")
.你从as_date
中得到了什么?
编辑
您可以重写函数以处理向量:
test <- function(x)
{
ans <- rep.int(2, length(x))
ans[is.na(x) | x == ""] <- NA
dates <- grepl('../', x)
ans[dates] <- as_date(x[dates], "%d/%m/%Y")
return(ans)
}