[R] データフレームの因子データを一括で数値データに変換する

2016.09.21

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

CSVからロードされたデータフレーム内部の全ての要素が以下のような値をとる因子型だったとします。

  • 満足
  • やや満足
  • 普通
  • やや不満
  • 不満

このときにデータフレームの中身の因子型をつぎのような形で数値型に一括でマッピングしたい場合がありました。

  • 満足 → 5
  • やや満足 → 4
  • 普通 → 3
  • やや不満 → 2
  • 不満 → 1

今回の記事はそのメモ書きになります。

サンプルコード

as <- data.frame(q1 = c("満足", "やや満足", "普通", "不満", "不満", "やや不満"), q2 = c("普通", "満足", "不満", "普通", "やや満足", "普通"), stringsAsFactors=TRUE)
toPoint <- function(factors) { 
  mapping <- c("満足"=5, "やや満足"=4, "普通"=3, "やや不満"=2, "不満"=1)
  mapping[as.character(factors)]
}
ps <- data.frame(lapply(as, toPoint))

l1

因子型を要素としたデータフレームを読み込みます。stringsAsFactors引数ではTRUEを明示的に指定して文字列型が因子型としてインポートされるように指定します。デフォルトでは環境依存で因子型に変換されることもあれば、文字列としてそのまま扱われることもあるためです。

l2

因子型のベクトルを受け取って数値型へのマッピングを行う関数を宣言します

l3

文字列によって各数値にアクセスできるようにラベル付きのベクトルmappingを宣言します

l4

因子型を文字列型にするためにas.characterを用いて因子型のベクトルを文字列型のベクトルにします。その上で文字列型のベクトルをインデックスの列としてラベル付きベクトルにアクセスし、もともと因子型だった文字列に対応する数値をベクトルとして取得します。

l5

lapply関数は第一引数としてベクトルをとる使い方がありますが、実はデータフレームも第一引数にとれます。lapply関数は内部で第一引数の型のチェックを行い、ベクトル型ではないオブジェクト型に対してはas.list関数でカラムに対応したラベルのついたリスト型にマッピングされます。

as.list(as)
$q1
[1] 満足     やや満足 普通     不満     不満     やや不満
Levels: やや不満 やや満足 不満 普通 満足

$q2
[1] 普通     満足     不満     普通     やや満足 普通    
Levels: やや満足 不満 普通 満足

lapply関数はこのような内部の処理を経たあとに要素(ここではベクトル)の一つ一つに対して第二引数に渡した関数による処理を適用します。第二引数に渡した関数としてはここでは因子型のベクトルを引数にとり数値型のベクトルを返却する関数toPointを指定していたため、lapplyの最終的な返り値としては中身が数値型であるようなラベル付きのリストとなります。

その上でdata.frame関数でラベル付きのリストはデータフレーム型にマッピングされ、要素が数値型であるようなデータフレームが得られるというわけです。

備考

csvからロードする時に文字列型として以下のようにstringsAsFactors引数をFALSEに指定しておけばlapplyにわたす引数を文字列のベクトル型にできます。

as <- read.csv("filepath", stringsAsFactors = FALSE)
toPoint <- function(factor_strings) {
  mapping <- c("満足"=5, "やや満足"=4, "普通"=3, "やや不満"=2, "不満"=1)
  mapping[factor_strings]
}
ps <- <- data.frame(lapply(as, toPoint))

名前付きのベクトルを関数内部に用意してあげてそれを用いてlapply関数でデータフレーム内部の値を一括でマッピングできるというのが今回の記事の趣旨でした。

まとめ

データフレーム内部の値が決められた文字列や因子型しかとらず、それらを点数にマッピングするケースはアンケートや心理学データに対する分析等でよく見られます。簡潔な形式での変換の記述をlapplyに見られるapply系の関数ではサポートしているので積極的に活用していきたいところです。

参考