web-dev-qa-db-ja.com

data.tableのfactor列のレベルをどのように変更しますか

data.tablefactor列のレベルを変更する正しい方法は何ですか(注:データフレームではありません)

  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
46
Ricardo Saporta

引き続き従来の方法で設定できます。

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

これは、従来の構文がオブジェクト全体をコピーするため、mydtが非常に大きい場合を除き、かなり高速です。また、非ファクタリングとリファクタリングのゲームをプレイすることもできます...しかし、とにかく誰もそのゲームが好きではありません。

mydtのコピーなしで参照によってレベルを変更するには:

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

ただし、有効なレベルベクトル(十分な長さのcharacter型)を割り当ててください。そうしないと、無効な係数(levels<-はいくつかのチェックとコピーを行います)。

59
Justin

私はむしろ、因子への再割り当ての伝統的な方法に行きたい

_> 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") very non-intuitiveのように名前を変更するレベルを見つけます。これは、Xをデータ内で最初のレベルに割り当てるだけなので(順序が本当に重要です)

PPS:レベルが多すぎる場合は、ループ構造を使用します。

5
ekta

関連するアプローチを使用してレベルの名前を変更し、レベルに追加することもできます。これは、特にデフォルトではなく特定の順序でより有益なラベルを必要とするプロットを作成する場合に非常に便利です。

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

?levelsから変更)

3
Bryan Hanson