#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
fromdplyr
, мне кажется, что это не совсем мой случай, так как я хочу заранее установить 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))
просто может увенчаться успехом.