Переменная фактора приведена к символу при замене NA на число с помощью apply () - PullRequest
0 голосов
/ 14 февраля 2019

Я заметил странное поведение apply () при попытке заменить NA числом 9 для многофакторных переменных.Я уже определил уровни и метки этих переменных.Когда я использую ifelse () для каждой переменной в отдельности (например, ifelse (is.na (x), 9, x)), она переводит переменную в целое число, что понятно. Однако, когда я заставляю функцию делать то же самое иИспользуйте apply () для нескольких столбцов, он привел все переменные в символ. Добавление еще одного шага для преобразования их обратно в фактор в функции не помогает. Я что-то упустил или это странно в функциях apply ()? Спасибо!

a<-c(1,2,3,NA,2)
b<-c(2,1,2,2,NA)
a<-factor(a,levels=c(1,2,3),labels=c("First","Second","Third"))
b<-factor(b,levels=c(1,2,3), labels=c("AA","BB","CC"))
dat<-cbind(a,b)
replace.na<-function(x){
    x<-as.factor(ifelse(is.na(x),9,x))
}
a<-ifelse(is.na(a),9,a)
str(a)
dat<-apply(dat,2,replace.na)
str(dat)

Я ожидаю, что apply () выдаст переменные того же типа, или, по крайней мере, использование as.factor () в функции приведет переменную к фактору.

1 Ответ

0 голосов
/ 16 февраля 2019

Основная трудность при работе с факторами заключается в том, что они не могут принять присвоение значения, которого нет на существующих уровнях.Ваш пример не иллюстрирует это, так как вы использовали cbind, который приводит факторы к их целочисленным значениям.Факторы - это действительно целочисленные векторы с атрибутом уровней.Если вы хотите получить структуру, которая будет принимать назначения за пределами существующих уровней, то у вас есть два варианта: 1) преобразовать факторы с помощью as.character или 2) сначала увеличить уровни факторов с помощью levels(fac) <- c(levels(fac), new_values).

Поскольку вы хотите работать с несколькими столбцами в матрице, я думаю, что было бы лучше использовать первый вариант преобразования в символ перед использованием cbind.

 a<-c(1,2,3,NA,2)
 b<-c(2,1,2,2,NA)
 a<-factor(a,levels=c(1,2,3),labels=c("First","Second","Third"))
 b<-factor(b,levels=c(1,2,3), labels=c("AA","BB","CC"))
 dat<-cbind( as.character(a), as.character(b))
 replace.na<-function(x){
     x<-as.factor(ifelse(is.na(x), 9, x))
 }
 a<-ifelse(is.na(a),9,a)
 str(a)
num [1:5] 1 2 3 9 2    #shows the underlying numeric values after changing `a`
 dat<-apply(dat,2,replace.na)
 str(dat)             # the dat object was not affected by the second modification of `a`
chr [1:5, 1:2] "First" "Second" "Third" "9" "Second" "BB" "AA" "BB" "BB" ...
dat
#---------------
     [,1]     [,2]
[1,] "First"  "BB"
[2,] "Second" "AA"
[3,] "Third"  "BB"
[4,] "9"      "BB"
[5,] "Second" "9" 
...