10

昨日、コードのバグを見つけるのに時間を費やす必要があり、data.tableパッケージが base とは少し異なる方法で文字列を並べ替えていることがわかりました。これは正常な動作であり、基本関数data.tableで得られた結果を再現する最も効率的な方法 (の利点がある)は何ですか? orderこれはおもちゃの再現可能な例です:

library(data.table)
options(stringsAsFactors = FALSE)

d <- data.frame(cn=c("USA","Ubuntu","Uzbekistan"))
d[order(d$cn),,drop=F]

#          cn
#2     Ubuntu
#1        USA
#3 Uzbekistan

dt <- data.table(d)
setkey(dt, cn)
dt

#           cn
#1:        USA
#2:     Ubuntu
#3: Uzbekistan

options(stringsAsFactors = default.stringsAsFactors())

OS Windows7

4

2 に答える 2

10

2014 年 3 月の更新

これについては、いくつかの議論がありました。v1.9.2 の時点で、setkeyC ロケールを使用したソートに落ち着いています。たとえば、ユーザーのロケールに関係なく、すべての大文字がすべての小文字の前に来ます。これは v1.8.8 で行われた変更であり、元に戻すつもりでしたが、今のところ固執しています。

save()あなたのロケールでキー付きテーブルを -ing し、同僚が別のロケールで -ing することを検討してくださいload()。それらがそのテーブルに参加すると、それがロケールのソート順である場合、正しく機能しなくなる可能性があります。setkeyおそらく「ソート済み」属性とともにロケール名を保存することにより、ロケールの順序付けを再度許可するかどうかをもう少し慎重に検討する必要があります。これによりdata.table、少なくとも現在のロケールが実行されたロケールと異なるかどうかを比較および検出できますsetkey

また、ロケールによるソートは C ロケールよりもはるかに遅いため、速度上の理由もあります。ただし、可能な限り効率的に行うことができ、オプションで許可することが理想的です。

したがって、これは現在機能のリクエストであり、さらなるコメントは大歓迎です。

FR#4842 C ロケールではなくセッションのロケールを使用してソートするための setkey



ナイスキャッチ!への呼び出しはsetkey、 を呼び出しsetkeyv、 を呼び出すfastorder列/エントリを「順序付け」ますchorder

chorder次に、C 関数を呼び出しますCcountingcharacter.c。さて、ここで問題は「ロケール」が原因であると思います。

Mac で使用している「ロケール」を見てみましょう。

Sys.getLocale()
# [1] "en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8"

orderそれでは、それをどのようにソートするか見てみましょう:

x <- c("USA", "Ubuntu", "Uzbekistan")
order(x)
# [1] 2 1 3

では、「locale」を「C」に変更してみましょう。

Sys.setlocale("LC_ALL", "C")
# [1] "C/C/C/C/C/en_US.UTF-8"

order(x)
# [1] 1 2 3

から?order:

文字ベクトルの並べ替え順序は、使用されているロケールの照合順序によって異なります。 を参照してくださいComparison

から?Comparison:

文字ベクトル内の文字列の比較は、使用中のロケールの照合順序を使用して、文字列内で辞書式に行われます。ロケールを参照してください。en_US などのロケールの照合順序は通常、C (ASCII を使用する必要があります) とは異なり、驚くべきことがあります。照合順序に関する仮定に注意してください。たとえば、エストニア語では Z は S と T の間にあり、照合は必ずしも文字単位で行われるとは限りません。デンマーク語では、aa は z... の後に 1 文字としてソートされます。

したがって、基本的に、order「C」ロケールの下でも、 と同じ順序になりdata.tableますsetkey。私の推測では、によって呼び出される C 関数はchorderC ロケールで自動的に実行され、"S" が "b" の前にある ascii 値を比較します。

これを@MatthewDowleの注意を引くことはおそらく重要です(彼がまだ気づいていない場合)。したがって、これをバグとしてここに報告することをお勧めします(念のため)。

于 2013-08-20T14:21:51.470 に答える