63

折りたたむ必要がある複数のレベルを含む因子をクリーンアップする最も効果的な (つまり、効率的/適切な) 方法は何ですか? つまり、2 つ以上の因子レベルを 1 つに結合する方法です。

以下は、2 つのレベル "Yes" と "Y" が "Yes" に折りたたまれ、"No" と "N" が "No" に折りたたまれる例です。

## Given: 
x <- c("Y", "Y", "Yes", "N", "No", "H")   # The 'H' should be treated as NA

## expectedOutput
[1] Yes  Yes  Yes  No   No   <NA>
Levels: Yes No  # <~~ NOTICE ONLY **TWO** LEVELS

1 つのオプションはもちろん、手で使用する前に弦をきれいにするsubことです。

別の方法は、重複したラベルを許可してからドロップすることです

## Duplicate levels ==> "Warning: deprecated"
x.f <- factor(x, levels=c("Y", "Yes", "No", "N"), labels=c("Yes", "Yes", "No", "No"))

## the above line can be wrapped in either of the next two lines
factor(x.f)      
droplevels(x.f) 

しかし、より効果的な方法はありますか?


levelsとの引数がベクトルであることはわかっていlabelsますが、リスト、名前付きリスト、名前付きベクトルを使って何が起こるかを実験しました。

  factor(x, levels=list(c("Yes", "Y"), c("No", "N")), labels=c("Yes", "No"))
  factor(x, levels=c("Yes", "No"), labels=list(c("Yes", "Y"), c("No", "N")))

  factor(x, levels=c("Y", "Yes", "No", "N"), labels=c(Y="Yes", Yes="Yes", No="No", N="No"))
  factor(x, levels=c("Y", "Yes", "No", "N"), labels=c(Yes="Y", Yes="Yes", No="No", No="N"))
  factor(x, levels=c("Yes", "No"), labels=c(Y="Yes", Yes="Yes", No="No", N="No"))
4

10 に答える 10

83

更新 2:これを行う新しい「tidyverse」方法を示す Uwe の回答を参照してください。これは急速に標準になりつつあります。

更新 1: 重複したラベル (レベルではありません!) が実際に許可されるようになりました (上記の私のコメントによると)。ティムの答えを見てください。

元の回答ですが、それでも有用で興味深いものlevelsです。まさにこの目的のために、名前付きリストを関数に渡すためのほとんど知られていないオプションがあります。リストの名前はレベルの目的の名前にする必要があり、要素は名前を変更する必要がある現在の名前にする必要があります。一部(OPを含む、ティムの回答に対するリカルドのコメントを参照)は、読みやすさのためにこれを好みます。

x <- c("Y", "Y", "Yes", "N", "No", "H", NA)
x <- factor(x)
levels(x) <- list("Yes"=c("Y", "Yes"), "No"=c("N", "No"))
x
## [1] Yes  Yes  Yes  No   No   <NA>  <NA>
## Levels: Yes No

ドキュメントに記載されているようにlevels; そこにある例も参照してください。

値: 'factor' メソッドの場合、長さが 'x' のレベル数以上の文字列のベクトル、またはレベルの名前を変更する方法を指定する名前付きリスト。

マレクがここで行うように、これは1行で行うこともできます: https://stackoverflow.com/a/10432263/210673 ; levels<-魔術はここで説明されていますhttps://stackoverflow.com/a/10491881/210673

> `levels<-`(factor(x), list(Yes=c("Y", "Yes"), No=c("N", "No")))
[1] Yes  Yes  Yes  No   No   <NA>
Levels: Yes No
于 2013-10-16T17:46:48.003 に答える
29

質問のタイトルがClean up factor levels (collapseing multiple levels/labels)forcatsであるため、完全を期すために、パッケージについてもここで言及する必要があります。forcats2016年8月にCRANに出演。

因子レベルのクリーンアップに使用できる便利な関数がいくつかあります。

x <- c("Y", "Y", "Yes", "N", "No", "H") 

library(forcats)

因子レベルを手動で定義したグループに折りたたむ

fct_collapse(x, Yes = c("Y", "Yes"), No = c("N", "No"), NULL = "H")
#[1] Yes  Yes  Yes  No   No   <NA>
#Levels: No Yes

要因レベルを手動で変更する

fct_recode(x, Yes = "Y", Yes = "Yes", No = "N", No = "No", NULL = "H")
#[1] Yes  Yes  Yes  No   No   <NA>
#Levels: No Yes

因子レベルを自動的に再ラベル付けし、必要に応じて折りたたむ

fun <- function(z) {
  z[z == "Y"] <- "Yes"
  z[z == "N"] <- "No"
  z[!(z %in% c("Yes", "No"))] <- NA
  z
}
fct_relabel(factor(x), fun)
#[1] Yes  Yes  Yes  No   No   <NA>
#Levels: No Yes

fct_relabel()因子レベルで機能するため、最初の引数として因子が必要であることに注意してください。他の 2 つの関数fct_collapse()とは、ドキュメント化されていない機能である文字ベクトルfct_recode()も受け入れます。

因子水準を初出順に並べ替える

OPによって与えられる期待される出力は

[1] Yes  Yes  Yes  No   No   <NA>
Levels: Yes No

ここではx、デフォルトとは異なるレベルが表示されるように並べられています ( ?factor:因子のレベルは、デフォルトでソートされます)。

期待される出力と一致させるために、これはレベルを折りたたむfct_inorder() 前に使用することで実現できます。

fct_collapse(fct_inorder(x), Yes = c("Y", "Yes"), No = c("N", "No"), NULL = "H")
fct_recode(fct_inorder(x), Yes = "Y", Yes = "Yes", No = "N", No = "No", NULL = "H")

どちらも同じ順序のレベルで期待される出力を返します。

于 2017-04-13T06:27:55.870 に答える
3

この回答を追加して、受け入れられた回答がデータフレームの特定の要素に作用することを示します。

levels(df$var1)
# "0" "1" "Z"
summary(df$var1)
#    0    1    Z 
# 7012 2507    8 
levels(df$var1) <- list("0"=c("Z", "0"), "1"=c("1"))
levels(df$var1)
# "0" "1"
summary(df$var1)
#    0    1 
# 7020 2507
于 2018-12-02T02:12:18.833 に答える
2

@Aaronのアプローチに似ていますが、少し単純です:

x <- c("Y", "Y", "Yes", "N", "No", "H")
x <- factor(x)
# levels(x)  
# [1] "H"   "N"   "No"  "Y"   "Yes"
# NB: the offending levels are 1, 2, & 4
levels(x)[c(1,2,4)] <- c(NA, "No", "Yes")
x
# [1] Yes  Yes  Yes  No   No   <NA>
# Levels: No Yes
于 2016-06-09T22:10:47.860 に答える