数値(numeric型)を因子(factor型)として扱う時には注意を
前回、factor型(1)_Levels:・・・って?では
Levels: ○,○・・・ のように記載されているのはfactor型で、文字型のデータをデータフレームに引き渡すとfactor型として処理されることをとりあげました。たとえ中身が数値であっても文字列として引き渡すとfactor型になってしまうのでした。
a-habakiri.hateblo.jp
今回の内容は、例えば、c(2,3)という数値型をfactor型に変換した後、数値型に変換すると1,2になって元の値と変わってしまって困るなあというものです。
# Sample 1 vector→numeric nm<-c("2","3","4","5") as.numeric(nm) ##[1] 2 3 4 5
Sample 1 では、文字(character型)ベクトルを数値(numeric型)に戻しています。"2"→2と当たり前に変換されています。
数値(numeric型)を因子(factor型)に変換すると数値が変わってしまうように見える
次に、
# Sample 2 numeric→factor→numeric nm<-c(2,3,4,5) as.factor(nm) ##[1] 2 3 4 5 ##Levels: 2 3 4 5 as.numeric(as.factor(nm)) ##[1] 1 2 3 4
Sample 2 では、 数値(numeric型)ベクトルを因子(factor型)に変換した後、数値(numeric型)に戻しています。
2→"2"→1 となっていて、数値が変わっています。この後の処理に支障をきたすことが多いでしょう。
factorは元データをソートした結果を1から順に連番にして返す(デフォルト)
文字(character)型の体裁の数値をdata.frameに変換した時も数値が変わってしまうように見える
続いて二つのサンプルを比較してみます。
# Sample 3 numeric→data.frame(factor)→numeric nm<-c(2,3,4,5) df<-data.frame(nm) df$nm ##[1] 2 3 4 5 as.numeric(df$nm) ##[1] 2 3 4 5
Sample 3 では数値ベクトルをデータフレームに変換していますが、そのまま数値として元の値で処理されています。
# Sample 4 (numeric)character→data.frame(factor)→numeric nm<-c("2","3","4","5") df<-data.frame(nm) df$nm ##[1] 2 3 4 5 ##Levels: 2 3 4 5 as.numeric(df$nm) ##[1] 1 2 3 4
Sample 4 では数値を文字型ベクトルとしてデータフレームに変換していますが、factor型として処理され、数値はもとの値とは変わっています。
ファイル読み込みのときにも注意
データをファイルから読み込みデータフレームにする場合にも注意が必要です。
数値の列のはずが、文字列として扱われてしまうとfactor型に変換されてしまいます。
それはSample2,Sample4と同じことです。
factor型で数値が変わらないようにするための対策
対策1
数値をfactor型に変換すると、as.numericで数値に戻してももとに戻らないことがあります(Sample5)。
# Sample 5 nm<-c(2,3,4,5) as.factor(nm) ##[1] 2 3 4 5 ##Levels: 2 3 4 5 as.numeric(as.factor(nm)) ##[1] 1 2 3 4 # Sample 6 counterplan as.character(as.factor(nm)) ##[1] "2" "3" "4" "5" as.numeric(as.character(as.factor(nm))) ##[1] 2 3 4 5
対策としては、Sample6のようにas.numeric(as.character())で一旦文字型に変換した後、数値型に戻すのが簡単かと思います。
対策2
ファイルからの読み込みの際に勝手にfactor型に変換されて困るのであれば、read.csv() などで stringsAsFactors=FALSE を指定すれば問題が解消するでしょう。
read.table(...,stringsAsFactors=FALSE) read.csv(...,stringsAsFactors=FALSE)