【发布时间】:2016-07-01 08:32:04
【问题描述】:
我有两个数据集 - TEST end TRAIN。 TEST 是 TRAIN 的一个子集。通过使用列“prod”和“clnt”,我需要在 TRAIN 中找到与 TEST 对应的所有行(它是一对多对应)。然后我对TEST的“order”列的各个值进行时间分析(第一列“week”是时间)。
所以我取 TRAIN 的第一行,比较 TEST 的所有行是否其中一些包含相同的“prod”和“clnt”数字组合,并在 TS 中记录“order”各自的值。通常我在每行 TRAIN 的 TS 中有 0 到 10 个值。然后我对 TS 进行一些计算(在这个人为的情况下,只是平均值(TS))并记录结果以及数据集 Subm 中 TEST 行的“Id”。
该算法有效,但因为我在 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
【问题讨论】:
-
你的解释有点不清楚。我运行了你的代码,但我不确定我应该看什么。为什么
TS最后只有两个值? (至少在我尝试过时)从一开始的描述来看,您似乎想要所有 TRAIN 行也出现在 TEST 中,只考虑prod和clnt列。如果是这种情况,使用dplyr::semi_join(train, test, by = c("prod", "clnt"))将为您提供那部分答案。 -
@LuisUsie,这是人为的例子,它按预期工作。 TS 中只有两个值是正常的。你是对的,我想要所有的 TRAIN 行,出现在 TEST 中,缺点。 "prod" 和 "clnt" 唯一的问题是最后使用循环导致的低速。我知道一些向量化是必要的,但我还是 R 的新手。所以我会尝试关于 dplyr 的建议。
-
@sebastianmm 我试图提供工作示例。如果您只是运行脚本,它会生成所有必要的数据。
-
@LuisUsier 是的,现在它部分达到了目的。现在我需要从
dlpyr操作的结果中提取相等的行(考虑相等的偶数"prod"&"clnt"),并对最后一列做一些数学运算,例如mean("order")。在这个(人工)示例中,我们每行有两次重复。在一般情况下,我不知道重复次数是多少 - 它们在各行之间是不同的,介于 0 到 10 之间。
标签: r for-loop subset vectorization