追記(2016/5/1):直りました!!!
追記(2016/12/1):と思ったらそのあとまた壊れてました!!!(涙)
Encoding problems on Windows caused by character -> symbol -> character roundtrip · Issue #1950 · hadley/dplyr https://t.co/b6dESZt5WZ フワー!!
— Hiroaki Yutani (@yutannihilation) 2016年12月1日
Tokyo.R界隈で「Why are you using SJIS?」ということばが有名です。
これは、文字コードのつらみを表現する言葉として多用され、感嘆詞としての役割を担っています。その元ネタはこのIssueなのですが、これはSJISの文字列を列名に使っているとエラーが起きるというものでした。
が、今日私はその真逆の問題があるのに気づいてしまいました。そう、これがのちのWhy are you using UTF-8?問題です。
これは、おそらくWindows特有で、今のところgroup_by()
とdistinct()
で発生することを確認しています。
たとえば、こんな感じで列名に日本語を使う場合を考えてみましょう。以下のようにデフォルトの文字コードだと何のエラーもなく成功します。
library(dplyr) x <- "種類" names(iris)[5] <- x # 文字コードはすべてデフォルト Encoding(names(iris)) #> [1] "unknown" "unknown" "unknown" "unknown" "unknown" # これはOK distinct_(iris, x) #> Sepal.Length Sepal.Width Petal.Length Petal.Width 種類 #> 1 5.1 3.5 1.4 0.2 setosa #> 2 7.0 3.2 4.7 1.4 versicolor #> 3 6.3 3.3 6.0 2.5 virginica
ところが、これがUTF-8になるとエラーが出ます。
# UTF-8を使う x <- iconv("種類", to = "UTF-8") names(iris)[5] <- x # UTF-8を使う Encoding(names(iris)) # エラーになる... distinct_(iris, x) #> Error: unknown column '種類' distinct(iris, `種類`) #> Error: unknown column '種類' # group_byも同じ group_by_(iris, x) #> Error: unknown column '種類'
おおブッダよ! 寝ているのですか??
つらい。
ちなみにこれはなぜ起こるかというとlazyevalのall_dots()
で評価されるときに文字コードが落ちるからっぽくて、
x <- iconv("進捗", to = "UTF-8") Encoding(x) #> [1] "UTF-8" f <- function(.dots, ...) { lazyeval::all_dots(.dots, ..., all_named = TRUE) } sinchoku_dots <- f(x) sinchoku_dots #> $進捗 #> <lazy> #> expr: 進捗 #> env: <environment: base> #> #> attr(,"class") #> [1] "lazy_dots" Encoding(names(sinchoku_dots)) #> [1] "unknown"
じゃあなんでそれでもselect()
とかはうまく動くかというとlazy_eval()
がいい感じにやってくれるからみたいです(このへん)
names_list <- setNames(list(1), x) names_list #> $`進捗` #> [1] 1 Encoding(names(names_list)) #> [1] "UTF-8" # 文字コードが違ってても評価するときに同じとみなしてくれるっぽい lazyeval::lazy_eval(sinchoku_dots, names_list) #> $進捗 #> [1] 1
それはわかるけどどうやって直せばいいんだ…