如何更改data.table中因子列的级别

时间:2013-01-31 20:54:50

标签: r data.table

更改factordata.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

5 个答案:

答案 0 :(得分:59)

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

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

除非mydt非常大,否则这应该很快,因为传统语法会复制整个对象。你也可以玩非保理和重构游戏......但是无论如何也没有人喜欢那个游戏。

要通过引用更改级别而不复制mydt

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

但请务必指定有效级别向量(类型character足够长),否则您将得到无效因素(levels<-进行一些检查以及复制)。

答案 1 :(得分:4)

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

> 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:如果级别太多,请使用循环结构。

答案 2 :(得分:3)

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

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

(从?levels修改)

答案 3 :(得分:0)

这比Matt Dowle的建议更安全(因为它使用了setattr跳过的检查),但是不会复制整个data.table。它将替换整个列向量(而Matt的解决方案仅替换了列向量的属性),但这似乎是可以接受的折衷方案,目的是降低混乱因子对象的风险。

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

答案 4 :(得分:-1)

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

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