首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在R或向量化中快速vectorization

在R或向量化中快速vectorization
EN

Stack Overflow用户
提问于 2017-08-09 20:33:41
回答 1查看 241关注 0票数 1

我有一个相当大的数据帧,大约有1000万行,在我的示例中,这是由向量x1和y1表示的。

代码语言:javascript
运行
复制
set.seed(100)
x1<-round(runif(10000,min=1,max=5),0) #random values [1;2;3;4;5]
x2<-runif(10000,min=0,max=1) #random num (0,1]

我想借助下面的表格'rvps‘来计算新的向量xx

代码语言:javascript
运行
复制
rvps<-data.frame(Q_cat=c(1,2,2,2,3,3,3,4,4,5),prov_calc=c(0,1,10,20,21,30,50,51,60,100),
       s3_from=c(0.00,0.00,0.90,0.99,0.00,0.60,0.65,0.00,0.99,0.00), 
       s3_to=c(1.00,0.90,0.99,1.00,0.60,0.65,1.00,0.99,1.00,1.00))

我提出了几个解决方案:

代码语言:javascript
运行
复制
#sol№1
library(doParallel)
xx1<-foreach(i=1:length(x1)) %do% {rvps$prov_calc[x1[i]==rvps$Q_cat & x2[i]>rvps$s3_from & x2[i]<=rvps$s3_to]}
#system.time=2.87

太慢了

代码语言:javascript
运行
复制
#sol№2
xx2<-ifelse(x1==1,0,
     ifelse(x1==2,
            ifelse(x2>0 & x2<=0.9,1,
            ifelse(x2>0.9 & x2<=0.99,10,
            ifelse(x2>0.99 & x2<=1,20,20))),
     ifelse(x1==3,
            ifelse(x2>0 & x2<=0.6,21,
            ifelse(x2>0.6 & x2<=0.65,30,
            ifelse(x2>0.65 & x2<=1,50,50))),
     ifelse(x1==4,
            ifelse(x2>0 & x2<=0.99,51,
            ifelse(x2>0.99 & x2<=1,60,60)),
     ifelse(x1==5,100,100)))))
#system.time=0.02

没有我的表(所有边界都是手动输入的),但速度很快

代码语言:javascript
运行
复制
#sol№3
rvps.prob<-function(X,Y) {rvps$prov_calc[X==rvps$Q_cat & Y>rvps$s3_from & Y<=rvps$s3_to]}
xx3<-mapply(rvps.prob,x1,x2)
#system.time=0.59

mapply解决方案。比我的第一次尝试更快,但没有我需要的那么快。如何向量化我的任务?The same question in russian

更新:我的同事提供了更多的解决方案。都输给了矢量化函数

代码语言:javascript
运行
复制
#4 вариант #system.time=1.03
system.time(for(i in 1:length(x1))
{
  if (rvps$prov_calc[x1[i]==rvps$Q_cat & x2[i]>rvps$s3_from & x2[i]<=rvps$s3_to]) 
    xx4[i] <- rvps$prov_calc[x1[i]==rvps$Q_cat & x2[i]>rvps$s3_from & x2[i]<=rvps$s3_to]
  else xx4[i] <- 0
})

#5 вариант #system.time=3.57
system.time({
  xx5<-unlist(foreach(i=1:length(x1)) %do% {rvps$prov_calc[x1[i]==rvps$Q_cat & x2[i]>rvps$s3_from & x2[i]<=rvps$s3_to]})
  })

#6 вариант #system.time=2.24
system.time(for(i in 1:length(x1))
{
  for(j in 1:length(rvps$prov_calc)) 
    if (x1[i]==rvps$Q_cat[j] & x2[i]>rvps$s3_from[j] & x2[i]<=rvps$s3_to[j]) {xx6[i] <- rvps$prov_calc[j];break}
})
EN

回答 1

Stack Overflow用户

发布于 2017-08-11 16:42:35

下面介绍了我的工作精华。

初始数据:

代码语言:javascript
运行
复制
mm1<-round(runif(200000,min=1,max=5),0) #random values [1;2;3;4;5]
mm2<-runif(200000,min=0,max=1) #random num (0,1]  

使用{dplur}№1进行矢量化:

代码语言:javascript
运行
复制
system.time({
mm3<-if_else(mm1==1,0,
  if_else(mm1==2 & mm2>0 & mm2<= 0.9,1,
  if_else(mm1==2 & mm2>0.9 & mm2<= 0.99,10,
  if_else(mm1==2 & mm2>0.99 & mm2<= 1,20,
  if_else(mm1==3 & mm2>0.0 & mm2<= 0.6,21,
  if_else(mm1==3 & mm2>0.6 & mm2<= 0.65,30,
  if_else(mm1==3 & mm2>0.65 & mm2<= 1,50,
  if_else(mm1==4 & mm2>0 & mm2<= 0.99,51,  
  if_else(mm1==4 & mm2>0.99 & mm2<= 1,60,
  if_else(mm1==5,100,100))))))))))
}) #system.time=0.14

使用{dplur}№2进行矢量化:

代码语言:javascript
运行
复制
system.time({
mm3<-case_when(
  mm1==1 ~ 0,
  mm1==2 & mm2>0 & mm2<= 0.9 ~ 1,
  mm1==2 & mm2>0.9 & mm2<= 0.99 ~ 10,
  mm1==2 & mm2>0.99 & mm2<= 1 ~ 20,
  mm1==3 & mm2>0.0 & mm2<= 0.6 ~ 21,
  mm1==3 & mm2>0.6 & mm2<= 0.65 ~ 30,
  mm1==3 & mm2>0.65 & mm2<= 1 ~ 50,
  mm1==4 & mm2>0 & mm2<= 0.99 ~ 51,  
  mm1==4 & mm2>0.99 & mm2<= 1 ~ 60,
  mm1==5 ~ 100) #system.time=0.14
}) #system.time=0.08
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45590843

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档