L oop приводит к неправильной позиции / порядку - PullRequest
0 голосов
/ 17 февраля 2020

Мне нужно рассчитать результаты очень простой формулы (средневзвешенного значения), в которой используются две переменные (A и B) и два весовых коэффициента (A_prop и B_prop). Расчет должен быть выполнен в очень большом наборе данных, а весовые коэффициенты хранятся в другом фрейме данных, который я назвал здесь сеткой.

Мой подход был первым, чтобы создать повторы данных для каждой комбинации весовых коэффициентов и затем выполнил расчеты. Пока что ничего странного. Однако потом я подумал о расчете значений внутри l oop. Все вроде бы на месте, но потом я проверил результаты обоих подходов и результаты не совпадают. Результаты вычислений внутри l oop неверны.

Я знаю, что должен просто согласиться с тем, что дает мне правильные результаты, также потому, что число строк довольно мало. Нет больших проблем. Однако ... Я могу просто жить с этим. Я собираюсь порвать мои волосы.

Может кто-нибудь объяснить мне, почему результаты не совпадают? Что не так с вычислением l oop? Кроме того, кроме того, если у вас есть какие-либо предложения по поводу более элегантного, это будет приветствоваться.

(примечание: я впервые использую представительство. Надеюсь, что так и должно быть)

>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 голосов
/ 17 февраля 2020

Проблема на самом деле ваша left_join, а не для l oop. Для будущих публикаций я бы рекомендовал вам также предоставить минимальный (isti c) пример.

Я покажу, что пошло не так в вашем коде.

Скажем, у нас есть эти фреймы данных , которая должна быть аналогична вашим реальным данным:

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 * ​​1020 *

Ожидаемый выходной сигнал 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.

Я бы написал для l oop следующим образом:

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))

Тест, в котором оценка и оценка2 одинаковы:

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

Я не уверен, почему i из "magicfor" отличается от созданного вручную iteration. Я конечно получаю ваше замешательство ...

...