library("tidyr")
library("dplyr")
library("pipeR")

とあるホクソエムさんが悩んでおりました。

tidyrでダミー変数を作成する(赤ペン先生希望) - My Life as a Mock Quant

少ない脳みそを使ってちょっと考えてみました。

df <- data.frame(id = 1:10, 
                 feature = c(1, NaN, 2, 2, 2, NaN, NaN, 3, 3, 1))
df
##    id feature
## 1   1       1
## 2   2     NaN
## 3   3       2
## 4   4       2
## 5   5       2
## 6   6     NaN
## 7   7     NaN
## 8   8       3
## 9   9       3
## 10 10       1

元ブログでNA (欠損値)を与えているところをNaN (非数)にします。その理由は下で書きます(犯人はヤス)。あとの処理はおんなじ。selectのところだけNaNに変更。

df %>>% spread(key   = feature, 
              value  = feature,
              fill   = 0) %>>% 
  select(-contains("NaN")) %>>% 
  mutate_each(funs(ifelse(. >= 1, 1, 0)), -id)
##    id 1 2 3
## 1   1 1 0 0
## 2   2 0 0 0
## 3   3 0 1 0
## 4   4 0 1 0
## 5   5 0 1 0
## 6   6 0 0 0
## 7   7 0 0 0
## 8   8 0 0 1
## 9   9 0 0 1
## 10 10 1 0 0

こうさつ

要点を先に。何気なく頻繁に使うNA。こいつの挙動には気をつけたほうが良さ気。teramonagiさんはダミーデータの作成時に欠損値を意味するNAを使っていたのですが、これをそのままspreadにかけてしまったところが罠だったようです。

df <- data.frame(id = 1:10, 
                 feature = c(1, NaN, 2, 2, 2, NaN, NaN, 3, 3, 1))
df$feature
##  [1]   1 NaN   2   2   2 NaN NaN   3   3   1
df.na <- data.frame(id = 1:10, 
                 feature = c(1, NA, 2, 2, 2, NA, NA, 3, 3, 1))
df.na$feature
##  [1]  1 NA  2  2  2 NA NA  3  3  1

この段階では何も問題がなさそう。

ところがどっこい、spreadでdf$featureの値を列名に置き換えるという処理を行うさい、NAの存在が思わぬ障害を招いていました。

df.na %>>% spread(key   = feature, 
              value  = feature,
              fill   = 0) %>>% 
  select(-contains("NA"))
## data frame with 0 columns and 10 rows

どうしてこのようなことになるのでしょうか。

spreadした時点での列名はid, 1, 2, 3, NAの5列からなっているはずですが…

df.na %>>% spread(key   = feature, 
              value  = feature,
              fill   = 0) %>>%  colnames()
## [1] "id" "1"  "2"  "3"  NA

NAの部分は認識されていない(?)みたいです。これが元で返り値がエラーになったのだと思われます。

というわけで、欠損値ではなく、とりあえずなんらかしらが存在するよ、という意味でNaNを使って対処しました。

df %>>% spread(key   = feature, 
              value  = feature,
              fill   = 0) %>>%  colnames()
## [1] "id"  "1"   "2"   "3"   "NaN"

NaNであれば列名として認識してくれるみたいです。

理由は説明できません。他の(R言語の構造に詳しい)方が解説してくれることを願います。現場からは以上です。