在data.table R

时间:2016-07-12 10:10:32

标签: r data.table lapply

我在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。我想念什么才能得到我想要的东西?

2 个答案:

答案 0 :(得分:0)

经过多次尝试后,答案是data.table将列视为变量,而.SD是一个列表,其元素是列作为变量,因此在应用函数时,在此处进行测试,此函数必须将列表作为参数。

以下是您应该更改的内容:

testList <- function(x) 
{
  lapply(x,test)
}

x1[,lapply(.SD,testList)]

如果有人知道其他解决方案,请随时分享。

答案 1 :(得分:0)

首先,我无法在不抛出错误的情况下运行您的示例。 data.tables的第二列属于&#34; Date&#34;,但""条目不是日期。当它打印时,它的格式看起来像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)
}