r中有多个变量过滤器

时间:2015-11-24 10:13:19

标签: r

我试图找出如何在R中使用多个变量过滤器的最佳方法。

通常最多有100个变量(在一个条件下)并且需要过滤这些变量中的任何一个满足相同条件的情况(例如VARx = 170)。 变量的名称和数量通常不同,并作为要评估的字符串输入。 这是我整个计算的瓶颈。

示例(过滤器Varx = 37):

id <- c(1:100000) 
x1 <- sample(1:100, 100000, replace=T)
x2 <- sample(1:100, 100000, replace=T)
x3 <- sample(1:100, 100000, replace=T)
x4 <- sample(1:100, 100000, replace=T)
x5 <- sample(1:100, 100000, replace=T)
x6 <- sample(1:100, 100000, replace=T)
x7 <- sample(1:100, 100000, replace=T)
x8 <- sample(1:100, 100000, replace=T)
x9 <- sample(1:100, 100000, replace=T)
x10 <- sample(1:100, 100000, replace=T)

df<-data.frame(id,x1,x2,x3,x4,x5,x6,x7,x8,x9,x10)
dt<-data.table(df)

pm<-proc.time()
vys<-((x1==37) | (x2==37) | (x3==37) | (x4==37) | (x5==37) | (x6==37) | (x7==37) | (x8==37) | (x9==37) | (x10==37))
proc.time() - pm

pm<-proc.time()
vys<-((rowSums(subset(df,select=c(x1:x10))==37)>0))
proc.time() - pm

第一个陈述需要的时间更少,但准备时间更长,时间更长。第二个更慢,更简洁。我试图在我的计算中加入data.table但没有成功(即没有获得更好的计算时间)。

我是否错过了更好的方法来进行此过滤?

(改变数据结构或变量编码当然可能是一个解决方案。我仍然想研究这种多重过滤。)

3 个答案:

答案 0 :(得分:1)

我们可以将<hibernate.version>4.2.15.Final</hibernate.version> Reduce

一起使用
lapply

基于相同的基准使用

vys1 <-  dt[, Reduce('|', lapply(.SD, '==', 37)), .SDcols= x1:x10]
identical(as.vector(vys), vys1)
#[1] TRUE

答案 1 :(得分:1)

我认为您在基础R中的第二个陈述是正常的,只需使用[代替subset

rowSums(df[sprintf("x%d", 1:10)]==37) > 0

基准:

library(microbenchmark)
microbenchmark( times = 20, 
  subset = {((rowSums(subset(df,select=c(x1:x10))==37)>0))},
  dt_reduce = {dt[, Reduce('|', lapply(.SD, '==', 37)), .SDcols= x1:x10]},
  base_r = {rowSums(df[sprintf("x%d", 1:10)]==37) > 0}
)

# Unit: milliseconds
#       expr      min       lq     mean   median        uq       max neval
#     subset 82.74922 88.63819 99.69935 91.18369 110.24876 134.06550    20
#  dt_reduce 25.78002 28.62765 32.73945 28.89021  29.12712  71.25822    20
#     base_r 21.52504 24.27624 27.03380 25.83219  26.24400  65.38550    20

答案 2 :(得分:0)

您正在寻找适用于数据帧每一行的功能。那是什么&#34;适用&#34;是在做。它与其他人的解决方案一样快,但易于处理:

system.time(
((x1==37) | (x2==37) | (x3==37) | (x4==37) | (x5==37) | (x6==37) | (x7==37) | (x8==37) | (x9==37) | (x10==37))
 )
# user  system elapsed 
# 0.02    0.00    0.02 

 system.time(
    apply(df, 1 , function(x) any(x[2:11]==37))
 )
# user  system elapsed 
# 0.59    0.00    0.61 

虽然您不要求更改数据结构,但我建议您查看tidy data。使用重新排列的数据框版本,您可以高效且易于处理过滤:

library(tidyr)
df2 = gather(df, key, value, -id)

system.time(
    select(filter(df, value==37), id)
)
#   user  system elapsed 
#   0.02    0.00    0.02