Ответ 1
Добавив 2 к -1, 0 и 1, вы можете получить индексы в вектор желаемых результатов:
c("no", "maybe", "yes")[dat + 2]
# [1] "no" "yes" "maybe" "yes" "yes" "no"
Связанная опция может использовать функцию match
для определения индексации:
c("no", "maybe", "yes")[match(dat, -1:1)]
# [1] "no" "yes" "maybe" "yes" "yes" "no"
В качестве альтернативы вы можете использовать именованный вектор для перекодирования:
unname(c("-1"="no", "0"="maybe", "1"="yes")[as.character(dat)])
# [1] "no" "yes" "maybe" "yes" "yes" "no"
Вы также можете использовать вложенный ifelse
:
ifelse(dat == -1, "no", ifelse(dat == 0, "maybe", "yes"))
# [1] "no" "yes" "maybe" "yes" "yes" "no"
Если вы не против загрузки нового пакета, функция Recode
из пакета car
выполняет следующее:
library(car)
Recode(dat, "-1='no'; 0='maybe'; 1='yes'")
# [1] "no" "yes" "maybe" "yes" "yes" "no"
Данные
dat <- c(-1, 1, 0, 1, 1, -1)
Обратите внимание, что все, кроме первого, будут работать, если dat
хранится в виде строки; в первом случае вам нужно будет использовать as.numeric(dat)
.
Если ясность кода является вашей главной целью, тогда вы должны выбрать тот, который вам будет легче всего понять - я бы лично выбрал второй или последний, но это личные предпочтения.
Если скорость кода представляет интерес, то вы можете сравнить решения. Здесь были указаны те пять параметров, которые я представил, включая два других решения, которые в настоящее время размещены как другие ответы, сравниваются с случайным вектором длиной 100 тыс. Страниц:
set.seed(144)
dat <- sample(c(-1, 0, 1), replace=TRUE, 100000)
opt1 <- function(dat) c("no", "maybe", "yes")[dat + 2]
opt2 <- function(dat) c("no", "maybe", "yes")[match(dat, -1:1)]
opt3 <- function(dat) unname(c("-1"="no", "0"="maybe", "1"="yes")[as.character(dat)])
opt4 <- function(dat) ifelse(dat == -1, "no", ifelse(dat == 0, "maybe", "yes"))
opt5 <- function(dat) Recode(dat, "-1='no'; 0='maybe'; 1='yes'")
AnandaMahto <- function(dat) factor(dat, levels = c(-1, 0, 1), labels = c("no", "maybe", "yes"))
hrbrmstr <- function(dat) sapply(as.character(dat), switch, `-1`="no", `0`="maybe", `1`="yes", USE.NAMES=FALSE)
library(microbenchmark)
microbenchmark(opt1(dat), opt2(dat), opt3(dat), opt4(dat), opt5(dat), AnandaMahto(dat), hrbrmstr(dat))
# Unit: milliseconds
# expr min lq mean median uq max neval
# opt1(dat) 1.513500 2.553022 2.763685 2.656010 2.837673 4.384149 100
# opt2(dat) 2.153438 3.013502 3.251850 3.117058 3.269230 5.851234 100
# opt3(dat) 59.716271 61.890470 64.978685 62.509046 63.723048 144.708757 100
# opt4(dat) 62.934734 64.715815 71.181477 65.652195 71.123384 123.840577 100
# opt5(dat) 82.976441 84.849147 89.071808 85.752429 88.473162 155.347273 100
# AnandaMahto(dat) 57.267227 58.643889 60.508402 59.065642 60.368913 80.852157 100
# hrbrmstr(dat) 137.883307 148.626496 158.051220 153.441243 162.594752 228.271336 100
Первые два параметра кажутся более чем на порядок быстрее любого из других вариантов, хотя либо вектор должен быть довольно огромным, либо вам нужно будет повторять операцию несколько раз для любого из это имеет значение.
Как указано @AnandaMahto, эти результаты качественно отличаются, если у нас есть ввод символов вместо числового ввода:
set.seed(144)
dat <- sample(c("-1", "0", "1"), replace=TRUE, 100000)
opt1 <- function(dat) c("no", "maybe", "yes")[as.numeric(dat) + 2]
opt2 <- function(dat) c("no", "maybe", "yes")[match(dat, -1:1)]
opt3 <- function(dat) unname(c("-1"="no", "0"="maybe", "1"="yes")[as.character(dat)])
opt4 <- function(dat) ifelse(dat == -1, "no", ifelse(dat == 0, "maybe", "yes"))
opt5 <- function(dat) Recode(dat, "-1='no'; 0='maybe'; 1='yes'")
AnandaMahto <- function(dat) factor(dat, levels = c(-1, 0, 1), labels = c("no", "maybe", "yes"))
hrbrmstr <- function(dat) sapply(dat, switch, `-1`="no", `0`="maybe", `1`="yes", USE.NAMES=FALSE)
library(microbenchmark)
microbenchmark(opt1(dat), opt2(dat), opt3(dat), opt4(dat), opt5(dat), AnandaMahto(dat), hrbrmstr(dat))
# Unit: milliseconds
# expr min lq mean median uq max neval
# opt1(dat) 8.397194 9.519075 10.784108 9.693706 10.163203 55.78417 100
# opt2(dat) 2.281438 3.091418 4.231162 3.210794 3.436038 49.39879 100
# opt3(dat) 3.606863 5.481115 6.466393 5.720282 6.344651 48.47924 100
# opt4(dat) 66.819638 69.996704 74.596960 71.290522 73.404043 127.52415 100
# opt5(dat) 32.897019 35.701401 38.488489 36.336489 38.950272 88.20915 100
# AnandaMahto(dat) 1.329443 2.114504 2.824306 2.275736 2.493907 46.19333 100
# hrbrmstr(dat) 81.898572 91.043729 154.331766 100.006203 141.425717 1594.17447 100
Теперь решение factor
, предложенное @AnandaMahto, является самым быстрым, за которым следует векторная индексация с помощью match
и именованный векторный поиск. Опять же, все время автономной работы достаточно быстро, что вам понадобится большой вектор или множество прогонов для любого из них.