我有一个包含数字和有序因子列的数据框。我有很多NA值,因此没有为它们分配级别。我将NA更改为“无应答”,但因子列的级别不包含该级别,所以这是我的开始,但我不知道如何以优雅的方式完成它:
addNoAnswer = function(df) {
factorOrNot = sapply(df, is.factor)
levelsList = lapply(df[, factorOrNot], levels)
levelsList = lapply(levelsList, function(x) c(x, "No Answer"))
...
有没有办法直接将新级别应用于因子列,例如:
df[, factorOrNot] = lapply(df[, factorOrNot], factor, levelsList)
当然,这不能正常工作。
我希望保留级别的顺序,并将“无应答”级别添加到最后一个位置。
答案 0 :(得分:26)
您可以定义一个函数,将级别添加到因子,但只返回其他任何内容:
addNoAnswer <- function(x){
if(is.factor(x)) return(factor(x, levels=c(levels(x), "No Answer")))
return(x)
}
然后你只需lapply
这个功能到你的专栏
df <- as.data.frame(lapply(df, addNoAnswer))
应该返回你想要的东西。
答案 1 :(得分:20)
levels
函数接受levels(x) <- value
调用。因此,添加不同级别非常容易:
f1 <- factor(c("a", "a", NA, NA, "b", NA, "a", "c", "a", "c", "b"))
str(f1)
Factor w/ 3 levels "a","b","c": 1 1 NA NA 2 NA 1 3 1 3 ...
levels(f1) <- c(levels(f1),"No Answer")
f1[is.na(f1)] <- "No Answer"
str(f1)
Factor w/ 4 levels "a","b","c","No Answer": 1 1 4 4 2 4 1 3 1 3 ...
然后,您可以将其循环到data.frame中的所有变量:
f1 <- factor(c("a", "a", NA, NA, "b", NA, "a", "c", "a", "c", "b"))
f2 <- factor(c("c", NA, "b", NA, "b", NA, "c" ,"a", "d", "a", "b"))
f3 <- factor(c(NA, "b", NA, "b", NA, NA, "c", NA, "d" , "e", "a"))
df1 <- data.frame(f1,n1=1:11,f2,f3)
str(df1)
'data.frame': 11 obs. of 4 variables:
$ f1: Factor w/ 3 levels "a","b","c": 1 1 NA NA 2 NA 1 3 1 3 ...
$ n1: int 1 2 3 4 5 6 7 8 9 10 ...
$ f2: Factor w/ 4 levels "a","b","c","d": 3 NA 2 NA 2 NA 3 1 4 1 ...
$ f3: Factor w/ 5 levels "a","b","c","d",..: NA 2 NA 2 NA NA 3 NA 4 5 ...
for(i in 1:ncol(df1)) if(is.factor(df1[,i])) levels(df1[,i]) <- c(levels(df1[,i]),"No Answer")
df1[is.na(df1)] <- "No Answer"
str(df1)
'data.frame': 11 obs. of 4 variables:
$ f1: Factor w/ 4 levels "a","b","c","No Answer": 1 1 4 4 2 4 1 3 1 3 ...
$ n1: int 1 2 3 4 5 6 7 8 9 10 ...
$ f2: Factor w/ 5 levels "a","b","c","d",..: 3 5 2 5 2 5 3 1 4 1 ...
$ f3: Factor w/ 6 levels "a","b","c","d",..: 6 2 6 2 6 6 3 6 4 5 ...
答案 2 :(得分:3)
自上次回答此问题以来,使用fct_explicit_na()
包中的forcats
可以实现此问题。我在这里添加了文档中给出的示例。
f1 <- factor(c("a", "a", NA, NA, "a", "b", NA, "c", "a", "c", "b"))
table(f1)
# f1
# a b c
# 4 2 2
f2 <- forcats::fct_explicit_na(f1)
table(f2)
# f2
# a b c (Missing)
# 4 2 2 3
默认值为(Missing)
,但可以通过na_level
参数更改。
答案 3 :(得分:3)
扩展ilir's answer及其注释,您可以检查列是否是一个因素,并且它尚未包含新级别,然后添加级别,从而使该函数可重新运行:
addLevel <- function(x, newlevel=NULL) {
if(is.factor(x)) {
if (is.na(match(newlevel, levels(x))))
return(factor(x, levels=c(levels(x), newlevel)))
}
return(x)
}
然后您可以像这样应用它:
dataFrame$column <- addLevel(dataFrame$column, "newLevel")
答案 4 :(得分:1)
您需要将列转换为字符,然后根据条件添加新级别,然后在最后一次将列转换为因子。
步骤 1.First Convert Factor列到字符:
df$column2 <- as.character(column2)
2.添加新级别
df[df$column1=="XYZ",]column2 <- "new_level"
3.再次转换为因素
df$column2 <- as.factor(df$column2)
答案 5 :(得分:0)
我有一个非常简单的答案,可能无法直接解决您的特定情况,但通常是执行此操作的简单方法
levels(df$column) <- c(levels(df$column), newFactorLevel)
答案 6 :(得分:0)
对于因子,级别是分配给因子变量的每个唯一值的数值。使用因子的优点是类别变量更适合可视化。因子变量的原始值即使是数字也存储为字符。因此,要检索原始值,请首先使用转换as.character-这将返回因子值,而不是以零开头的级别数字。拥有字符格式的值后,请使用as.numeric获取原始数字值。
factor_var.values = as.numeric(as.character(df $ factor_var))