データフレームにいくつかの数値変数といくつかのカテゴリ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の順序を変更したいだけなので、プロットするとき、バーは希望する順序で表示されます。デフォルトのアルファベット順とは異なる場合があります。
levels
のfactor
引数を使用します。
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
記録のためだけに
## 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 が見つかるかもしれません。
したがって、R辞書で必要なのは、特定の因子変数のlabelsのみを変更することです(つまり、データと係数levels、変更なし)。
df$letters = factor(df$letters, labels=c("d", "c", "b", "a"))
データポイントからラベルへのマッピングのみを変更し、データまたは因子スキーマ(データポイントを個々のビンにビン化する方法またはファクター値の場合、最初にファクターを作成するときにマッピングが元々どのように設定されているかを知ることが役立つ場合があります。
ルールは単純です:
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
の代わりにletters
とg
を使用して_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
_は実際にレベルと値の両方を変更する必要がありますか?うーん...私はこれを掘ります...
この質問が最後にアクティブだったので、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()
関数。
レベルがいくつかの特殊文字と一緒に数字を運ぶ文字列である可能性がある別のケースを追加したい:下の例のように
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
これが将来の読者にとって有用な情報とみなされることを願っています。
特定のデータフレームの因子を並べ替える私の機能は次のとおりです。
_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"))