Создание средней переменной из имен переменных и весов, предоставленных векторами - PullRequest
0 голосов
/ 24 ноября 2018

Предположим, я хочу создать среднюю переменную в данном кадре данных на основе двух векторов, один из которых задает имена переменных, которые нужно использовать, а другой - веса, по которым эти переменные должны переходить в среднюю переменную:

vars <- c("a", "b", "c","d"))
weights <- c(0.5, 0.7, 0.8, 0.2))
df <- data.frame(cbind(c(1,4,5,7), c(2,3,7,5), c(1,1,2,3), 
                       c(4,5,3,3), c(3,2,2,1), c(5,5,7,1)))
colnames(df) <- c("a","b","c","d","e","f")

Как я могу использовать dplyr::mutate() для создания средней переменной, которая использует vars и weights для вычисления балльной оценки по ряду?mutate() должен специально использовать переменные, предоставленные vars Результат должен в основном делать следующее:

df <- df %>% 
  rowwise() %>% 
  mutate(comp = mean(c(vars[1]*weights[1], vars[2]*weights[2], ...)))

Записано:

df2 <- df %>% 
  rowwise() %>% 
  mutate(comp = mean(c(0.5*a, 0.7*b, 0.8*c, 0.2*d)))

Я не могу понять, какСделайте это, потому что, хотя vars содержит точные имена переменных, которые я хочу использовать для mutate в моем df, внутри vars они являются строками.Как я мог mutate() понять, что строки vars содержат ссылки на столбцы в моем df?Если вам известна другая процедура, не использующая mutate(), то это тоже хорошо.Спасибо!

Ответы [ 3 ]

0 голосов
/ 24 ноября 2018

Вы можете использовать

df %>% mutate(wmean = apply(.[vars], 1, weighted.mean, weights))
#   a b c d e f     mean
# 1 1 2 1 4 3 5 1.590909
# 2 4 3 1 5 2 5 2.681818
# 3 5 7 2 3 2 7 4.363636
# 4 7 5 3 3 1 1 4.545455

, но с tidyverse выиграть не так уж и много, поскольку базовые подходы R могут быть почти одинаковыми и в итоге будут короче:

df$wmean <- apply(df[vars], 1, weighted.mean, weights)

или одно из следующего:

df$wmean <- colSums(t(df[vars]) * weights) / sum(weights)
df$wmean <- as.matrix(df[vars]) %*% weights / sum(weights)
df$wmean <- rowSums(sweep(df[vars], 2, weights, `*`)) / sum(weights)
0 голосов
/ 25 ноября 2018

Должно быть tidyverse решение с использованием pmap, но оно ускользает от меня.Вот еще один подход с использованием пакетов tidyverse purrr и tibble

library(tidyverse)

vars <- c("a", "b", "c", "d")
weights <- c(0.5, 0.7, 0.8, 0.2)
df <- data.frame(cbind(c(1,4,5,7), c(2,3,7,5), c(1,1,2,3), 
                       c(4,5,3,3), c(3,2,2,1), c(5,5,7,1)))
colnames(df) <- c("a","b","c","d","e","f")

df %>% 
 transpose() %>% 
  simplify_all() %>% 
  map_dbl(~weighted.mean(.x[vars], weights)) %>% 
  add_column(df, wmean = .)
#>   a b c d e f    wmean
#> 1 1 2 1 4 3 5 1.590909
#> 2 4 3 1 5 2 5 2.681818
#> 3 5 7 2 3 2 7 4.363636
#> 4 7 5 3 3 1 1 4.545455

, созданных в 2018-11-24 пакетом представлением (v0.2.1)

0 голосов
/ 24 ноября 2018

Операции со строками могут быть немного хитрыми в tidyverse .Это тот случай, когда некоторые базовые знания R могут быть очень полезны.Например, вы можете сделать это в одной строке с помощью apply (обратите внимание, что я исправил опечатку в строке, которая создает weights и удалил столбцы e и f, которые не имеют весов):

vars <- c("a", "b", "c","d")
weights <- c(0.5, 0.7, 0.8, 0.2)
df <- data.frame(cbind(c(1,4,5,7), c(2,3,7,5), c(1,1,2,3), 
                       c(4,5,3,3), c(3,2,2,1), c(5,5,7,1)))
colnames(df) <- c("a","b","c","d","e","f")

df$weighted.mean <- apply(df %>% select(-e, -f), 1, weighted.mean, weights)

  a b c d e f weighted.mean
1 1 2 1 4 3 5      1.590909
2 4 3 1 5 2 5      2.681818
3 5 7 2 3 2 7      4.363636
4 7 5 3 3 1 1      4.545455

Если вы действительно хотите сделать это в тидиверсе, вам следует начать:

library(tidyverse)

df.weights <- data.frame(vars, weights)

df.new <- df %>% 
  mutate(row.num = 1:n()) %>% 
  gather(variable, value, -row.num) %>% 
  left_join(df.weights, by = c(variable = 'vars')) %>% 
  filter(variable %in% vars) %>% 
  group_by(row.num) %>% 
  mutate(weighted.mean = weighted.mean(value, weights))
...