Репликация сгруппированной функции по нескольким переменным для создания множества новых переменных - PullRequest
1 голос
/ 05 августа 2020

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

test <- data.frame(1:10)
test$ID <- c("A", "B", "C", "D", "E", "F", "G", "H", "I", "J")
test$Zone1 <- c(1,1,1,2,3,2,5,6,4,1)
test$Zone2 <- c(1,2,1,2,2,2,4,8,6,1)
test$Zone3 <- c(1,1,1,2,2,2,3,3,3,1)
test$Zone1_group<- c(1,1,1,2,2,2,3,3,3,4)
test$Zone2_group<- c(1,1,1,2,2,2,3,3,3,4)
test$Zone3_group<- c(1,1,1,2,2,2,3,3,3,4)

Я хотел бы определить, есть ли у группы для данной переменной какое-либо отклонение. Если у группы нет дисперсии, я бы заменил ее значение на NA. Ниже приведен желаемый результат, который мне удалось достичь для одной переменной (если я исключу Zone1_group == 4) в dplyr, используя следующее:

test2 <- test %>% group_by(Zone1_group) %>% summarise(Zone1_variance = SD(Zone1)) 
test3 <- left_join(test, test2, by = "Zone1_group")
test3 %>% mutate(Zone1_new = if_else(Zone1_variance == 0, NA_real_, Zone1))

  X1.9 ID Zone1 Zone2 Zone3 Zone1_group Zone2_group Zone3_group Zone1_variance Zone1_new
1    1  A     1     1     1           1           1           1      0.0000000        NA
2    2  B     1     2     1           1           1           1      0.0000000        NA
3    3  C     1     1     1           1           1           1      0.0000000        NA
4    4  D     2     2     2           2           2           2      0.5773503         2
5    5  E     3     2     2           2           2           2      0.5773503         3
6    6  F     2     2     2           2           2           2      0.5773503         2
7    7  G     5     4     3           3           3           3      1.0000000         5
8    8  H     6     8     3           3           3           3      1.0000000         6
9    9  I     4     6     3           3           3           3      1.0000000         4

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

1 Ответ

1 голос
/ 05 августа 2020

Вот один из способов сделать это:

library(dplyr)
library(purrr)
library(rlang)

add_new_var_cols <- function(data, col) {
    group_col <- paste0(col, '_group')
    col1 <- sym(col)

    data %>% 
     group_by(!!sym(group_col)) %>% 
     transmute(!!paste0(col, '_new') := if(length(!!col1) > 1 && 
                                    sd(!!col1) != 0) !!col1 else NA_real_) %>%
     ungroup %>%
     select(-group_col)
}

Теперь примените эту функцию к каждому 'Zone' столбцу:

cols <- paste0('Zone', 1:3)
bind_cols(test, map_dfc(cols, add_new_var_cols, data = test))


#  X1.9 ID Zone1 Zone2 Zone3 Zone1_group Zone2_group Zone3_group Zone1_new Zone2_new Zone3_new
#1    1  A     1     1     1           1           1           1        NA         1        NA
#2    2  B     1     2     1           1           1           1        NA         2        NA
#3    3  C     1     1     1           1           1           1        NA         1        NA
#4    4  D     2     2     2           2           2           2         2        NA        NA
#5    5  E     3     2     2           2           2           2         3        NA        NA
#6    6  F     2     2     2           2           2           2         2        NA        NA
#7    7  G     5     4     3           3           3           3         5         4        NA
#8    8  H     6     8     3           3           3           3         6         8        NA
#9    9  I     4     6     3           3           3           3         4         6        NA

Мы передаем символьные переменные в cols, используя sym и !! мы оцениваем их как значения столбцов, чтобы использовать их в функции.

...