Пример утверждения, эквивалентный в R

У меня есть переменная в dataframe, где одно из полей обычно имеет 7-8 значений. Я хочу, чтобы они разделили их на 3 или 4 новые категории в пределах новой переменной внутри фрейма данных. Каков наилучший подход?

Я бы использовал оператор CASE, если бы был в SQL-подобном инструменте, но не уверен, как атаковать это в R.

Любая помощь, которую вы можете предоставить, будет очень признательна!

Посмотрите на функцию memisc пакета memisc . Он реализует функциональность case с двумя различными способами ее использования. Из примеров в пакете:

 z1=cases( "Condition 1"=x<0, "Condition 2"=y<0,# only applies if x >= 0 "Condition 3"=TRUE ) 

где x и y – два вектора.

Ссылки: memisc package , примеры примеров

Если у вас есть factor вы можете изменить уровни стандартным методом:

 df <- data.frame(name = c('cow','pig','eagle','pigeon'), stringsAsFactors = FALSE) df$type <- factor(df$name) # First step: copy vector and make it factor # Change levels: levels(df$type) <- list( animal = c("cow", "pig"), bird = c("eagle", "pigeon") ) df # name type # 1 cow animal # 2 pig animal # 3 eagle bird # 4 pigeon bird 

Вы можете написать простую функцию в качестве обертки:

 changelevels <- function(f, ...) { f <- as.factor(f) levels(f) <- list(...) f } df <- data.frame(name = c('cow','pig','eagle','pigeon'), stringsAsFactors = TRUE) df$type <- changelevels(df$name, animal=c("cow", "pig"), bird=c("eagle", "pigeon")) 

Ниже приведен пример использования оператора switch :

 df <- data.frame(name = c('cow','pig','eagle','pigeon'), stringsAsFactors = FALSE) df$type <- sapply(df$name, switch, cow = 'animal', pig = 'animal', eagle = 'bird', pigeon = 'bird') > df name type 1 cow animal 2 pig animal 3 eagle bird 4 pigeon bird 

Единственным недостатком этого является то, что вы должны продолжать писать название категории ( animal и т. Д.) Для каждого элемента. Синтаксически более удобно определять наши категории, как показано ниже (см. Очень похожий вопрос. Как добавить столбец в кадре данных в R )

 myMap <- list(animal = c('cow', 'pig'), bird = c('eagle', 'pigeon')) 

и мы хотим как-то «инвертировать» это отображение. Я пишу свою собственную функцию invMap:

 invMap <- function(map) { items <- as.character( unlist(map) ) nams <- unlist(Map(rep, names(map), sapply(map, length))) names(nams) <- items nams } 

а затем инвертируйте приведенную выше карту следующим образом:

 > invMap(myMap) cow pig eagle pigeon "animal" "animal" "bird" "bird" 

И тогда это легко использовать для добавления столбца type в кадре данных:

 df <- transform(df, type = invMap(myMap)[name]) > df name type 1 cow animal 2 pig animal 3 eagle bird 4 pigeon bird 

case_when() , который был добавлен в dplyr в мае 2016 года, решает эту проблему аналогично memisc::cases() .

Например:

 library(dplyr) mtcars %>% mutate(category = case_when( .$cyl == 4 & .$disp < median(.$disp) ~ "4 cylinders, small displacement", .$cyl == 8 & .$disp > median(.$disp) ~ "8 cylinders, large displacement", TRUE ~ "other" ) ) 

Imho, самый простой и универсальный код:

 dft=data.frame(x = sample(letters[1:8], 20, replace=TRUE)) dft=within(dft,{ y=NA y[x %in% c('a','b','c')]='abc' y[x %in% c('d','e','f')]='def' y[x %in% 'g']='g' y[x %in% 'h']='h' }) в dft=data.frame(x = sample(letters[1:8], 20, replace=TRUE)) dft=within(dft,{ y=NA y[x %in% c('a','b','c')]='abc' y[x %in% c('d','e','f')]='def' y[x %in% 'g']='g' y[x %in% 'h']='h' }) 

Я не вижу предложения для «переключателя». Пример кода (запустите его):

 x <- "three"; y <- 0; switch(x, one = {y <- 5}, two = {y <- 12}, three = {y <- 432}) y 

Вы можете использовать recode из пакета автомобилей:

 library(ggplot2) #get data library(car) daimons$new_var <- recode(diamonds$clarity , "'I1' = 'low';'SI2' = 'low';else = 'high';")[1:10] 

Существует инструкция switch но я никогда не смогу заставить ее работать так, как мне кажется. Поскольку вы не представили пример, я сделаю один с использованием фактор-переменной:

  dft <-data.frame(x = sample(letters[1:8], 20, replace=TRUE)) levels(dft$x) [1] "a" "b" "c" "d" "e" "f" "g" "h" 

Если вы укажете категории, которые вы хотите в заказе, соответствующем переназначению, вы можете использовать фактор или числовые переменные в качестве индекса:

 c("abc", "abc", "abc", "def", "def", "def", "g", "h")[dft$x] [1] "def" "h" "g" "def" "def" "abc" "h" "h" "def" "abc" "abc" "abc" "h" "h" "abc" [16] "def" "abc" "abc" "def" "def" dft$y <- c("abc", "abc", "abc", "def", "def", "def", "g", "h")[dft$x] str(dft) 'data.frame': 20 obs. of 2 variables: $ x: Factor w/ 8 levels "a","b","c","d",..: 4 8 7 4 6 1 8 8 5 2 ... $ y: chr "def" "h" "g" "def" ... 

Позже я узнал, что на самом деле существуют две разные функции переключения. Это не общая функция, но вы должны думать об этом как о switch.numeric или switch.character . Если ваш первый аргумент является фактором R ', вы получаете switch.numeric поведение, которое может вызвать проблемы, поскольку большинство людей видят факторы, отображаемые как символ, и делают неправильное предположение о том, что все функции будут обрабатывать их как таковые.

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

 result <- ( function() { if (x==10 | y< 5) return('foo') if (x==11 & y== 5) return('bar') })() 

все из них () необходимо заключить и оценить анонимную функцию.

Смешивание plyr::mutate и dplyr::case_when работает для меня и читается.

 iris %>% plyr::mutate(coolness = dplyr::case_when(Species == "setosa" ~ "not cool", Species == "versicolor" ~ "not cool", Species == "virginica" ~ "super awesome", TRUE ~ "undetermined" )) -> testIris head(testIris) levels(testIris$coolness) ## NULL testIris$coolness <- as.factor(testIris$coolness) levels(testIris$coolness) ## ok now testIris[97:103,4:6] 

Бонусные очки, если столбец может выйти из мутанта как фактор вместо char! Последняя строка оператора case_when, которая захватывает все несогласованные строки, очень важна.

  Petal.Width Species coolness 97 1.3 versicolor not cool 98 1.3 versicolor not cool 99 1.1 versicolor not cool 100 1.3 versicolor not cool 101 2.5 virginica super awesome 102 1.9 virginica super awesome 103 2.1 virginica super awesome 

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

Скажем, у вас есть фактор с буквами от A до E, вот так.

 > a <- factor(rep(LETTERS[1:5],2)) > a [1] ABCDEABCDE Levels: ABCDE 

Чтобы присоединиться к уровням B и C и называть его BC, просто измените имена этих уровней на BC.

 > levels(a) <- c("A","BC","BC","D","E") > a [1] A BC BC DEA BC BC DE Levels: A BC DE 

Результат по желанию.

Если вы хотите иметь sql-подобный синтаксис, вы можете просто использовать sqldf пакет. Функция, которая будет использоваться, также является именем sqldf а синтаксис выглядит следующим образом

 sqldf() 

Вы можете использовать merge base функций для задач переназначения в стиле case:

 df <- data.frame(name = c('cow','pig','eagle','pigeon','cow','eagle'), stringsAsFactors = FALSE) mapping <- data.frame( name=c('cow','pig','eagle','pigeon'), category=c('animal','animal','bird','bird') ) merge(df,mapping) # name category # 1 cow animal # 2 cow animal # 3 eagle bird # 4 eagle bird # 5 pig animal # 6 pigeon bird 

Я использую в тех случаях, когда вы ссылаетесь на switch() . Это похоже на инструкцию управления, но на самом деле это функция. Выражение оценивается и на основе этого значения возвращается соответствующий элемент в списке.

коммутатор работает двумя различными способами в зависимости от того, оценивает ли первый аргумент строку символов или число.

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

Для формы с символьной строкой укажите один именованный аргумент как значение по умолчанию после именованных значений.

 newCat <- switch(EXPR = category, cat1 = catX, cat2 = catX, cat3 = catY, cat4 = catY, cat5 = catZ, cat6 = catZ, "not available") 
Давайте будем гением компьютера.