从行的数据子集中消除循环

时间:2016-07-01 08:32:04

标签: r for-loop subset vectorization

我有两个数据集 - TEST结束TRAIN。 TEST是TRAIN的子集。通过使用列" prod"和" clnt"我需要在TRAIN中找到与TEST相对应的所有行(它是一对多的对应关系)。然后我对列的相应值进行时间分析" order" TEST(第一栏"周"是时间)。

所以我选了TRAIN的第一行,我比较了TEST的所有行是否有一些包含" prod"的数字组合。和" clnt"并记录" order"的相应值。在TS。通常我在每行TRAIN的TS中有零到大约十个值。然后我在TS上进行一些计算(在这个人工案例中只是意味着(TS))并记录结果以及" Id"数据集Subm中的TEST行。

该算法有效,但由于我在TRAIN和TEST中有数百万行,我需要尽可能快,特别是要摆脱循环,这是最慢的部分。可能我也搞砸了data.frame声明/用法,但我不确定。

set.seed(42)
NumObsTrain=100000 # this can be as much as 70 000 000
NumObsTest=10000 # this can be as much as 6 000 000

#create the TRAIN data set
train1=floor(runif(NumObsTrain, min=0, max=NumObsTrain+1))
train1=matrix(train1,ncol = 2)
train=cbind(8,train1) #week
train=rbind(train,cbind(9,train1)) #week
train=cbind(train,runif(NumObsTrain,min=1,max=10)) #order
train=cbind(c(1:nrow(train)),train)# id number of each row
colnames(train)=c("id","week","prod","clnt","order")
train=as.data.frame(train)
train=train[sample(nrow(train)),] # reflush the rows of train

# Create the TEST dataset
test=train[1:NumObsTest,]
test[,"week"][1:{NumObsTest/2}]=10
test[,"week"][{(NumObsTest/2)+1}:NumObsTest]=11

TS=numeric(length = 10)
id=c(1:NumObsTest*2)
order=c(1:NumObsTest*2)
Subm=data.frame(id,order)
ptm <- proc.time()

# This is the loop
for (i in 1:NumObsTest){
   Subm$id[i]=test$id[i]
   TS=train$order[train$clnt==test$clnt[i]&train$prod==test$prod[i]]
   Subm$order[i]=mean(TS)
}
proc.time() - ptm

1 个答案:

答案 0 :(得分:2)

以下内容将创建一个包含所有(prod, clnt)order组合的data.frame,然后按prodclnt分组,然后取平均值每组。最终结果是缺少id,并且由于某种原因,您的最终data.frame中有更多数据,我无法弄清楚原因。但order结果是正确的。

newtrain <- train[, 3:5]
newtest <- test[, c(1, 3:4)]
x <- dplyr::inner_join(newtest, newtrain)
y <- dplyr::group_by(x, prod, clnt)
z <- dplyr::summarise(y, mean(order))