web-dev-qa-db-ja.com

値の順序を変更せずに因子のレベルを並べ替える

データフレームにいくつかの数値変数といくつかのカテゴリfactor変数があります。これらの要素のレベルの順序は、私が望むものではありません。

numbers <- 1:4
letters <- factor(c("a", "b", "c", "d"))
df <- data.frame(numbers, letters)
df
#   numbers letters
# 1       1       a
# 2       2       b
# 3       3       c
# 4       4       d

レベルの順序を変更すると、文字に対応する番号が表示されなくなります(これ以降、私のデータはまったくナンセンスです)。

levels(df$letters) <- c("d", "c", "b", "a")
df
#   numbers letters
# 1       1       d
# 2       2       c
# 3       3       b
# 4       4       a

levelの順序を変更したいだけなので、プロットするとき、バーは希望する順序で表示されます。デフォルトのアルファベット順とは異なる場合があります。

113
crangos

levelsfactor引数を使用します。

df <- data.frame(f = 1:4, g = letters[1:4])
df
#   f g
# 1 1 a
# 2 2 b
# 3 3 c
# 4 4 d

levels(df$g)
# [1] "a" "b" "c" "d"

df$g <- factor(df$g, levels = letters[4:1])
# levels(df$g)
# [1] "d" "c" "b" "a"

df
#   f g
# 1 1 a
# 2 2 b
# 3 3 c
# 4 4 d
112
Jonathan Chang

記録のためだけに

## reorder is a base function
df$letters <- reorder(df$letters, new.order=letters[4:1])

library(gdata)
df$letters <- reorder.factor(df$letters, letters[4:1])

また、便利な Relevel および combine_factor が見つかるかもしれません。

20
George Dontas

したがって、R辞書で必要なのは、特定の因子変数のlabelsのみを変更することです(つまり、データと係数levels、変更なし)。

df$letters = factor(df$letters, labels=c("d", "c", "b", "a"))

データポイントからラベルへのマッピングのみを変更し、データまたは因子スキーマ(データポイントを個々のビンにビン化する方法またはファクター値の場合、最初にファクターを作成するときにマッピングが元々どのように設定されているかを知ることが役立つ場合があります。

ルールは単純です:

  • ラベルはインデックス値によってレベルにマップされます(つまり、levels [2]の値にはラベルlabel [2]が与えられます)。
  • 因子レベルは、levels引数を介して渡すことで明示的に設定できます。または
  • レベル引数に値が指定されていない場合、デフォルト値が使用されます。デフォルト値は、渡されたデータベクトルでuniqueを呼び出した結果です(data引数);
  • labels引数を使用してラベルを明示的に設定できます。または
  • labels引数に値が指定されていない場合は、levelsベクトルだけであるデフォルト値が使用されます
8
doug

Rの因子を扱うのは非常に奇妙な仕事です。認めなければなりません...因子レベルを並べ替えるとき、基礎となる数値を並べ替えるわけではありません。ここに小さなデモがあります:

_> numbers = 1:4
> letters = factor(letters[1:4])
> dtf <- data.frame(numbers, letters)
> dtf
  numbers letters
1       1       a
2       2       b
3       3       c
4       4       d
> sapply(dtf, class)
  numbers   letters 
"integer"  "factor" 
_

この係数を数値に変換すると、次のようになります:

_# return underlying numerical values
1> with(dtf, as.numeric(letters))
[1] 1 2 3 4
# change levels
1> levels(dtf$letters) <- letters[4:1]
1> dtf
  numbers letters
1       1       d
2       2       c
3       3       b
4       4       a
# return numerical values once again
1> with(dtf, as.numeric(letters))
[1] 1 2 3 4
_

ご覧のように...レベルを変更することで、数値ではなく、レベルのみを変更します(ええ?)。しかし、@ Jonathan Changが提案したようにfactor関数を使用すると、何か別のことが起こります。数値自体を変更します。

levelsを実行してからfactorでレベルを変更しようとするため、もう一度エラーが発生します。しないでください!!!行う じゃない levelsを使用すると、混乱してしまいます(実行していることを正確に把握していない場合)。

ちょっとした提案:Rのオブジェクトと同じ名前でオブジェクトに名前を付けないでください(dfはF分布の密度関数、lettersは小文字のアルファベットを表します)。この特定のケースでは、コードに欠陥はありませんが、場合によっては...可能性がありますが、これにより混乱が生じる可能性があります。 =)

代わりに、次のようなものを使用します(最初からもう一度行きます)。

_> dtf <- data.frame(f = 1:4, g = factor(letters[1:4]))
> dtf
  f g
1 1 a
2 2 b
3 3 c
4 4 d
> with(dtf, as.numeric(g))
[1] 1 2 3 4
> dtf$g <- factor(dtf$g, levels = letters[4:1])
> dtf
  f g
1 1 a
2 2 b
3 3 c
4 4 d
> with(dtf, as.numeric(g))
[1] 4 3 2 1
_

dfの代わりにlettersgを使用して_data.frame_という名前を付けることもできることに注意してください。結果はOKです。実際、このコードは投稿したものと同じで、名前のみが変更されています。この部分factor(dtf$letter, levels = letters[4:1])はエラーをスローしませんが、混乱させる可能性があります!

_?factor_マニュアルをよくお読みください! factor(g, levels = letters[4:1])factor(g, labels = letters[4:1])の違いは何ですか? levels(g) <- letters[4:1]g <- factor(g, labels = letters[4:1])の類似点は何ですか?

Ggplot構文を使用できますので、これについてさらにお手伝いします!

乾杯!!!

編集:

_ggplot2_は実際にレベルと値の両方を変更する必要がありますか?うーん...私はこれを掘ります...

6
aL3xa

この質問が最後にアクティブだったので、Hadleyは因子を操作するための彼の新しいforcatsパッケージをリリースしました。 OPのデータフレームの例:

_levels(df$letters)
# [1] "a" "b" "c" "d"
_

レベルを反転するには:

_library(forcats)
fct_rev(df$letters) %>% levels
# [1] "d" "c" "b" "a"
_

レベルを追加するには:

_fct_expand(df$letters, "e") %>% levels
# [1] "a" "b" "c" "d" "e"
_

さらに多くの便利なfct_xxx()関数。

4
Joe

レベルがいくつかの特殊文字と一緒に数字を運ぶ文字列である可能性がある別のケースを追加したい:下の例のように

df <- data.frame(x = c("15-25", "0-4", "5-10", "11-14", "100+"))

xのデフォルトレベルは次のとおりです。

df$x
# [1] 15-25 0-4   5-10  11-14 100+ 
# Levels: 0-4 100+ 11-14 15-25 5-10

ここで、明示的にレベルを書き出すことなく、数値に従って因子レベルを並べ替えたい場合、できることは

library(gtools)
df$x <- factor(df$x, levels = mixedsort(df$x))

df$x
# [1] 15-25 0-4   5-10  11-14 100+ 
# Levels: 0-4 5-10 11-14 15-25 100+
as.numeric(df$x)
# [1] 4 1 2 3 5

これが将来の読者にとって有用な情報とみなされることを願っています。

3
joel.wilson

特定のデータフレームの因子を並べ替える私の機能は次のとおりです。

_reorderFactors <- function(df, column = "my_column_name", 
                           desired_level_order = c("fac1", "fac2", "fac3")) {

  x = df[[column]]
  lvls_src = levels(x) 

  idxs_target <- vector(mode="numeric", length=0)
  for (target in desired_level_order) {
    idxs_target <- c(idxs_target, which(lvls_src == target))
  }

  x_new <- factor(x,levels(x)[idxs_target])

  df[[column]] <- x_new

  return (df)
}
_

使用法:reorderFactors(df, "my_col", desired_level_order = c("how","I","want"))

0
Boern