as.data.frame()
でもstringsAsFactors
の引数が使えること今更ながら知りまして、これを機にちょっとまとめてみました。
場面別にまとめました
データフレーム生成時
「引数にstringsAsFactors = F
を指定する」で解決します。
ファイルから読み込み時
下記データをただ読み込みと、3列目がfactor化してしまいます。
yes | no | churn |
---|---|---|
0.13717622958469677 | 0.8628237704153032 | no |
0.053731282512169964 | 0.94626871748783 | no |
0.12273577469177754 | 0.8772642253082225 | no |
0.1780542822350093 | 0.8219457177649907 | yes |
0.028350089708717996 | 0.971649910291282 | no |
> data.factor <- read.delim("pred.txt", header = T, sep = "\t", quote = "")
> str(data.factor)
# 'data.frame': 3326 obs. of 3 variables:
# $ yes : num 0.1372 0.0537 0.1227 0.1781 0.0284 ...
# $ no : num 0.863 0.946 0.877 0.822 0.972 ...
# $ churn: Factor w/ 2 levels "no","yes": 1 1 1 2 1 1 1 1 2 1 ...
引数にstringsAsFactors = F
を指定して、因子型化を防ぎます。
> data.nofactor <- read.delim("pred.txt", header = T, sep = "\t", quote = "", stringsAsFactors = F)
> str(data.nofactor)
# 'data.frame': 3326 obs. of 3 variables:
# $ yes : num 0.1372 0.0537 0.1227 0.1781 0.0284 ...
# $ no : num 0.863 0.946 0.877 0.822 0.972 ...
# $ churn : chr "no" "no" "no" "yes" ...
ちなみに、readr::read_delim()
等なら、読み込み時の型を指定できます。
ただ、データフレームではなくtibbleになります。
> tibble.data <- readr::read_delim("pred.txt", delim = "\t", quote = "", col_names = T, col_types = "nnc")
> str(tibble.data)
# Classes ‘spec_tbl_df’, ‘tbl_df’, ‘tbl’ and 'data.frame': 3326 obs. of 3 variables:
# $ yes : num 0.1372 0.0537 0.1227 0.1781 0.0284 ...
# $ no : num 0.863 0.946 0.877 0.822 0.972 ...
# $ churn : chr "no" "no" "no" "yes" ...
# - attr(*, "spec")=
# .. cols(
# .. yes = col_number(),
# .. no = col_number(),
# .. churn = col_character(),
# .. )
別のベクトルから生成するとき
同様に、引数にstringsAsFactors = F
を指定して、因子型化を防ぎます。
> data.factor <- data.frame(a = c(1,2,3), b = c(0.1,0.2,0.3), c = c("one","two","three"))
> str(data.factor)
# 'data.frame': 3 obs. of 3 variables:
# $ a: num 1 2 3
# $ b: num 0.1 0.2 0.3
# $ c: Factor w/ 3 levels "one","three",..: 1 3 2
> data.nofactor <- data.frame(a = c(1,2,3), b = c(0.1,0.2,0.3), c = c("one","two","three"), stringsAsFactors = F)
> str(data.nofactor)
# 'data.frame': 3 obs. of 3 variables:
# $ a: num 1 2 3
# $ b: num 0.1 0.2 0.3
# $ c: chr "one" "two" "three"
as.data.frame()
as.data.frame()
でデータフレームに変換するときでも、stringsAsFactors = F
です。
apply系でmatrixを出力した後にまたデータフレームに戻すときなどで使えるかと思います。
> data.matrix <- matrix(c("1","2","3","0.1","0.2","0.3","one","two","three"), 3, 3)
> data.matrix
# [,1] [,2] [,3]
# [1,] "1" "0.1" "one"
# [2,] "2" "0.2" "two"
# [3,] "3" "0.3" "three"
> data.factor <- as.data.frame(data.matrix)
> str(data.factor)
# 'data.frame': 3 obs. of 3 variables:
# $ V1: Factor w/ 3 levels "1","2","3": 1 2 3
# $ V2: Factor w/ 3 levels "0.1","0.2","0.3": 1 2 3
# $ V3: Factor w/ 3 levels "one","three",..: 1 3 2
> data.nofactor <- as.data.frame(data.matrix, stringsAsFactors = F)
> str(data.nofactor)
# 'data.frame': 3 obs. of 3 variables:
# $ V1: chr "1" "2" "3"
# $ V2: chr "0.1" "0.2" "0.3"
# $ V3: chr "one" "two" "three"
カラムごとに変換
データフレーム生成後でも、factor型→charactor型に変換可能です。
as.character()
> str(data.factor)
# 'data.frame': 3326 obs. of 3 variables:
# $ yes : num 0.1372 0.0537 0.1227 0.1781 0.0284 ...
# $ no : num 0.863 0.946 0.877 0.822 0.972 ...
# $ churn: Factor w/ 2 levels "no","yes": 1 1 1 2 1 1 1 1 2 1 ...
> data.nofactor <- data.factor
> data.nofactor$churn <- as.character(data.nofactor$churn)
> str(data.nofactor)
# 'data.frame': 3326 obs. of 3 variables:
# $ yes : num 0.1372 0.0537 0.1227 0.1781 0.0284 ...
# $ no : num 0.863 0.946 0.877 0.822 0.972 ...
# $ churn : chr "no" "no" "no" "yes" ...
levels()
"no"と"yes"の二つの因子としてラベル付けされているので、そのラベル名を返す処理を使えば、文字列型に変換できます。
> str(data.factor)
# 'data.frame': 3326 obs. of 3 variables:
# $ yes : num 0.1372 0.0537 0.1227 0.1781 0.0284 ...
# $ no : num 0.863 0.946 0.877 0.822 0.972 ...
# $ churn: Factor w/ 2 levels "no","yes": 1 1 1 2 1 1 1 1 2 1 ...
> levels(data.factor$churn) # levels()の挙動確認
# [1] "no" "yes"
> head(levels(data.factor$churn)[data.factor$churn], 5) # levels()の挙動確認
# [1] "no" "no" "no" "yes" "no"
> data.nofactor <- data.factor
> data.nofactor$churn <- levels(data.nofactor$churn)[data.nofactor$churn]
> str(data.nofactor)
# 'data.frame': 3326 obs. of 3 variables:
# $ yes : num 0.1372 0.0537 0.1227 0.1781 0.0284 ...
# $ no : num 0.863 0.946 0.877 0.822 0.972 ...
# $ churn : chr "no" "no" "no" "yes" ...
transform()
引数を増やしていけば、複数カラムの文字列型への変換が一行で書けます。
カラム名だけで書けるのでややすっきりします。
> str(data.factor)
# 'data.frame': 3326 obs. of 3 variables:
# $ yes : num 0.1372 0.0537 0.1227 0.1781 0.0284 ...
# $ no : num 0.863 0.946 0.877 0.822 0.972 ...
# $ churn: Factor w/ 2 levels "no","yes": 1 1 1 2 1 1 1 1 2 1 ...
> data.nofactor <- transform(data.factor, churn = levels(churn)[churn])
> str(data.nofactor)
# 'data.frame': 3326 obs. of 3 variables:
# $ yes : num 0.1372 0.0537 0.1227 0.1781 0.0284 ...
# $ no : num 0.863 0.946 0.877 0.822 0.972 ...
# $ churn : chr "no" "no" "no" "yes" ...
おわり
(こんなこと書くと元も子もないですが)as.data.frame()
で非因子化の引数が使えることを知ったのは、公式のドキュメンテーションでした。
公式を参照するのは大事だなと思いつつ、小さなソリューションが見つかりやすくなればと思い、この記事を書いた次第です。