読者です 読者をやめる 読者になる 読者になる

Why are you using UTF-8???

追記(2016/5/1):直りました!!!

追記(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 '種類' 

UTF-8でもSJISでも何かしらエラーになるとか…

おおブッダよ! 寝ているのですか??

つらい。

ちなみにこれはなぜ起こるかというと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

それはわかるけどどうやって直せばいいんだ…