2011-06-18 11 views
3

サブセット化が行われたときに未使用の因子レベルを削除する問題before[.data.frameをオーバーライドして未使用の因子レベルを削除する

subsetDrop <- function(...){droplevels(subset(...))} 
:一般的な解決策は、私たちが subsetのラッパーを作成するために droplevelsのような便利な機能を使用することができ、その場合には、プロットのために必要であるしかし場合によっては、要因を命じ可能

options(stringsAsFactors = FALSE) 

を宣言することにより、文字ベクトルを使用することを含みます

私はsubsetDropがこの問題をほとんど解決することを認識していますが、[を介したサブセット化がより便利に(そしてタイピングが減ります)いくつかの状況があります。

私の質問は、便宜上、因子枠を自動的に落とすデータフレームのために[を無効にすることによって、これをRの「デフォルト」の振る舞いにすることができます。たとえば、HmiscパッケージにはdropUnusedLevelsが含まれており、単一の要素をサブセット化するために[.factorをオーバーライドします(デフォルトの[.factorには使用されていないレベルを削除するための引数がdropと表示されるため、不要です)。私は[を使用してデータフレームのサブセットを作成することができますが、未使用のファクタレベルを自動的に削除する同様のソリューションを探しています(もちろん、順序付けられたファクタの場合は順序を保持しています)。あなたはこのようにドロップ引数のデフォルト値を上書きすることでその作業を行うことができます

+0

プロットするために順序付けられた要素はほとんど必要ありません。レベルの順序を変更することは、しばしばプロットの難しさの中核です。順序付け係数は、因子レベルの順序を変更することとはまったく異なります。 –

答えて

6

デフォルトの動作を変更することには本当に注意が必要です。使用する別の関数が通常のデフォルト動作に依存するかどうかはわかりません。あなたが本当にデフォルトを変更したい場合は、私が代わりにあなたは

foo <- `[.data.frame` 
`[.data.frame` <- function(...) droplevels(foo(...)) 
ような何かを行うことができ、その後

sel <- function(x, ...) droplevels(x[...]) 

> d <- data.frame(a=factor(LETTERS[1:5]), b=factor(letters[1:5])) 
> str(d[1:2,]) 
'data.frame': 2 obs. of 2 variables: 
$ a: Factor w/ 5 levels "A","B","C","D",..: 1 2 
$ b: Factor w/ 5 levels "a","b","c","d",..: 1 2 
> str(sel(d,1:2,)) 
'data.frame': 2 obs. of 2 variables: 
$ a: Factor w/ 2 levels "A","B": 1 2 
$ b: Factor w/ 2 levels "a","b": 1 2 

のように、あなたのsubsetDropではなく[のための同様の機能を記述します。

しかし、グローバル名前空間から呼び出されたものであれば動作するが、ベース名前空間のバージョンは変更されないので、名前空間がどのように動作するかを必ず確認してください。それは良いことかもしれませんが、あなたが理解できるようにしたいものです。この変更後、出力は希望どおりです。

> str(d[1:2,]) 
'data.frame': 2 obs. of 2 variables: 
$ a: Factor w/ 2 levels "A","B": 1 2 
$ b: Factor w/ 2 levels "a","b": 1 2 
+0

ありがとうございました(また、@kohskeに+1しました)!サブセット()と同じトリックを本質的に使うべきだと考えていたはずです。そしてあなたは正しいです、紛争を避ける方がいいです... – joran

5

`[.data.frame` <- function(...)droplevels(base::`[.data.frame`(...)) 
:data.frame用として

formals(`[.factor`)$drop <- TRUE 

UPDATE

、次の方法で行うことができます

は実際に@Aaronのものと似ています。

あなたは、この動作を、中止する場合:

rm(`[.data.frame`) 

それを行います。

> d <- data.frame(a=letters[1:10], b=LETTERS[1:10]) 
> str(d[1:5, ]) 
'data.frame': 5 obs. of 2 variables: 
$ a: Factor w/ 10 levels "a","b","c","d",..: 1 2 3 4 5 
$ b: Factor w/ 10 levels "A","B","C","D",..: 1 2 3 4 5 
> `[.data.frame` <- function(...)droplevels(base::`[.data.frame`(...)) 
> str(d[1:5, ]) 
'data.frame': 5 obs. of 2 variables: 
$ a: Factor w/ 5 levels "a","b","c","d",..: 1 2 3 4 5 
$ b: Factor w/ 5 levels "A","B","C","D",..: 1 2 3 4 5 
> rm(`[.data.frame`) 
> str(d[1:5, ]) 
'data.frame': 5 obs. of 2 variables: 
$ a: Factor w/ 10 levels "a","b","c","d",..: 1 2 3 4 5 
$ b: Factor w/ 10 levels "A","B","C","D",..: 1 2 3 4 5 
+0

これは、単一因子ベクトルをサブセット化するためのデフォルトの動作を変更しますが、少なくとも私が試したときには、私が探している因子を含むデータフレームに '['を使用すると効果がありません。 – joran

2

私は私の応答hereを参照して、デフォルトを変更することは非常に危険だと思います。

人が因子レベルを落とすことに関心を持つほとんどのケースでは、あなたが本当に必要としない(1つの価値を持つことを余儀なくされたものを愚かにする)か、あなたが試みていることを達成するためのより良い方法があります。自動削除による副作用は、キーストロークの節約よりも悪い可能性があります。また、再現性のあるリサーチを行っている場合は、コンピュータに依存してはいけません。

関連する問題