我需要替换数据帧中因子列的级别。以iris
数据集为例,我如何在Species列中用virginica
替换任何包含setosa
的单元格?
我期望以下工作,但它会生成一条警告消息,只需插入NAs:
iris$Species[iris$Species == 'virginica'] <- 'setosa'
我敢打赌问题是当你试图用新的值替换值时,这个值当前不是现有因子的一部分:
levels(iris$Species)
# [1] "setosa" "versicolor" "virginica"
你的例子不好,这有效:
iris$Species[iris$Species == 'virginica'] <- 'setosa'
这更有可能产生您使用自己的数据看到的问题:
iris$Species[iris$Species == 'virginica'] <- 'new.species'
# Warning message:
# In `[<-.factor`(`*tmp*`, iris$Species == "virginica", value = c(1L, :
# invalid factor level, NAs generated
如果您首先提高因子水平,它将起作用:
levels(iris$Species) <- c(levels(iris$Species), "new.species")
iris$Species[iris$Species == 'virginica'] <- 'new.species'
对于您建议的事情,您可以使用levels
更改级别:
levels(iris$Species)[3] <- 'new'
您可以使用包revalue
中的函数plyr
来替换因子向量中的值。
在你的例子中用virginica
替换因子setosa
:
data(iris)
library(plyr)
revalue(iris$Species, c("virginica" = "setosa")) -> iris$Species
我有同样的问题。这效果更好:
确定要修改的级别:levels(iris$Species)
"setosa" "versicolor" "virginica"
所以,setosa
是第一个。
然后,写下这个:
levels(iris$Species)[1] <-"new name"
一个更通用的解决方案可以同时处理所有数据框,并且您不必添加新的因子级别:
data.mtx <- as.matrix(data.df)
data.mtx[which(data.mtx == "old.value.to.replace")] <- "new.value"
data.df <- as.data.frame(data.mtx)
此代码的一个很好的功能是,您可以一次分配原始数据框中的多个值,而不仅仅是一个"new.value"
,新值可以是随机值。因此,您可以创建一个与原始大小相同的完整的新随机数据框。
使用dlpyr::mutate
和forcats::fct_recode
:
library(dplyr)
library(forcats)
iris <- iris %>%
mutate(Species = fct_recode(Species,
"Virginica" = "virginica",
"Versicolor" = "versicolor"
))
iris %>%
count(Species)
# A tibble: 3 x 2
Species n
<fctr> <int>
1 setosa 50
2 Versicolor 50
3 Virginica 50
如果你不得不替换多个值,如果你不介意用as.factor(as.character(...))“重构”你的变量,你可以尝试以下方法:
replace.values <- function(search, replace, x){
stopifnot(length(search) == length(replace))
xnew <- replace[ match(x, search) ]
takeOld <- is.na(xnew) & !is.na(x)
xnew[takeOld] <- x[takeOld]
return(xnew)
}
iris$Species <- as.factor(search=c("oldValue1","oldValue2"),
replace=c("newValue1","newValue2"),
x=as.character(iris$Species))
您想要替换数据集列中的值,但是您收到如下错误:
无效因子水平,NA生成
试试这个:
levels(dataframe$column)[levels(dataframe$column)=='old_value'] <- 'new_value'