循环导致错误的位置/顺序

时间:2020-02-17 09:47:32

标签: r loops for-loop

我需要计算一个非常简单的公式(加权平均值)的结果,该公式使用两个变量(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

1 个答案:

答案 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”库,但是问题出在您加入iid的方式上。

我将如下编写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()

现在,如果我们查看输出并比较iiteration,我们会发现它们并不相同。因此,您的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不同。我当然让您感到困惑...