Цикл внутри мутации

Я рассчитываю индекс с помощью dplyr. Индекс представляет собой сумму квадратов соотношений между каждой записью и общей записью в группе.

library(dplyr)

set.seed(1e2)
firm_id <-  sample(1:3, 1e2, rep=T)
pro_id <-  sample(1:8, 1e2, rep=T)
emplo_id <- sample(1:5, 1e2, rep=T)
cost <-  round(abs(rnorm(1e2, 20)), 2)

df <- data.frame(firm_id, pro_id, emplo_id, cost)

df_index <- df %>% group_by(firm_id,pro_id) %>% 
  mutate(INDEX = sum((cost/sum(cost))^2))

Теперь я хочу рассчитать, насколько каждая запись вносит вклад в idex, создаваемую ее группой, а это означает, что я хочу рассчитать новый индекс, как если бы стоимость входа для значения была 0, и это для каждой записи, как если бы в цикле (затем разделите новый индекс по старому).

Ожидаемые результаты:

firm_id <-  c(1,1,1)
pro_id <-  c(1,1,1)
emplo_id <- c(1:3)
cost <-  c(1,50,100)
INDEX <- rep(0.5482654,3)
newINDEX <- c(0.5555556,0.9803941,0.9615532)
df_index <- data.frame(firm_id, pro_id, emplo_id, cost, INDEX, newINDEX)

С mutate я понятия не имею, как это сделать. Любые предложения приветствуются!


person MCS    schedule 08.08.2018    source источник
comment
Можете ли вы показать ожидаемый результат? Кроме того, set.seed сделает его воспроизводимым   -  person akrun    schedule 08.08.2018
comment
Непонятен расчет as if the entry cost is 0   -  person akrun    schedule 08.08.2018


Ответы (1)


Вы можете использовать purrr::map_dbl() для перебора индексов строк в каждой группе, а затем применить функцию, которая заменяет cost в данном индексе на 0, а затем пересчитывает индекс. Вот пример данных, для которых вы дали ожидаемый результат:

library(dplyr)
library(purrr)

# The function used to calculate the index value
index <- function(x) sum((x / sum(x)) ^ 2)

df_index %>%
  group_by(firm_id, pro_id) %>%
  mutate(new = map_dbl(row_number(), function(i) {
    index(replace(cost, i, 0))
  }))
#> # A tibble: 3 x 7
#> # Groups:   firm_id, pro_id [1]
#>   firm_id pro_id emplo_id  cost INDEX newINDEX   new
#>     <dbl>  <dbl>    <int> <dbl> <dbl>    <dbl> <dbl>
#> 1       1      1        1     1 0.548    0.556 0.556
#> 2       1      1        2    50 0.548    0.980 0.980
#> 3       1      1        3   100 0.548    0.962 0.962


С помощью дополнительной вспомогательной функции вы также можете сделать это более чистым способом:

index_without <- function(i, x) {
  map_dbl(i, function(i) index(replace(x, i, 0)))
}

df_index %>%
  group_by(firm_id, pro_id) %>%
  mutate(new = index_without(row_number(), cost))
#> # A tibble: 3 x 7
#> # Groups:   firm_id, pro_id [1]
#>   firm_id pro_id emplo_id  cost INDEX newINDEX   new
#>     <dbl>  <dbl>    <int> <dbl> <dbl>    <dbl> <dbl>
#> 1       1      1        1     1 0.548    0.556 0.556
#> 2       1      1        2    50 0.548    0.980 0.980
#> 3       1      1        3   100 0.548    0.962 0.962

Создано 08.08.2018 с помощью пакета REPEX (v0.2.0.9000).

person Mikko Marttila    schedule 08.08.2018