Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/71.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何加快R data.table中的缺失搜索过程_R_Data.table - Fatal编程技术网

如何加快R data.table中的缺失搜索过程

如何加快R data.table中的缺失搜索过程,r,data.table,R,Data.table,我正在为缺失值处理编写一个通用函数。数据可以有Char、numeric、factor和integer类型的列。数据示例如下所示 dt<-data.table( num1=c(1,2,3,4,NA,5,NA,6), num3=c(1,2,3,4,5,6,7,8), int1=as.integer(c(NA,NA,102,105,NA,300,400,700)), int3=as.integer(c(1,10,102,105,200,300,400,700)), cha1=

我正在为缺失值处理编写一个通用函数。数据可以有Char、numeric、factor和integer类型的列。数据示例如下所示

dt<-data.table(
  num1=c(1,2,3,4,NA,5,NA,6),
  num3=c(1,2,3,4,5,6,7,8),
  int1=as.integer(c(NA,NA,102,105,NA,300,400,700)),
  int3=as.integer(c(1,10,102,105,200,300,400,700)),
  cha1=c('a','b','c',NA,NA,'c','d','e'),
  cha3=c('xcda','b','c','miss','no','c','dfg','e'),
  fact1=c('a','b','c',NA,NA,'c','d','e'),
  fact3=c('ad','bd','cc','zz','yy','cc','dd','ed'),
  allm=as.integer(c(NA,NA,NA,NA,NA,NA,NA,NA)),
  miss=as.character(c("","",'c','miss','no','c','dfg','e')),
  miss2=as.integer(c('','',3,4,5,6,7,8)),
  miss3=as.factor(c(".",".",".","c","d","e","f","g")),
  miss4=as.factor(c(NA,NA,'.','.','','','t1','t2')),
  miss5=as.character(c(NA,NA,'.','.','','','t1','t2'))  
)

但结果很慢,另外,我还需要添加逻辑,也可以把“…”看作是缺失的。 所以我打算写这篇文章来说明缺失值识别

dt[miss5 %in% c(NA,'','.'),flag:=1]
但是在一个600万的记录集上,运行这个程序需要将近1秒的时间

dt[!nzchar(miss5),flag:=1]  takes close 0.14 secod to run.
我的问题是,我们是否可以有一个代码,其中花费的时间尽可能少,而我们可以查找丢失的值NA、blank和Dot(NA、“,”)


非常感谢您的帮助。

您可以循环浏览“未命中”列,并使用
set
创建相应的“标志”列

library(data.table)#v1.9.5+
ind <- grep('^miss', names(dt))
nm1 <- sub('miss', 'flag',names(dt)[ind])
dt[,(nm1) := 0]
for(j in seq_along(ind)){
     set(dt, i=which(dt[[ind[j]]] %in% c('.', '', NA)),j= nm1[j], value=1L)
  }
library(data.table)#v1.9.5+

ind
==
和%
中的
%经过优化,可自动使用二进制搜索(新功能:自动索引)。要使用它,我们必须确保:

a) 我们使用
dt[…]
而不是
set()
,因为它尚未在
set()
中实现

b) 当%
中指向
%的RHS的SEXPTYPE高于LHS时,自动索引将重新路由到基本R以确保结果正确(因为二进制搜索总是强制RHS)。因此,对于整数列,我们需要确保只传入
NA
,而不是

使用@akrun的数据,下面是代码和运行时间:

in_col = grep("^miss", names(dt), value=TRUE)
out_col = gsub("^miss", "flag", in_col)
system.time({
    dt[, (out_col) := 0L]
    for (j in seq_along(in_col)) {
        if (class(.subset2(dt, in_col[j])) %in% c("character", "factor")) {
            lookup = c("", ".", NA)
        } else lookup = NA
        expr = call("%in%", as.name(in_col[j]), lookup)
        tt = dt[eval(expr), (out_col[j]) := 1L]
    }
})
#    user  system elapsed 
#   1.174   0.295   1.476 
工作原理:

a) 我们首先将所有输出列初始化为0

b) 然后,对于每一列,我们检查它的类型,并相应地创建
lookup

c) 然后,我们为%lookup中的
i
-
miss(.)%创建相应的表达式

d) 然后我们计算
i
中的表达式,它将使用自动索引快速创建索引,并使用该索引使用二进制搜索快速查找匹配索引

注意:如有必要,您可以在for循环的末尾添加一个
set2key(dt,NULL)
,以便在使用后立即删除创建的索引(以节省空间)

与本次跑步相比,@akrun的最快回答需要6.33秒,这是~4.2倍的加速

更新:在400万行和100列上,大约需要9.2秒。即每列约0.092秒


调用
[.data.table
a 100次可能会很昂贵。当在
set()
中实现自动索引时,最好比较性能。

注释不用于扩展讨论;此对话已被取消。
set.seed(24)
df1 <- as.data.frame(matrix(sample(c(NA,0:9), 6e6*5, replace=TRUE), ncol=5))
set.seed(23)
df2 <- as.data.frame(matrix(sample(c('.','', letters[1:5]), 6e6*5,
   replace=TRUE), ncol=5))
set.seed(234)
i1 <- sample(10)
dfN <- setNames(cbind(df1, df2)[i1], paste0('miss',1:10))
dt <- as.data.table(dfN)

system.time({
 ind <- grep('^miss', names(dt))
 nm1 <- sub('miss', 'flag',names(dt)[ind])
 dt[,(nm1) := 0L]
 for(j in seq_along(ind)){
  set(dt, i=which(dt[[ind[j]]] %in% c('.', '', NA)), j= nm1[j], value=1L)
  }
 }
)
#user  system elapsed 
#  8.352   0.150   8.496 

system.time({
 m1 <- matrix(0, nrow=6e6, ncol=10)
 m2 <- sapply(seq_along(dt), function(i) {
   ind <- which(dt[[i]] %in% c('.', '', NA))
    replace(m1[,i], ind, 1L)})
  cbind(dt, m2)})
 #user  system elapsed 
 # 14.227   0.362  14.582   
in_col = grep("^miss", names(dt), value=TRUE)
out_col = gsub("^miss", "flag", in_col)
system.time({
    dt[, (out_col) := 0L]
    for (j in seq_along(in_col)) {
        if (class(.subset2(dt, in_col[j])) %in% c("character", "factor")) {
            lookup = c("", ".", NA)
        } else lookup = NA
        expr = call("%in%", as.name(in_col[j]), lookup)
        tt = dt[eval(expr), (out_col[j]) := 1L]
    }
})
#    user  system elapsed 
#   1.174   0.295   1.476