Создайте символьную переменную со значениями, зависящими от предыдущих переменных (как их имен, так и их значений) с помощью dplyr - PullRequest
3 голосов
/ 06 ноября 2019

У меня есть фрейм данных с ~ 100 переменными и несколькими тысячами наблюдений. Некоторые из этих наблюдений исключены из дальнейшего анализа из-за значений в некоторых из их переменных. Вместо того, чтобы просто удалить эти дисквалифицированные наблюдения, я хочу создать символьную переменную , которая указывает , если наблюдение было дисквалифицировано, и если да, из-за каких переменных (одиннаблюдение может быть дисквалифицировано из-за нескольких переменных).

Большинство переменных являются числовыми и могут иметь одно из следующих значений: -1, 0, 1. В дополнение к этому переменные, которые могут потенциально дисквалифицировать наблюдение, могут также принимать значение 99, что означает дисквалификацию.

# create example data
df <- data.frame(id = c(1:6),
                 AA_B = c(1, 0, NA, 1, -1, 99),
                 A_B_C = c(0, 0, 0, -1, 1, NA),
                 A_BB = c(-1, 99, 0, 0, -1, NA),
                 B_C = c(99, NA, 1, 99, 0, 99),
                 D_AC = c(1, 1, 1, 1, -1, -1))

Если наблюдение дисквалифицируется, новая переменная «дисквалифицировать» должна быть чем-токак Disqualified because of A_BB или Disqualified because of AA_B and B_C (в зависимости от того, какие переменные вызвали дисквалификацию), в противном случае это может быть любая другая строка или просто NA. Итак, результат должен выглядеть следующим образом:

> df
  id AA_B A_B_C A_BB B_C D_AC                           disqualify
1  1    1     0   -1  99    1          Disqualified because of B_C
2  2    0     0   99  NA    1         Disqualified because of A_BB
3  3   NA     0    0   1    1                                 <NA>
4  4    1    -1    0  99    1          Disqualified because of B_C
5  5   -1     1   -1   0   -1                                 <NA>
6  6   99    NA   NA  99   -1 Disqualified because of AA_B and B_C

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

df <-
  df %>%
  mutate(disqualify = case_when(AA_B == 99 |
                                  A_BB == 99 | 
                                  B_C == 99 ~ paste("Disqualified because of",
                                                    case_when(AA_B == 99 & (is.na(A_BB) | A_BB != 99) & (is.na(B_C) | B_C != 99) ~ deparse(substitute(AA_B)),
                                                              AA_B == 99 & A_BB == 99 & (is.na(B_C) | B_C != 99) ~ paste(deparse(substitute(AA_B)), deparse(substitute(A_BB)), sep = " and "),
                                                              AA_B == 99 & A_BB == 99 & B_C == 99 ~ paste(deparse(substitute(AA_B)), deparse(substitute(A_BB)), deparse(substitute(B_C)), sep = " and "),
                                                              AA_B == 99 & (is.na(A_BB) | A_BB != 99) & B_C == 99 ~ paste(deparse(substitute(AA_B)), deparse(substitute(B_C)), sep = " and "),
                                                              (is.na(AA_B) | AA_B != 99) & A_BB == 99 & B_C == 99 ~ paste(deparse(substitute(A_BB)), deparse(substitute(B_C)), sep = " and "),
                                                              (is.na(AA_B) | AA_B != 99) & A_BB == 99 & (is.na(B_C) | B_C != 99) ~ deparse(substitute(A_BB)),
                                                              (is.na(AA_B) | AA_B != 99) & (is.na(A_BB) | A_BB != 99) & B_C == 99 ~ deparse(substitute(B_C))
                                                              ))))

Если возможно, я бы предпочел решение dplyr , которое позволяет мне вызывать дисквалифицирующие переменные по именам переменных (без индексации).

И,как вишня сверху, было бы замечательно, если бы был способ заменить имена переменных в моей выходной переменной другой строкой. Так что Disqualified because of A_BB может стать Disqualified because of Weather.

Любая помощь приветствуется!

Ответы [ 3 ]

2 голосов
/ 06 ноября 2019
library(dplyr)
df %>%
   #Check for 99 in specific columns
   mutate(disqualify = apply(.[,c('AA_B','A_B_C','A_BB','B_C')], 1, function(x) ifelse(any(x==99), 
                                   paste0("Disqualified because of ", paste(names(x[!is.na(x) & x==99]), collapse = " and ")), 
                                   NA)))

  id AA_B A_B_C A_BB B_C D_AC                           disqualify
1  1    1     0   -1  99    1          Disqualified because of B_C
2  2    0     0   99  NA    1         Disqualified because of A_BB
3  3   NA     0    0   1    1                                 <NA>
4  4    1    -1    0  99    1          Disqualified because of B_C
5  5   -1     1   -1   0   -1                                 <NA>
6  6   99    NA   NA  99   -1 Disqualified because of AA_B and B_C

#Base R
df$disqualify <- apply(df[,c('AA_B','A_B_C','A_BB','B_C')], 1, function(x) ifelse(any(x==99), 
                                                             paste0("Disqualified because of ", paste(names(x[!is.na(x) & x==99]), collapse = " and ")), 
                                                             NA))

В базе R мы можем apply функцию над строками / столбцами данных в зависимости от того, передаете ли вы 1 или 2. Здесь нам нужно apply функцию в каждую строку, поэтому мы использовали 1. см. ?apply для более подробной информации.

2 голосов
/ 06 ноября 2019

Один dplyr и tidyr параметр может быть:

df %>%
 left_join(df %>%
            pivot_longer(names_to = "variables", values_to = "values", -id, values_drop_na = TRUE) %>%
            group_by(id) %>%
            summarise(disqualify = if_else(all(values != 99), 
                                           NA_character_, 
                                           paste("Disqualified because of", paste0(variables[values == 99], collapse = " and ")))),
           by = c("id" = "id"))

  id AA_B A_B_C A_BB B_C D_AC                           disqualify
1  1    1     0   -1  99    1          Disqualified because of B_C
2  2    0     0   99  NA    1         Disqualified because of A_BB
3  3   NA     0    0   1    1                                 <NA>
4  4    1    -1    0  99    1          Disqualified because of B_C
5  5   -1     1   -1   0   -1                                 <NA>
6  6   99    NA   NA  99   -1 Disqualified because of AA_B and B_C
0 голосов
/ 06 ноября 2019

базовый однострочный:

df$disqualify <- apply(df,1,function(x)paste(names(which(x==99)),collapse = " and "))
> df
  id AA_B A_B_C A_BB B_C D_AC      disqualify
1  1    1     0   -1  99    1             B_C
2  2    0     0   99  NA    1            A_BB
3  3   NA     0    0   1    1                
4  4    1    -1    0  99    1             B_C
5  5   -1     1   -1   0   -1                
6  6   99    NA   NA  99   -1   AA_B and B_C

, чтобы получить именно то, что вы хотели - вы можете добавить:

df$disqualify <- ifelse(test = df$disqualify=="", yes = NA, no = paste('Disqualified because of ',df$disqualify))

> df
  id AA_B A_B_C A_BB B_C D_AC                            disqualify
1  1    1     0   -1  99    1          Disqualified because of  B_C
2  2    0     0   99  NA    1         Disqualified because of  A_BB
3  3   NA     0    0   1    1                                  <NA>
4  4    1    -1    0  99    1          Disqualified because of  B_C
5  5   -1     1   -1   0   -1                                  <NA>
6  6   99    NA   NA  99   -1 Disqualified because of  AA_B and B_C

если вы хотите изменить имена столбцов - почему бы не сделать это перед этой операцией с
names(df) <- c("id","Weather", "Climate","Name3"...)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...