makedummies
パッケージの概要
makedummiesパッケージは、データフレームのfactor型変数(カテゴリ変数)をダミー変数化する関数を提供します。 簡単な指定で一度に複数の列を加工することが出来る点が特徴です。
準備
パッケージの読み込み
library(makedummies)
library(carData) #データセットデータセットの読み込み
John Fox and Sanford Weisberg (2018) で使用されたデータセット等をまとめたパッケージcarDataに含まれる、 WVSというデータセットを使用します。
1995~1997年にオーストラリア、ノルウェー、スウェーデン、アメリカにて実施されたアンケート調査で、 貧困層への政策に対する評価と、年齢、性別などの回答者の属性からなる6つの列で構成されたデータセットです。 サンプル数は5,381件です。
data("WVS")
df_all <- WVS
str(df_all)'data.frame': 5381 obs. of 6 variables:
$ poverty : Ord.factor w/ 3 levels "Too Little"<"About Right"<..: 1 2 1 3 1 2 3 1 1 1 ...
$ religion: Factor w/ 2 levels "no","yes": 2 2 2 2 2 2 2 2 2 2 ...
$ degree : Factor w/ 2 levels "no","yes": 1 1 1 2 2 1 1 1 1 1 ...
$ country : Factor w/ 4 levels "Australia","Norway",..: 4 4 4 4 4 4 4 4 4 4 ...
$ age : int 44 40 36 25 39 80 48 32 74 30 ...
$ gender : Factor w/ 2 levels "female","male": 2 1 1 1 2 1 1 2 1 2 ...
各列の内容は次のとおりで、age以外はfactor型変数(カテゴリ変数)であることがわかります。
| 列名 | 型 | 説明 |
|---|---|---|
| poverty | 順序付きfactor型 | この国の政府が貧困層に対して行っていることは、適切だと思うか、多すぎるか、少なすぎるか?という問いへの答え : Too Little < About Right < Too Much の3通り |
| religion | factor型 | 宗教の信者かどうか : no または yes |
| degree | factor型 | 大学の学位を取得しているかどうか : no または yes |
| country | factor型 | 国 : Austraila, Norway, Sweden, USA の4通り |
| age | 整数型 | 年齢(歳) |
| gender | factor型 | 性別 : male または female |
冒頭6行のレコード、およびサマリーを確認すると次のとおり。
head(df_all)summary(df_all) poverty religion degree country age
Too Little :2708 no : 786 no :4238 Australia:1874 Min. :18.00
About Right:1862 yes:4595 yes:1143 Norway :1127 1st Qu.:31.00
Too Much : 811 Sweden :1003 Median :43.00
USA :1377 Mean :45.04
3rd Qu.:58.00
Max. :92.00
gender
female:2725
male :2656
データセットのさらなる詳細については ?WVS を実行することで確認できます。
使用方法
基本的な使用方法
makedummies関数により、すべてのfactor型変数(順序付きを含む)をダミー変数に変換することが出来ます。
df_all_dummy <- makedummies(df_all)
head(df_all_dummy)factor型変数だった列が、(カテゴリの数 - 1)個の列に変換されています。
基準となるカテゴリ(例えば、poverty列なら"Too Little"、religion列なら"no")に対応する列は作られず、 それ以外のカテゴリに対して、「対応するカテゴリに所属しているなら1」というダミー変数が生成されています。
カテゴリが3個以上ある場合、列名が「元の列名_カテゴリ名」のように加工されます。 一方、カテゴリが2個しかない場合は、元の列名のままとなっています。
factor型ではない列(age)はそのまま残されていることがわかります。
引数 basal_level: 基準カテゴリに対応する列を作る
引数 basal_level に TRUE を与えることで、基準となるカテゴリに対応する列も作られるようになります。 なお、このような変換をワンホットエンコーディングといいます。
df_all_dummy <- makedummies(df_all, basal_level = TRUE)
head(df_all_dummy)引数 col: 特定の列のみ出力する
引数 col に列名を与えることで、その列の処理結果だけが出力されるようになります。
df_all_dummy <- makedummies(df_all, col = "poverty")
head(df_all_dummy) poverty_About Right poverty_Too Much
1 0 0
2 1 0
3 0 0
4 0 1
5 0 0
6 1 0
次のように、複数の列を出力対象にすることもできます。また、数値型のような処理されない列を含めることも可能です。
df_all_dummy <- makedummies(df_all, col = c("poverty", "age", "gender"))
head(df_all_dummy)引数 numerical: ダミー変数化ではなく単純に整数に変換する列を指定
引数 numerical に列名を与えることで、その列は単純に1, 2, 3, …とカテゴリ別の整数に変換するように変更できます。
df_all_dummy <- makedummies(df_all, numerical = c("poverty", "gender"))
head(df_all_dummy)引数 as.is: 変換しない列を指定
引数 as.is に列名を与えることで、その列は処理の対象から除外されます。
df_all_dummy <- makedummies(df_all, as.is = c("poverty", "country"))
head(df_all_dummy)補足
存在しないカテゴリに対する動作
factor型の定義にはあるものの、実際には存在しないカテゴリについては、ダミー変数化の対象から除かれます。
たとえば上から3行のみを抽出したとします。
df_minimum <- df_all[1:3,c("poverty", "gender")]
df_minimumpoverty列には"Too Much"のカテゴリとなるデータがありません。
summary(df_minimum) poverty gender
Too Little :2 female:2
About Right:1 male :1
Too Much :0
この場合、makedummies関数による処理では"Too Much"に対応するダミー変数は作られません。
makedummies(df_minimum) poverty gender
1 0 1
2 1 0
3 0 0
なお、単一のカテゴリしかない列が存在するとエラーとなります。 このような列はモデル構築においても悪影響を及ぼしうるため、前処理の中で別途取り除いておくことが考えられます。
df_minimum <- df_all[1:3,c("country", "gender")]
summary(df_minimum) #countryはUSAのみ country gender
Australia:0 female:2
Norway :0 male :1
Sweden :0
USA :3
makedummies(df_minimum) #res[cbind(seq.int(m), dat)] <- 1L でエラー: 添え字が許される範囲外ですError in res[cbind(seq.int(m), dat)] <- 1L: subscript out of bounds
NA値に対する動作
NA値(欠損値)が含まれている場合、ダミー変数化後もNA値のままとなります。
#NAの混ざったデータを生成
N <- 6
df_NA <- df_all[1:N, c("poverty","gender")]
set.seed(2024)
df_NA <- data.frame(lapply(df_NA, function(x) {
x[[floor(runif(1, min=1, max=N+1))]] <- NA
x
}))
df_NAmakedummies(df_NA) poverty_About Right poverty_Too Much gender
1 0 0 1
2 1 0 NA
3 0 0 0
4 0 1 0
5 0 0 1
6 NA NA 0
factor型以外の取り扱い
本パッケージはfactor型以外の列の加工には対応していません。
実質的にはカテゴリ変数であるものの、数値や文字列として格納されている場合には、factor型に変換してからmakedummies関数を使用します。
例えば性別が文字列で、学歴が数値で格納されているとしましょう。当然これらはfactor型ではないので、makedummies関数では加工できません。
df_tmp <- data.frame("性別" = c("女", "男", "女", "男"), "学歴" = c(1, 1, 3, 2))
df_tmp 性別 学歴
1 女 1
2 男 1
3 女 3
4 男 2
makedummies(df_tmp) 性別 学歴
1 女 1
2 男 1
3 女 3
4 男 2
以下のように、factor関数等を用いてfactor型に変換する必要があります。
df_tmp$性別 <- factor(df_tmp$性別, levels = c("男", "女"))
df_tmp$学歴 <- factor(df_tmp$学歴, levels = c(1, 2, 3), labels = c("高卒", "大卒", "大学院卒"), ordered = TRUE)
str(df_tmp)'data.frame': 4 obs. of 2 variables:
$ 性別: Factor w/ 2 levels "男","女": 2 1 2 1
$ 学歴: Ord.factor w/ 3 levels "高卒"<"大卒"<..: 1 1 3 2
makedummies(df_tmp) 性別 学歴_大卒 学歴_大学院卒
1 1 0 0
2 0 0 0
3 1 0 1
4 0 1 0
基準カテゴリの変更
本パッケージでは基準カテゴリを指定する機能は無いため、事前にrelevel関数などで変更しておく必要があります。
df_tmp <- df_all
df_tmp$country <- relevel(df_tmp$country, "USA")#アメリカを基準カテゴリに変更
head(makedummies(df_tmp))reorder関数で数が多いカテゴリを基準カテゴリにするなど、機械的に基準カテゴリを変更しておくことも考えられます。
df_tmp <- df_all
table(df_tmp$country) #カテゴリごとの件数を表示
Australia Norway Sweden USA
1874 1127 1003 1377
df_tmp$country <- reorder(df_tmp$country, df_tmp$country, length, decreasing = TRUE) #件数が多い順にカテゴリを並べ替える
head(makedummies(df_tmp)) #最も件数が多かったAustraliaが基準カテゴリになっている順序付きfactor型
順序付きfactor型とはカテゴリ変数を取り扱うfactor型の中でも特殊なもので、 カテゴリ間に大小関係のような順序関係があること(質的変数のなかでも順序尺度であること)を表しています。
class関数で型を確認してみるとorderedという型が付与されており、順序付きでないfactor型とは区別されていることがわかります。
lapply(df_all, class)$poverty
[1] "ordered" "factor"
$religion
[1] "factor"
$degree
[1] "factor"
$country
[1] "factor"
$age
[1] "integer"
$gender
[1] "factor"
順序付きfactor型変数は、factor関数で引数orderedにTRUEを与える(またはordered関数を使用する)ことで生成することができます。
df_tmp <- factor(c(4,2,4,2,3,2,3), levels = c(1,2,3,4),
labels = c("まったくそう思わない", "あまりそう思わない", "ややそう思う", "とてもそう思う"),
ordered = TRUE)
df_tmp[1] とてもそう思う あまりそう思わない とてもそう思う あまりそう思わない
[5] ややそう思う あまりそう思わない ややそう思う
4 Levels: まったくそう思わない < あまりそう思わない < ... < とてもそう思う
class(df_tmp)[1] "ordered" "factor"
tibbleに対する動作
data.frame型を拡張したものにtibbleがありますが、makedummies関数がtibbleを加工した場合はtibbleのまま返します。
data.frame型を加工すると当然data.frame型のままです1が…
class(df_all)[1] "data.frame"
class(makedummies(df_all))[1] "data.frame"
tibbleを加工したものはtibbleになります。
library(tibble)
df_all_tb <- as_tibble(df_all)
class(df_all_tb)[1] "tbl_df" "tbl" "data.frame"
class(makedummies(df_all_tb))[1] "tbl_df" "tbl" "data.frame"
なお、tibbleはtidyverseに含まれるもののうちの一つで、 例えば以下のような記法で列を選択した時にベクトルにならない(データフレームのままである)等の点で R標準のdata.frameとは違いがあります。
tibbleを用いている場合、加工後にtibbleとしての機能が失われないことは利便性の観点で重要です。
head(df_all[,"poverty"])[1] Too Little About Right Too Little Too Much Too Little About Right
Levels: Too Little < About Right < Too Much
head(df_all_tb[,"poverty"])他の関数・パッケージとの比較
model.matrix関数
数値型への変換にあたってはR標準のmodel.matrix関数が使われることがあります。
こちらは予測モデルに入力する計画行列を生成するための関数で、交互作用項の追加等、ダミー変数化以外の機能もあります。
出力は行列(matrix型)となるため注意してください。
head(model.matrix(~ . , data = df_all)) #切片項が生成される 順序付きfactor型に対しては多項式対比を使用 (Intercept) poverty.L poverty.Q religionyes degreeyes countryNorway
1 1 -7.071068e-01 0.4082483 1 0 0
2 1 -7.850462e-17 -0.8164966 1 0 0
3 1 -7.071068e-01 0.4082483 1 0 0
4 1 7.071068e-01 0.4082483 1 1 0
5 1 -7.071068e-01 0.4082483 1 1 0
6 1 -7.850462e-17 -0.8164966 1 0 0
countrySweden countryUSA age gendermale
1 0 1 44 1
2 0 1 40 0
3 0 1 36 0
4 0 1 25 0
5 0 1 39 1
6 0 1 80 0
head(model.matrix(~ . +0, data = df_all)) #切片項が生成されない povertyToo Little povertyAbout Right povertyToo Much religionyes degreeyes
1 1 0 0 1 0
2 0 1 0 1 0
3 1 0 0 1 0
4 0 0 1 1 1
5 1 0 0 1 1
6 0 1 0 1 0
countryNorway countrySweden countryUSA age gendermale
1 0 0 1 44 1
2 0 0 1 40 0
3 0 0 1 36 0
4 0 0 1 25 0
5 0 0 1 39 1
6 0 0 1 80 0
fastDummiesパッケージ
本パッケージと非常に類似するパッケージとしてfastDummiesパッケージがあります。 名前のとおり、model.matrix関数よりも処理が高速だとされています。
dummy_cols関数によりダミー変数化が可能です。 ただし、makedummies関数とはデフォルトの処理が若干異なっています。 たとえば順序付きfactor型は処理対象としないほか、ダミー変数化前の変数が残る、 基準カテゴリに対応するダミー変数も作成する、といった点が異なります。
library(fastDummies)Warning: package 'fastDummies' was built under R version 4.5.1
head(dummy_cols(df_all))引数により処理をカスタマイズすることができます。
例えば引数select_columnsにより処理対象の列を指定することが出来ます。 ここでは順序付きfactor型だけでなく、数値型をも処理の対象とすることが出来ます。
head(dummy_cols(df_all,
#処理対象列の指定
select_columns = c("poverty","religion","degree","county"),
#元の列を残さない
remove_selected_columns = TRUE,
#基準カテゴリに対応するダミー変数を作らない
remove_first_dummy = TRUE
))Warning in dummy_cols(df_all, select_columns = c("poverty", "religion", : NOTE: The following select_columns input(s) is not a column in data.
なお、NA値に対してはデフォルトで個別のダミー変数を作成する挙動となっていますが、 引数ignore_naでこれを制御することが出来ます。
head(dummy_cols(df_NA, remove_selected_columns = TRUE, ignore_na = FALSE))head(dummy_cols(df_NA, remove_selected_columns = TRUE, ignore_na = TRUE))その他、最も大きなカテゴリを基準カテゴリとする引数remove_most_frequent_dummy、 複数のカテゴリ名が単一の文字列に含まれる際の処理を行う引数split、 元の列名をダミー変数に引き継がない引数omit_colname_prefixといった機能があります。
また、factor型の列に関してすべてのカテゴリ(の組み合わせ)が現れるように行を補完するdummy_rows関数も提供されます。
onehotパッケージ
onehotパッケージはシンプルにワンホットエンコーディングを行う機能だけを提供するものです。
まずonehot関数によりエンコーダーを生成し、predict関数により実際にデータを変換します。
出力は行列(matrix型)となるため注意してください。
library(onehot)
df_tmp <- df_all
#順序付きfactor型があるとエラーとなるため普通のfactor型に変換
df_tmp$poverty <- factor(df_tmp$poverty, ordered = FALSE)
#ここでのdf_tmpはデータの形式を指定するためのもので、実際に変換したいデータと同一データである必要はない
encoder <- onehot(df_tmp)
head(predict(encoder, df_tmp)) poverty=Too Little poverty=About Right poverty=Too Much religion=no
[1,] 1 0 0 0
[2,] 0 1 0 0
[3,] 1 0 0 0
[4,] 0 0 1 0
[5,] 1 0 0 0
[6,] 0 1 0 0
religion=yes degree=no degree=yes country=Australia country=Norway
[1,] 1 1 0 0 0
[2,] 1 1 0 0 0
[3,] 1 1 0 0 0
[4,] 1 0 1 0 0
[5,] 1 0 1 0 0
[6,] 1 1 0 0 0
country=Sweden country=USA age gender=female gender=male
[1,] 0 1 44 0 1
[2,] 0 1 40 1 0
[3,] 0 1 36 1 0
[4,] 0 1 25 1 0
[5,] 0 1 39 0 1
[6,] 0 1 80 1 0
recipesパッケージ
recipesパッケージはtidymodelsに含まれ、ダミー変数化を含む様々な前処理機能を提供するパッケージです。
前処理手順のオブジェクト化などtidyな(整然とした)コーディングが可能になるほか、 他のtidymodelsのパッケージとの連携も特徴です。 本パッケージはダミー変数化のためだけに導入するようなものではありませんが、 そのようなコーディングを指向する場合にはこちらを用いるべきかもしれません。
ダミー変数化を行う機能を提供するのはstep_dummy関数で、例えば次のように使用します。 なお、順序付きfactor型変数に対しては多項式対比を用いた変換が行われます。
library(recipes)
rec <- recipe(df_all, formula = ) %>%
step_dummy(all_factor(), all_ordered())
rec %>% prep() %>% bake(new_data = NULL) %>% head()その他のパッケージ
caretパッケージのdummyVars関数、mltoolsパッケージのone_hot関数でも同様の処理は可能です。 これらのパッケージを利用している場合は、それらの関数を用いてもよいでしょう。 ただし、これらはより広範な機能を提供するパッケージのため、ダミー変数化のためだけに導入するようなものではありません。
参考文献
意図された動作かは不明なものの、すべての列が変換対象となったときは行列(matrix型)になります。↩︎