Как я могу переоценить элементы в факторе на основе значений аргументов, переданных функции в R?

#r #function #replace #parameter-passing #plyr

Вопрос:

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

Например, если я хочу переоценить уровни в факторе my_factor («кошки» -> «животные», «сосны» ->> «деревья»), я использую: >> my_factor <- revalue(my_factor, c("cats"="animals", "pines"="trees")) . Но теперь я хочу переоценить уровни на основе значений аргументов, переданных функции:

 myFunction(..., member1 = "cats", member2 = "pines") {
my_factor <- revalue(my_factor, c(member1="animals", member2="trees"))
}
 

Этот фрагмент кода не работает ( Error: The following из values were not present in x : member1, member2 ).

Пожалуйста, скажите мне, как это сделать правильно?
Возможно, мне нужно использовать что-то другое, чем revalue .

Ответ №1:

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

Базовая функция levels<- сделает это чисто. Когда вы делаете что-то вроде:

 levels(fac)[some_index] <- "something"
 

Вы изменяете значение печати этого уровня без изменения базового шаблона целых множителей, которые несут информацию. Поэтому используйте levels(fac) ; один раз , чтобы получить текущие значения уровней, чтобы создать логический индекс для использования внутри » [ » , и снова «снаружи» LHS, чтобы выполнить переназначение:

 levels(fac)[ levels(fac) == "cats"] <- "animals"
levels(fac)[ levels(fac) == "pines"] <- "trees"
 

На самом деле вы используете две разные функции: levels<- (снаружи) и levels (внутри). Чтобы превратить этот процесс в функцию, которая может обрабатывать произвольное количество назначений, вам нужно, чтобы пары назначений были перенесены в список списков, чтобы вы могли перебирать пары. Ваш текущий запрос пытается использовать языковое выражение, такое как "cats" = "animals" , но это создаст параметр cats со значением "animals" . Глядя на код plyr::revalue , я вижу, что затем ему нужно отменить эту конструкцию, прежде чем он отправит имена и значения в mapvalues который работает с двумя отдельными наборами параметров. Во всяком случае, это попытка старой школы.

 reval <- function(x)(fac, reassigns) {
             levs <-lapply(reassigns, function(fac, pair) {
                       levels(fac)[levels(fac)==pair[[1]]] <-pair[[2]]}
                                      return(levs) }
 

И вы бы назвали это так:

 levels(facname) <- reval ( facname, list( list("curlev1", "newlev1"),
                                  list("curlev2", "newlev2")) )  )
 

Если у вас есть пример из примера именования, которое вы использовали «my_factor («кошки» -> «животные», «сосны» ->> «деревья»)», затем протестируйте его с помощью

 levels(my_factor)<- reval(my_factor, reassigns = list (list("cats" , "animals"),
                                           list("pines", "trees") ) )
 

Если это не сработает, вам следует опубликовать код R, чтобы создать пример, который можно использовать для дальнейшей разработки и тестирования. И, глядя на dplyr индекс, я вижу recode функцию, которая имеет факторный метод. Это пример со страницы справки, которая, как представляется, соответствует вашим желаниям:

 # For factor values, use only named replacements
# and supply default with levels()
factor_vec <- factor(c("a", "b", "c"))
recode(factor_vec, a = "Apple", .default = levels(factor_vec))
 

Как (почти) всегда, R фактически не изменится factor_vec , если вы не присвоите результат перекодирования исходному имени

 factor_vec <- recode(factor_vec, a = "Apple", .default = levels(factor_vec))
 

Комментарии:

1. Большое вам спасибо за такой подробный ответ, я добавил pair в вашу функцию, так как R указал, что она не была установлена. reval <- function(fac, reassigns) { for (i in 1:length(reassigns)) { pair <- reassigns[[i]] levs <-lapply(reassigns, function(fac, pair) { levels(fac)[levels(fac)==pair[[1]]] <-pair[[2]]}) return(levs) } } Но это вызывает ту же ошибку: Error in FUN(X[[i]], ...): argument "pair" is missing, with no default . Не могли бы вы помочь с модификацией, пожалуйста?

2. my_factor <- factor(c("cats", "cats", "pines")) curlev1 <- "cats" curlev2 <- "pines" reval(my_factor, reassigns = list (list(curlev1 , "animals"), list(curlev2 , "trees") ) )

3. Что касается использования recode from dplyr , мне кажется, что это не совсем мой случай, так как я хочу заранее установить curlev. factor_vec <- factor(c("a", "b", "c")) name <- "a" recode(factor_vec, name = "Apple", .default = levels(factor_vec)) ‘factor_vec’ остается прежним ( "a", "b", "c" ).

4. Но я думаю, что могу использовать метод решения в более простой версии: reval_simple <- function(my_factor, curlev1, curlev2) { levels(my_factor)[levels(my_factor) == curlev1] <- "animals" levels(my_factor)[levels(my_factor) ==curlev2] <- "trees" return(my_factor) } И тогда: some_my_factor <- factor(c("cats", "cats", "pines")) some_curlev1 <- "cats" some_curlev2 <- "pines" reval_simple(some_my_factor, some_curlev1, some_curlev2)

5. Прочитайте последний фрагмент еще раз: recode(factor_vec, name = "Apple", .default = levels(factor_vec)) не будет иметь длительного эффекта, но factor_vec <- recode(factor_vec, name = "Apple", .default = levels(factor_vec)) просто может увенчаться успехом.