我需要计算一个非常简单的公式(加权平均值)的结果,该公式使用两个变量(A和B)和两个权重因子(A_prop和B_prop)。计算将在一个非常大的数据集中进行,权重因子存储在另一个数据框(我在此处称为网格)中。
我的方法是首先为每个权重因子组合创建重复数据,然后执行计算。直到没有什么奇怪的。但是后来我想到了在循环内计算值。一切似乎都准备就绪,但随后我检查了两种方法的结果,结果均不匹配。内部循环的计算结果不正确。
我知道我应该相处并保持能给我正确结果的结果,这也是因为行数非常少。没什么大不了的。但是...我可以忍受这个。我要撕头发了。
谁能解释我为什么结果不一样?循环计算出了什么问题? 另外,如果您有任何关于更优雅的建议,也将受到欢迎。
(注意:我第一次使用reprex。希望是应该的)
>require(tidyverse)
>require(magicfor)
>require(readxl)
>require(reprex)
> dput(dt)
structure(list(X = 1:5, A = c(83.73, 50.4, 79.59, 62.96, 0),
B = c(100, 86.8, 80.95, 81.48, 0), weight = c(201.6, 655,
220.5, 280, 94.5), ind = c(733L, 26266L, 6877L, 8558L, 16361L
)), class = "data.frame", row.names = c(NA, -5L))
> dput(grid)
structure(list(A_prop = c(0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8,
0.85, 0.9, 0.95, 1), B_prop = c(0.5, 0.45, 0.4, 0.35, 0.3, 0.25,
0.2, 0.15, 0.1, 0.05, 0), id = 1:11, tag = structure(1:11, .Label = c("Aprop_0.5",
"Aprop_0.55", "Aprop_0.6", "Aprop_0.65", "Aprop_0.7", "Aprop_0.75",
"Aprop_0.8", "Aprop_0.85", "Aprop_0.9", "Aprop_0.95", "Aprop_1"
), class = "factor")), class = "data.frame", row.names = c(NA,
-11L))
> foo<-function(data,i){
+ val<-(data$A*grid[i,1])+(data$B*grid[i,2])
+ return(val)
+ }
> magic_for(print, progress=FALSE,silent = TRUE)
> for(i in grid$id){
+
+ score<-(dt$A*grid[i,1])+(dt$B*grid[i,2])
+
+ weight=dt$weight
+ A<-dt$A
+ B<-dt$B
+
+ ind=dt$ind
+
+ print(score)
+ print(weight)
+ print(ind)
+ print(A)
+ print(B)
+ }
> rest<-magic_result_as_dataframe()
> magic_free()
> rest2<-left_join(rest,grid,by=c("i"="id"))%>%
+ arrange(ind,tag)%>%
+ mutate(score2=(A*A_prop)+(B*B_prop))
> head(rest2)
i score weight ind A B A_prop B_prop tag score2
1 1 91.8650 201.6 733 83.73 100 0.50 0.50 Aprop_0.5 91.8650
2 2 84.5435 201.6 733 83.73 100 0.55 0.45 Aprop_0.55 91.0515
3 3 86.1705 201.6 733 83.73 100 0.60 0.40 Aprop_0.6 90.2380
4 4 87.7975 201.6 733 83.73 100 0.65 0.35 Aprop_0.65 89.4245
5 5 89.4245 201.6 733 83.73 100 0.70 0.30 Aprop_0.7 88.6110
6 6 91.0515 201.6 733 83.73 100 0.75 0.25 Aprop_0.75 87.7975
答案 0 :(得分:0)
问题实际上是您的left_join而不是for循环。对于以后的帖子,我建议您还提供一个最低限度的示例。
我将演示您的代码出了什么问题。
说,我们有这些数据框,应该与您的真实数据相似:
dt <- data.frame(
A = c(2,3,4),
B = c(20,30,40)
)
grid <- data.frame(
A_prop = c(0.5, 0.6),
B_prop = c(0.5, 0.4),
id = c(1,2),
tag = c("A_prop0.5", "A_prop0.6"))
我们期望以下输出:
预期输出dt [1,]和A_prop 0.5和B_prop 0.5
2 * 0.5 + 20 * 0.5#= 11
预期输出dt [2,]和A_prop 0.5和B_prop 0.5
3 * 0.5 + 30 * 0.5#= 16.5
预期输出dt [3,]和A_prop 0.5和B_prop 0.5
4 * 0.5 + 40 * 0.5#= 22
预期输出dt [1,]和A_prop 0.6和B_prop 0.4
2 * 0.6 + 20 * 0.4#= 9.2
预期输出dt [1,]和A_prop 0.6和B_prop 0.4 3 * 0.6 + 30 * 0.4#= 13.8
预期输出dt [1,]和A_prop 0.6和B_prop 0.4
4 * 0.6 + 40 * 0.4#= 18.4
我从未使用过“ magicfor”库,但是问题出在您加入i
和id
的方式上。
我将如下编写for循环:
l <- list()
for(i in grid$id){
score<-(dt$A*grid[i,1])+(dt$B*grid[i,2])
A<-dt$A
B<-dt$B
iteration <- rep(i, 3) # to keep track in which iteration the result was created.
l[[i]] <- list(
score = score,
A = A,
B = B,
iteration = iteration
)
}
现在,我将列表绑定到数据框,并像您在示例中一样执行left_join:
l <- bind_rows(l)
l_merged <- grid %>% left_join(l, by = c("id"="iteration")) %>%
mutate(score2 = (A*A_prop + B*B_prop))
得分和score2相同的测试:
transmute(l_merged, identical = score == score2)
identical
1 TRUE
2 TRUE
3 TRUE
4 TRUE
5 TRUE
6 TRUE
现在是实际问题
我对您的代码做了一些修改。我已将迭代编号添加到输出中。
magic_for(print, progress=FALSE,silent = TRUE)
for(i in grid$id){
score<-(dt$A*grid[i,1])+(dt$B*grid[i,2])
A<-dt$A
B<-dt$B
iteration <- rep(i, 3)
print(score)
print(A)
print(B)
print(iteration)
}
rest<-magic_result_as_dataframe()
magic_free()
现在,如果我们查看输出并比较i
和iteration
,我们会发现它们并不相同。因此,您的left_join()
产生了令人困惑的结果。
rest %>% arrange(i)
i score A B iteration
1 1 11.0 2 20 1
2 1 22.0 4 40 1
3 1 13.8 3 30 2
4 2 16.5 3 30 1
5 2 9.2 2 20 2
6 2 18.4 4 40 2
最后,我们可以对其进行测试:
grid %>% left_join(rest, by = c("id"="i")) %>% # using i for the join
mutate(score2 = (A*A_prop + B*B_prop)) %>%
transmute(identical = score == score2)
identical
1 TRUE
2 TRUE
3 FALSE
4 FALSE
5 TRUE
6 TRUE
与i
的联接不能产生正确的结果。
但是与iteration
的加入将:
grid %>% left_join(rest, by = c("id"="iteration")) %>% # using the "manually" produced iteration for the join
mutate(score2 = (A*A_prop + B*B_prop)) %>%
transmute(identical = score == score2)
identical
1 TRUE
2 TRUE
3 TRUE
4 TRUE
5 TRUE
6 TRUE
我不确定为什么“ magicfor”中的i
与手动创建的iteration
不同。我当然让您感到困惑...