题 替换R数据帧中因子列的内容


我需要替换数据帧中因子列的级别。使用 iris 以数据集为例,我将如何替换包含的任何单元格 virginica 同 setosa 在里面 种类 柱?

我期望以下工作,但它会生成一条警告消息,只需插入NAs:

iris$Species[iris$Species == 'virginica'] <- 'setosa'

35
2017-08-04 17:30


起源


你的例子 iris 只是工作。你能以其他方式复制你的问题吗?目前很难理解你想做什么。 - Andrie
适合我。你收到哪条警告信息? - sgibb
它再次尝试时与虹膜配合使用。但是将相同的内容应用于我的数据集会产生以下结果:警告消息:In [<-.factor(*tmp*,x $ Hweet ==“hweet”,value = c(NA_integer_,:无效因子级别,生成的NAs - luciano
我强烈怀疑你想要操作 水平 这个因素而不是元素本身......基于你之前(非常相似)的问题,我想你可能会因为问一个问题而变得更远 略 时间越长, 重复性,更完整的问题,解释你正在尝试做什么... - Ben Bolker


答案:


我打赌问题是当你试图用新的值替换值时,这个值当前不是现有因子的一部分:

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'

76
2017-08-04 17:51



但是如果你想用物种B取代物种A你会更好 levels(iris$Species)[match("oldspecies",levels(iris$Species))] <- "newspecies" - Ben Bolker
@flodel - 完全正确 - luciano
+1很好的答案。你从哪里得到了你的阅读机器? :-) - Andrie


对于您建议的事情,您可以使用更改级别 levels

levels(iris$Species)[3] <- 'new'

10
2017-08-04 22:10



在多列上有一次性的方法吗?例如,我有多个具有'TRUE'和'FALSE'值的列,我想将其重新编码为'0','1' - UD1989
@ UD1989,只需使用: mydf[] <- lapply(mydf, as.numeric) - Greg Snow


你可以使用这个功能 revalue 从包中 plyr 替换因子向量中的值。

在您的示例中替换因子 virginica 通过 setosa

 data(iris)
 library(plyr)
 revalue(iris$Species, c("virginica" = "setosa")) -> iris$Species

8
2018-01-28 19:29



如果我没有旧的价值怎么办? //并且不想仅仅为了在这个方法中使用它而获取旧值 - Mohit Verma


我有同样的问题。这效果更好:

确定要修改的级别: levels(iris$Species)

    "setosa" "versicolor" "virginica" 

所以, setosa 是第一个。

然后,写下这个:

     levels(iris$Species)[1] <-"new name"

3
2018-03-23 13:13





一个更通用的解决方案可以同时处理所有数据框,而不必添加新的因子级别:

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",新值可以是随机值。因此,您可以创建一个与原始大小相同的完整新随机数据框。


1
2018-01-12 15:32





运用 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   

0
2018-03-09 14:00





如果你不得不替换多个值,并且你不介意用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))

0
2018-03-20 14:15