我试图找出如何在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但没有成功(即没有获得更好的计算时间)。
我是否错过了更好的方法来进行此过滤?
(改变数据结构或变量编码当然可能是一个解决方案。我仍然想研究这种多重过滤。)
答案 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