2017-08-16 16 views
0

データフレームにいくつか結果があります。私はいくつかの因子列と多くの数値列を持っています。 this質問への回答ごとに、数値列を数値に変換して簡単に索引付けすることができます。データフレームの列をインデックス付き因数に変換する

#create example data 
df = data.frame(replicate(1000,sample(1:10,1000,rep=TRUE))) 
df$X1 = LETTERS[df$X1] 
df$X2 = LETTERS[df$X2] 
df$X3 = LETTERS[df$X3] 
df[-1] <- sapply(df[-1], function(x) ifelse(runif(length(x)) < 0.1, NA, x)) 

#find columns that are factors 
factornames = c("X1", "X2", "X3") 
factorfilt = names(df) %in% factornames 

#convert non-factor columns to numeric 
df[, !factorfilt] = as.numeric(as.character(unlist(df[, !factorfilt]))) 

しかし、私は私の因子の列に同じことをやりたいとき、私は同じインデックスが仕事を得るカント:

#convert factor columns to factor 
df[, factorfilt] = as.factor(as.character(unlist(df[, factorfilt]))) 
class(df$X1) 

[1] "character" 

df[, factorfilt] = as.factor(as.character(df[, factorfilt])) 
class(df$X1) 

[1] "character" 

df[, factorfilt] = as.factor(unlist(df[, factorfilt])) 
class(df$X1) 

[1] "character" 

df[, factorfilt] = as.factor(df[, factorfilt]) 

Error in sort.list(y) : 'x' must be atomic for 'sort.list' 
Have you called 'sort' on a list? 

これらの戻り"character"のすべて私が実行している場合は一方で、私は、class(df$X1)を呼び出す場合df$X1= as.factor(df$X1)これは"factor"を返します。

as.factorを呼び出すと、このようなインデックス作成が機能しないのはなぜですか。as.numericに電話をかけた場合はどうなりますか?

+2

'as.factor'や' as.character'などは 'vector'では動作し、' data.frame'では動作しません。あなたは列をループしてから 'factor'を実行する必要があります – akrun

+0

なぜ' unlist'がそこにあるのですか? – Leo

+1

akrunのコメントに続いて、 'lapply'を使って選択したカラムを実行し、強制を実行します:' df [、factorfilt] < - lapply(df [、factorfilt]、as.factor) '。 – lmo

答えて

2

あなたがしていることのいくつかの行動面を観察する必要があります。あなたが行ったように、あなたのデータの定義:

df = data.frame(replicate(1000,sample(1:10,1000,rep=TRUE))) 
df$X1 = LETTERS[df$X1] 
df$X2 = LETTERS[df$X2] 
df$X3 = LETTERS[df$X3] 
df[-1] <- sapply(df[-1], function(x) ifelse(runif(length(x)) < 0.1, NA, x)) 

factornames = c("X1", "X2", "X3") 
factorfilt = names(df) %in% factornames 
df[, !factorfilt] = as.numeric(as.character(unlist(df[, !factorfilt]))) 

は、今のあなたがやったようX1X2、およびX3要因を作るの結果を見てみましょう、しかし、のはまだそれを再割り当てしないようにしましょう。

test <- as.factor(as.character(df[, factorfilt])) 
class(test) # "factor" 
length(test) # 3 

ここで注目すべき重要なことは、testがデータフレームではないということです。これはベクトルで、データフレームの3列に保存しようとしています。私はデータフレームをベクトルに変換してデータフレームに格納するという知恵に疑問を投げかけなければならないと思います。

は、次に2番目の割り当てを検討:

test2 <- as.factor(as.character(unlist(df[, factorfilt]))) 
class(test2) # factor 
length(test2) # 3000 

は再び、それが要因だが、それはtestよりも完全に異なる長さを有しています。 Rはこれをdfに再割り当てさせることで親切です。次元を調整できることを認識しているため、Rは親切です。しかし、要因をX1X2、およびX3にプッシュしようとすると、要因レベルとは何かに関する大きな質問があります。 3つの変数はすべて同じレベルでなければなりませんか?各変数は自分自身内に存在するレベルしか持たないのでしょうか? 「適切な」選択肢が何であるかを宣言しようとするのではなく、Rはそれを無視して、あなた自身で対処するための文字に変換し直します。

このように列を操作すると、予期せずクラスを変更する可能性があるという事実は、それを行わないのがよい理由です。これはNAの割り当てに明白です。さんが再訪してみましょう:

df = data.frame(replicate(1000,sample(1:10,1000,rep=TRUE))) 
df$X1 = LETTERS[df$X1] 
df$X2 = LETTERS[df$X2] 
df$X3 = LETTERS[df$X3] 

この時点で、X1000通じX4はすべてintegerクラスの列です。あなたは

df[-1] <- sapply(df[-1], function(x) ifelse(runif(length(x)) < 0.1, NA, x)) 

を実行すると、彼らはすべての今character秒であり、あなたはnumericに変換するために進んでください。彼らはもはや元のクラスではない。

があれば、代わりに、我々は、元のクラスが保存されているlapply

df[-1] <- lapply(df[-1], function(x) ifelse(runif(length(x)) < 0.1, NA, x)) 

を使用して数値クラスに戻ってそれらを変換する必要はありません。同様に、我々は容易に一般的なルールとして

df[, factorfilt] <- lapply(df[, factorfilt], as.factor) 

と要因X3介しX1に変換することができ、別個の列と列のデータを操作する方がよいです。複数の列に1つのベクトルを割り当て始めると、いたずらの暗い世界に入ります。

+0

うーん、私はこれらのことを全く知らなかった。 'sapply'と' lapply'について読むと、彼らは同じですが? – Leo

+2

彼らが返すものには違いがあります。 'sapply'はベクトルまたは行列のいずれかを返します(この特定のケースでは、本当に長いベクトルだと思います)。 'lapply'はリストを返します。これにより、データフレームのカラムが適切に分割された状態に保たれます。 – Benjamin

関連する問題