Какой самый короткий и чистый способ перекодировать несколько переменных в кадре данных с использованием R? - PullRequest
1 голос
/ 09 октября 2019

Итак, я работаю в области социальных наук, и мне часто приходится манипулировать несколькими переменными для изменения значений. Чаще всего это означает изменение масштаба. Я давно работаю с SPSS , и синтаксис там довольно прост. Чтобы изменить значения нескольких переменных, вы пишете:

RECODE var1 var2 var3 (1=5) (2=4) 4=2) (5=1) (ELSE=COPY).

Чтобы записать новые коды в новые переменные, вы добавляете into newvar1 newvar1 newvar3. в конце. В скобках вы можете использовать такие вещи, как hi, lo, 1 to 4 и т. Д.

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

## Packages -----
library(dplyr)
library(car)

## Data -----
tib <- tibble(v1 = 1:4, 
              v2 = 1:4,
              v3 = sample(1:5, 4, replace = FALSE))

vars <- c("v1", "v2", "v3")

Базовый путь:

tib$v2_rec <- NA
tib$v2_rec[tib$v2 == 1] <- 5 #1
tib$v2_rec[tib$v2 == 2] <- 4 #2
tib$v2_rec[tib$v2 == 3] <- 3 #3
tib$v2_rec[tib$v2 == 4] <- 2 #4
tib$v2_rec[tib$v2 == 5] <- 1 #5
# I'm forced to create a new variable here, otherwise #4 and #5 overwrite #1 and #2.
# Therefore I won't even bother to try to loop trough multiple variables.

recode () из пакета автомобилей:

tib$v1 <- recode(tib$v1, "1=5; 2=4; 4=2; 5=1")
# This is nice, understandable and short
# To handle multiple variables the following solutions won't work, because the reload functions seems not to be able to iterate through lists:

tib[vars] <- recode(tib[vars], "1=5; 2=4; 4=2; 5=1")
tib[1:3] <- recode(tib[1:3], "1=5; 2=4; 4=2; 5=1")

# I'd be forced to loop:

for (i in vars) {
  tib[[i]] <- recode(tib[[i]], "1=5; 2=4; 4=2; 5=1")
}

Я очень доволен этим, но мне было интересно, есть ли функция, которая будет выполнять зацикливание для меня. Сейчас я действительно борюсь с функциями dplyer, и я не рад, что не могу понять все интуитивно ...

Я пытался изменить:

#I get it for a single case and for multiple cases i got to a solution in combination with the recode() function:

tib <- tib %>%
  mutate_at(vars(v1:v3), 
            function(x) recode(x, "1=5; 2=4; 4=2; 5=1"))

это лучший способ сделать это? Просто чтобы быть понятным, я видел некоторые другие решения, использующие case_when (), replace () или mapvalues ​​(), но я нашел решение выше, потому что мне нравится видеть, какое значение перекодируется в какое значение одним проблеском.

Я немного попал в функцию apply () и не смог даже перекодировать одну переменную с ней. Я уверен, что в скором времени я получу контроль над этим, но сейчас я просто немного расстроен тем, как долго я искал рабочие процессы, которые заняли у меня одну строчку в SPSS. Если бы вы знали какое-либо более короткое и чистое решение, чем приведенное выше, с использованием функции apply (), я был бы очень рад!

Я доволен R и его возможностями, но сейчас мне нужен намек в правильном направлении, чтобыподдержи меня! Заранее спасибо!

Ответы [ 2 ]

2 голосов
/ 09 октября 2019

Я думаю, что при правильном использовании, dplyr имеет «самый чистый» синтаксис в этом случае:

library(dplyr)
tib <- tibble(v1 = 1:4, 
              v2 = 1:4,
              v3 = sample(1:5, 4, replace = FALSE))

tib %>% 
  mutate_at(vars(v1:v3), recode, `1` = 5, `2` = 4, `3` = 3, `4` = 2, `5` = 1)
#> # A tibble: 4 x 3
#>      v1    v2    v3
#>   <dbl> <dbl> <dbl>
#> 1     5     5     2
#> 2     4     4     5
#> 3     3     3     4
#> 4     2     2     1

Обратите внимание, что мне пришлось добавить 3 = 3, потому что для перекодировки требуется замена для всех значений.

Мне часто проще писать вещи более явно с новыми для меня функциями, поэтому, возможно, это поможет:

tib %>% 
  mutate_at(.vars = vars(v1:v3), 
            .funs = function(x) recode(x, 
                                       `1` = 5, 
                                       `2` = 4, 
                                       `3` = 3, 
                                       `4` = 2, 
                                       `5` = 1))

Если вы предпочитаете функцию recode из carВы не должны загружать car, а использовать:

tib %>% 
  mutate_at(vars(v1:v3), car::recode, "1=5; 2=4; 4=2; 5=1")

Таким образом, вы не столкнетесь с проблемами при смешивании dplyr с car (если вам не нужно car для чего-либоеще.

1 голос
/ 09 октября 2019

Вот простой способ использования только базовых функций. Это предполагает, что это 5-балльные элементы Ликерта, где исходная кодировка была 1 - 5. Если у вас были, скажем, 7-балльные элементы Ликерта, или закодировано 0 - 4, или -2 - 2, вам нужно адаптировать это,

Некоторые примечания по кодированию: у вас есть элемент генерации псевдослучайного числа в вашем наборе данных (вызов sample());чтобы сделать набор данных точно воспроизводимым, используйте ? set.seed . Вы можете автоматически распечатать переменную или набор данных, которые были назначены, заключив их в скобки при использовании оператора присваивания стрелки ((var <- value)). R векторизована, так что вам не нужен цикл (хотя здесь все в порядке - с таким небольшим количеством переменных это не вызовет заметного замедления).

set.seed(4636)  # this makes the example exactly reproducible
(d <- data.frame(v1 = 1:4, 
                 v2 = 1:4,
                 v3 = sample(1:5, 4, replace = FALSE)))  # adding outer ()'s prints
#   v1 v2 v3
# 1  1  1  1
# 2  2  2  2
# 3  3  3  5
# 4  4  4  4

d.orig <- d  # here's your original dataset, so they aren't overwritten
(d <- 6-d)  # adding outer ()'s prints
#   v1 v2 v3
# 1  5  5  5
# 2  4  4  4
# 3  3  3  1
# 4  2  2  2

rec.vars <- c("v2")
d.some   <- d.orig
(d.some[,rec.vars] <- 6-d.some[,rec.vars])
# [1] 5 4 3 2
d.some
#   v1 v2 v3
# 1  1  5  1
# 2  2  4  2
# 3  3  3  5
# 4  4  2  4

##### to do more than 1 variable
(rec.vars <- paste0("v", c(2,3)))
# [1] "v2" "v3"
d.some   <- d.orig
(d.some[,rec.vars] <- 6-d.some[,rec.vars])
#   v2 v3
# 1  5  5
# 2  4  4
# 3  3  1
# 4  2  2
d.some
#   v1 v2 v3
# 1  1  5  5
# 2  2  4  4
# 3  3  3  1
# 4  4  2  2
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...