Как рассчитать rowMeans по имени столбца, а не по номеру столбца - PullRequest
0 голосов
/ 01 мая 2018

У меня есть следующее df bhs1:

structure(list(bhs1_1 = c(NA, 1, NA, 2, 1, 2, 2, 2, 1, 2, 1, 
2, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 2, 2), bhs1_2 = c(NA, 
2, NA, 2, 1, 1, 2, 1, 2, 2, 2, 1, 1, 2, 1, 2, 1, 1, 2, 1, 2, 
1, 1, 2, 2, 2), bhs1_3 = c(NA, 1, NA, 2, 2, 2, 2, 2, 2, 2, 1, 
2, 2, 2, 1, 1, 2, 1, 2, 1, 1, 2, 1, 2, 1, 2), bhs1_4 = c(NA, 
2, NA, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 
1, 1, 2, 1, 1), bhs1_5 = c(NA, 1, NA, 1, 2, 2, 2, 2, 2, 2, 1, 
2, 2, 2, 2, 1, 2, 1, 2, 2, 2, 2, 1, 1, 1, 1), bhs1_6 = c(NA, 
1, NA, 2, 1, 2, 2, 2, 2, 1, 1, 2, 2, 2, 1, 1, 2, 2, NA, 2, 1, 
2, NA, 1, 1, 2), bhs1_7 = c(NA, 1, NA, 1, 2, 1, 1, 1, 1, 1, 2, 
1, 1, 2, 2, 2, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1), bhs1_8 = c(NA, 
2, NA, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 
2, 1, 2, 2, 2), bhs1_9 = c(NA, 1, NA, 2, 1, 1, 1, 1, 2, 1, 2, 
1, 1, 1, NA, 1, 1, 2, 2, 1, 2, 1, 1, 2, 1, 2), bhs1_10 = c(NA, 
2, NA, 1, 2, 2, 2, 2, 1, 2, 1, 1, NA, 2, 1, 1, 1, 2, 1, 2, 2, 
2, 2, 1, 1, 2), bhs1_11 = c(NA, 2, NA, 2, 2, 1, 1, 1, 2, 1, 1, 
1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, NA, 2, 2, 1), bhs1_12 = c(NA, 
2, NA, 2, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 2, 2, 1, 2, 1, 1, 1, 
1, 2, 2, 1, 1), bhs1_13 = c(NA, 1, NA, 1, 2, 2, 2, 2, 1, 1, 1, 
2, 2, 2, 2, 1, 2, 1, 1, 1, 2, 2, 1, 1, 1, 2), bhs1_14 = c(NA, 
2, NA, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 
1, 1, 2, 2, 1), bhs1_15 = c(NA, 1, NA, 2, 2, 2, 2, 2, 2, 1, 2, 
2, 2, 2, 1, 1, 2, 2, 2, NA, 2, 2, 2, 1, 2, 2), bhs1_16 = c(NA, 
2, NA, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 2, 2, 2, 2, 1, 2, 1, 
1, 2, 2, 2, 2), bhs1_17 = c(NA, 2, NA, 2, 2, 1, 1, 1, 2, 1, 1, 
1, 1, 1, 2, 2, 1, NA, 2, 2, 1, 1, 1, 2, 2, 2), bhs1_18 = c(NA, 
1, NA, 1, 2, 1, 1, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 
1, 1, 2, 1, 1), bhs1_19 = c(NA, 1, NA, 2, 1, 2, 2, 2, 1, 2, 2, 
2, 2, 2, 1, 1, 2, 1, 1, 2, 1, 2, 2, 1, 1, 2), bhs1_20 = c(NA, 
2, NA, 2, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 2, 2, 1, 1, 2, 1, 1, 
1, 1, 2, 2, 2)), row.names = c(NA, -26L), class = c("tbl_df", 
"tbl", "data.frame")) 

bhs1 было передано через as_tibble().

Мне интересно вычислить новую переменную bhs1$total, то есть среднее значение по переменным bhs1_1:bhs1_20. Причина пропорциональных средних заключается в том, что наблюдения с пропущенными значениями можно сравнить с наблюдениями без пропущенных значений. С риском констатировать очевидное:

  • Наблюдение 1 может иметь данные только по 18 переменным, поэтому мне нужно сложить записанные переменные, игнорировать NAs и затем разделить на 18, чтобы получить среднее значение, сравнимое с
  • наблюдение 2, у которого есть данные по 20 переменным, у которых сумма записанных переменных будет делиться на 20.

Мне известно (хотя я еще не знаю, как выполнить) множественное вменение, но я не хочу использовать это для этого упражнения.

Я попробовал следующий код:

# A tibble: 908 x 21
   bhs1_1 bhs1_2 bhs1_3 bhs1_4 bhs1_5 bhs1_6 bhs1_7 bhs1_8 bhs1_9
 *  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>
 1     NA     NA     NA     NA     NA     NA     NA     NA     NA
 2      1      2      1      2      1      1      1      2      1
 3     NA     NA     NA     NA     NA     NA     NA     NA     NA
 4      2      2      2      1      1      2      1      2      2
 5      1      1      2      1      2      1      2      2      1
 6      2      1      2      1      2      2      1      2      1
 7      2      2      2      1      2      2      1      2      1
 8      2      1      2      1      2      2      1      2      1
 9      1      2      2      1      2      2      1      1      2
10      2      2      2      1      2      1      1      2      1
# ... with 898 more rows, and 12 more variables: bhs1_10 <dbl>,
#   bhs1_11 <dbl>, bhs1_12 <dbl>, bhs1_13 <dbl>, bhs1_14 <dbl>,
#   bhs1_15 <dbl>, bhs1_16 <dbl>, bhs1_17 <dbl>, bhs1_18 <dbl>,
#   bhs1_19 <dbl>, bhs1_20 <dbl>, meanTest <dbl>

Который работает как положено. Однако при вводе имен столбцов вместо номеров столбцов происходит сбой:

> bhs1$meanTest <- rowMeans(bhs1[,"bhs1_1":"bhs1_20"], na.rm=TRUE)

Error in "bhs1_1":"bhs1_20" : NA/NaN argument
   5. check_names_df(j, x)
   4. `[.tbl_df`(bhs1, , "bhs1_1":"bhs1_20")
   3. bhs1[, "bhs1_1":"bhs1_20"]
   2. is.data.frame(x)
   1. rowMeans(bhs1[, "bhs1_1":"bhs1_20"], na.rm = TRUE)

Я думаю, что гораздо проще использовать имена переменных / столбцов вместо номеров столбцов. Есть ли элегантный способ написания кода для этого варианта использования? Если да, то можете ли вы указать мне правильное направление и / или предоставить мне образец?

Заранее благодарю за внимание и помощь.

1 Ответ

0 голосов
/ 01 мая 2018

Нам нужно получить вектор имен

nm1 <- paste0("bhs1_", 1:20)
bhs1$meanTest <- rowMeans(bhs1[nm1], na.rm = TRUE)

Если имена не имеют шаблонов, и мы заинтересованы в том, чтобы подмножество между именами стартов и остановок, затем используйте match, чтобы получить индекс столбца, получить последовательность (:)

nm1 <- Reduce(`:`, match(c("bhs1_1", "bhs1_20"), names(bhs1)))

и используйте это в rowMeans


Или, если мы используем tidyverse, мы можем указать диапазон (:)

bhs1 <- bhs1 %>%
          select(bhs1_1:bhs1_20) %>% #can replace with 'nm1'
          rowMeans(., na.rm = TRUE) %>%
          bind_cols(bhs1, meanTest = .)

Если нам нужно сделать rowMeans для нескольких наборов столбцов, используйте map2 из purrr, либо передав его в виде списка предложений для имен столбцов 'start' и 'end' в map2 а затем выполните select, оценив (!!) предложения, чтобы получить rowMeans впоследствии

library(purrr)
map2_df(quos(bhs1_1, bhs1_4), quos(bhs1_5, bhs1_8), ~
         bhs1 %>%
           select((!! .x) : (!! .y)) %>% 
           rowMeans(., na.rm = TRUE)) %>%
   bind_cols(bhs1, .)

Или мы можем передать как вектор строк, а затем выполнить преобразование в символ (с sym из rlang) и вычислить (!!)

map2(c("bhs1_1", "bhs1_4"), c("bhs1_5", "bhs1_8"), ~ 
           bhs1 %>%
              select(!!(rlang::sym(.x)): !!(rlang::sym(.y)))) %>%
              rowMeans(., na.rm = TRUE)) %>%
    bind_cols(bhs1, .)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...