2013-12-17 14 views
36

さまざまな型の列を持つ(既存の)データフレームがある場合、他の型の列に影響を与えずにすべての文字列を要素に変換する最も簡単な方法は何ですか?もう少しこのプロセスを自動化する方法はありすべてのデータフレームの文字列をファクタに変換する

df$D <- as.factor(df$D) 
df$E <- as.factor(df$E) 

:私は私が行うことができます知っている

df <- data.frame(A = factor(LETTERS[1:5]), 
       B = 1:5, C = as.logical(c(1, 1, 0, 0, 1)), 
       D = letters[1:5], 
       E = paste(LETTERS[1:5], letters[1:5]), 
       stringsAsFactors = FALSE) 
df 
# A B  C D E 
# 1 A 1 TRUE a A a 
# 2 B 2 TRUE b B b 
# 3 C 3 FALSE c C c 
# 4 D 4 FALSE d D d 
# 5 E 5 TRUE e E e 
str(df) 
# 'data.frame': 5 obs. of 5 variables: 
# $ A: Factor w/ 5 levels "A","B","C","D",..: 1 2 3 4 5 
# $ B: int 1 2 3 4 5 
# $ C: logi TRUE TRUE FALSE FALSE TRUE 
# $ D: chr "a" "b" "c" "d" ... 
# $ E: chr "A a" "B b" "C c" "D d" ... 

はここで例data.frameですか?

+0

@AnandaMahtoありがとうございました。私は通常、要因への変換を避けようと努力しており、しばしばグローバルオプションを設定することを余儀なくされています。だから、このアイデアは私には簡単に来ました。 – Roland

答えて

45
DF <- data.frame(x=letters[1:5], y=1:5, stringsAsFactors=FALSE) 

str(DF) 
#'data.frame': 5 obs. of 2 variables: 
# $ x: chr "a" "b" "c" "d" ... 
# $ y: int 1 2 3 4 5 

as.data.frameの(迷惑な)デフォルトでは、因子の列にすべての文字列を有効にすることです。

DF <- as.data.frame(unclass(DF)) 
str(DF) 
#'data.frame': 5 obs. of 2 variables: 
# $ x: Factor w/ 5 levels "a","b","c","d",..: 1 2 3 4 5 
# $ y: int 1 2 3 4 5 
77

ローランドの答えはこの特定の問題には最適ですが、私はより一般化されたアプローチを共有すると思いました。変換のため

DF <- data.frame(x = letters[1:5], y = 1:5, z = LETTERS[1:5], 
       stringsAsFactors=FALSE) 
str(DF) 
# 'data.frame': 5 obs. of 3 variables: 
# $ x: chr "a" "b" "c" "d" ... 
# $ y: int 1 2 3 4 5 
# $ z: chr "A" "B" "C" "D" ... 

## The conversion 
DF[sapply(DF, is.character)] <- lapply(DF[sapply(DF, is.character)], 
             as.factor) 
str(DF) 
# 'data.frame': 5 obs. of 3 variables: 
# $ x: Factor w/ 5 levels "a","b","c","d",..: 1 2 3 4 5 
# $ y: int 1 2 3 4 5 
# $ z: Factor w/ 5 levels "A","B","C","D",..: 1 2 3 4 5 

割り当てる(DF[sapply(DF, is.character)])の左側には、文字である列をサブセット。右側では、そのサブセットでは、必要な変換を実行するためにlapplyを使用します。 Rは元の列を結果に置き換えるのに十分スマートです。

これは便利なことですが、別の方法や他のコンバージョンを実行したい場合は、左にあるものを変更し、右に変更したいものを指定するだけです。

+0

特に、文字ベクトルのみのデータフレームを与えるRMySQLリクエストの後に、非常に便利です。あらかじめ文字ではない列に、適切な型の数値論理などを設定することを(私のように)忘れないでください。 –

16

@Raf Zがこのquestionにコメントしたように、dplyrにmutate_ifが追加されました。非常に便利で、シンプルで読みやすい。

> str(df) 
'data.frame': 5 obs. of 5 variables: 
$ A: Factor w/ 5 levels "A","B","C","D",..: 1 2 3 4 5 
$ B: int 1 2 3 4 5 
$ C: logi TRUE TRUE FALSE FALSE TRUE 
$ D: chr "a" "b" "c" "d" ... 
$ E: chr "A a" "B b" "C c" "D d" ... 

> df <- df %>% mutate_if(is.character,as.factor) 

> str(df) 
'data.frame': 5 obs. of 5 variables: 
$ A: Factor w/ 5 levels "A","B","C","D",..: 1 2 3 4 5 
$ B: int 1 2 3 4 5 
$ C: logi TRUE TRUE FALSE FALSE TRUE 
$ D: Factor w/ 5 levels "a","b","c","d",..: 1 2 3 4 5 
$ E: Factor w/ 5 levels "A a","B b","C c",..: 1 2 3 4 5 
1

私は、単純なforループを行うために使用。 @ A5C1D2H2I1M1N2O1R2T1答えとして、lapplyは素晴らしい解決策です。しかし、すべての列を変換すると、前にdata.frameが必要になります。そうしないと、listになります。少しの実行時間の違い。

mm2N=mm2New[,10:18] 
str(mm2N) 
'data.frame': 35487 obs. of 9 variables: 
$ bb : int 4 6 2 3 3 2 5 2 1 2 ... 
$ vabb : int -3 -3 -2 -2 -3 -1 0 0 3 3 ... 
$ bb55 : int 7 6 3 4 4 4 9 2 5 4 ... 
$ vabb55: int -3 -1 0 -1 -2 -2 -3 0 -1 3 ... 
$ zr : num 0 -2 -1 1 -1 -1 -1 1 1 0 ... 
$ z55r : num -2 -2 0 1 -2 -2 -2 1 -1 1 ... 
$ fechar: num 0 -1 1 0 1 1 0 0 1 0 ... 
$ varr : num 3 3 1 1 1 1 4 1 1 3 ... 
$ minmax: int 3 0 4 6 6 6 0 6 6 1 ... 

# For solution 
t1=Sys.time() 
for(i in 1:ncol(mm2N)) mm2N[,i]=as.factor(mm2N[,i]) 
Sys.time()-t1 
Time difference of 0.2020121 secs 
str(mm2N) 
'data.frame': 35487 obs. of 9 variables: 
$ bb : Factor w/ 6 levels "1","2","3","4",..: 4 6 2 3 3 2 5 2 1 2 ... 
$ vabb : Factor w/ 7 levels "-3","-2","-1",..: 1 1 2 2 1 3 4 4 7 7 ... 
$ bb55 : Factor w/ 8 levels "2","3","4","5",..: 6 5 2 3 3 3 8 1 4 3 ... 
$ vabb55: Factor w/ 7 levels "-3","-2","-1",..: 1 3 4 3 2 2 1 4 3 7 ... 
$ zr : Factor w/ 5 levels "-2","-1","0",..: 3 1 2 4 2 2 2 4 4 3 ... 
$ z55r : Factor w/ 5 levels "-2","-1","0",..: 1 1 3 4 1 1 1 4 2 4 ... 
$ fechar: Factor w/ 3 levels "-1","0","1": 2 1 3 2 3 3 2 2 3 2 ... 
$ varr : Factor w/ 5 levels "1","2","3","4",..: 3 3 1 1 1 1 4 1 1 3 ... 
$ minmax: Factor w/ 7 levels "0","1","2","3",..: 4 1 5 7 7 7 1 7 7 2 ... 

#lapply solution 
mm2N=mm2New[,10:18] 
t1=Sys.time() 
mm2N <- lapply(mm2N, as.factor) 
Sys.time()-t1 
Time difference of 0.209012 secs 
str(mm2N) 
List of 9 
$ bb : Factor w/ 6 levels "1","2","3","4",..: 4 6 2 3 3 2 5 2 1 2 ... 
$ vabb : Factor w/ 7 levels "-3","-2","-1",..: 1 1 2 2 1 3 4 4 7 7 ... 
$ bb55 : Factor w/ 8 levels "2","3","4","5",..: 6 5 2 3 3 3 8 1 4 3 ... 
$ vabb55: Factor w/ 7 levels "-3","-2","-1",..: 1 3 4 3 2 2 1 4 3 7 ... 
$ zr : Factor w/ 5 levels "-2","-1","0",..: 3 1 2 4 2 2 2 4 4 3 ... 
$ z55r : Factor w/ 5 levels "-2","-1","0",..: 1 1 3 4 1 1 1 4 2 4 ... 
$ fechar: Factor w/ 3 levels "-1","0","1": 2 1 3 2 3 3 2 2 3 2 ... 
$ varr : Factor w/ 5 levels "1","2","3","4",..: 3 3 1 1 1 1 4 1 1 3 ... 
$ minmax: Factor w/ 7 levels "0","1","2","3",..: 4 1 5 7 7 7 1 7 7 2 ... 

#data.frame lapply solution 
mm2N=mm2New[,10:18] 
t1=Sys.time() 
mm2N <- data.frame(lapply(mm2N, as.factor)) 
Sys.time()-t1 
Time difference of 0.2010119 secs 
str(mm2N) 
'data.frame': 35487 obs. of 9 variables: 
$ bb : Factor w/ 6 levels "1","2","3","4",..: 4 6 2 3 3 2 5 2 1 2 ... 
$ vabb : Factor w/ 7 levels "-3","-2","-1",..: 1 1 2 2 1 3 4 4 7 7 ... 
$ bb55 : Factor w/ 8 levels "2","3","4","5",..: 6 5 2 3 3 3 8 1 4 3 ... 
$ vabb55: Factor w/ 7 levels "-3","-2","-1",..: 1 3 4 3 2 2 1 4 3 7 ... 
$ zr : Factor w/ 5 levels "-2","-1","0",..: 3 1 2 4 2 2 2 4 4 3 ... 
$ z55r : Factor w/ 5 levels "-2","-1","0",..: 1 1 3 4 1 1 1 4 2 4 ... 
$ fechar: Factor w/ 3 levels "-1","0","1": 2 1 3 2 3 3 2 2 3 2 ... 
$ varr : Factor w/ 5 levels "1","2","3","4",..: 3 3 1 1 1 1 4 1 1 3 ... 
$ minmax: Factor w/ 7 levels "0","1","2","3",..: 4 1 5 7 7 7 1 7 7 2 ... 
0

最も簡単な方法は、以下のコードを使用することです。これは、Rのデータフレームの要素としてすべての変数を変換するプロセス全体を自動化します。ここではfood_catは私が使用しているデータセットです。あなたが取り組んでいるものに変更してください。

for(i in 1:ncol(food_cat)){ 

food_cat[,i] <- as.factor(food_cat[,i]) 

} 
関連する問題