56

更改 afactor中列级别的正确方法是什么data.table (注意:不是数据框)

  library(data.table)
  mydt <- data.table(id=1:6, value=as.factor(c("A", "A", "B", "B", "B", "C")), key="id")

  mydt[, levels(value)]
  [1] "A" "B" "C"

我正在寻找类似的东西:

mydt[, levels(value) <- c("X", "Y", "Z")]

但是,当然,上面的行是行不通的。

    # Actual               # Expected result
    > mydt                  > mydt
       id value                id value
    1:  1     A             1:  1     X
    2:  2     A             2:  2     X
    3:  3     B             3:  3     Y
    4:  4     B             4:  4     Y
    5:  5     B             5:  5     Y
    6:  6     C             6:  6     Z
4

5 回答 5

73

您仍然可以以传统方式设置它们:

levels(mydt$value) <- c(...)

这应该非常快,除非mydt非常大,因为传统语法会复制整个对象。你也可以玩分解和重构的游戏……但无论如何,没有人喜欢这种游戏。

要通过引用更改级别而没有副本mydt

setattr(mydt$value,"levels",c(...))

但一定要分配一个有效的级别向量(character足够长度的类型),否则你最终会得到一个无效的因素(levels<-做一些检查和复制)。

于 2013-01-31T21:08:26.200 回答
9

我宁愿采用传统的方式重新分配因素

> mydt$value # This we what we had originally
[1] A A B B B C
Levels: A B C
> levels(mydt$value) # just checking the levels
[1] "A" "B" "C"
**# Meat of the re-assignment**
> levels(mydt$value)[levels(mydt$value)=="A"] <- "X"
> levels(mydt$value)[levels(mydt$value)=="B"] <- "Y"
> levels(mydt$value)[levels(mydt$value)=="C"] <- "Z"
> levels(mydt$value)
[1] "X" "Y" "Z"
> mydt # This is what we wanted
   id value
1:  1     X
2:  2     X
3:  3     Y
4:  4     Y
5:  5     Y
6:  6     Z

正如您可能注意到的那样,重新分配的内容非常直观,它会检查确切的内容level(用于grepl存在模糊数学、正则表达式或类似情况的情况)

levels(mydt$value)[levels(mydt$value)=="A"] <- "X" 这会显式检查 levels 正在考虑的变量的值,然后重新分配X(等等)给它 - 优点 - 你明确知道什么标记了什么。

我发现在这里重命名级别levels(mydt$value) <- c("X","Y","Z")非常不直观,因为它只是分配X给它在数据中看到的第一个级别(所以顺序真的很重要)

PPS:如果级别太多,请使用循环结构。

于 2014-01-15T11:12:35.377 回答
5

您还可以使用相关方法重命名并添加到您的关卡,这非常方便,特别是如果您正在制作一个需要以特定顺序(而不是默认顺序)提供更多信息标签的绘图:

f <- factor(c("a","b"))
levels(f) <- list(C = "C", D = "a", B = "b")

(修改自?levels

于 2013-01-31T21:44:30.793 回答
0

这比 Matt Dowle 的建议更安全(因为它使用了 setattr 跳过的检查),但不会复制整个 data.table。它将替换整个列向量(而马特的解决方案只替换列向量的属性),但这似乎是一个可以接受的权衡,以减少弄乱因子对象的风险。

mydt[, value:=`levels<-`(value, c("X", "Y", "Z"))]
于 2020-07-20T03:19:04.493 回答
-1

更改列级别的最简单方法:

dat$colname <- as.factor(as.vector(dat$colname));

于 2016-10-20T14:07:34.280 回答