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())

操作系统视窗 7

4

2 回答 2

10

2014 年 3 月更新

关于这个有一些争论。从 v1.9.2 开始,我们现在已经决定setkey使用 C 语言环境进行排序;例如,所有大写字母都在所有小写字母之前,无论用户的语言环境如何。这是在 v1.8.8 中进行的更改,我们原本打算扭转但现在坚持下去。

考虑save()在您的语言环境中创建一个键控表,并让一位同事load()在不同的语言环境中使用它。当他们加入该表时,如果它是区域设置排序顺序,它可能不再正常工作。我们必须更仔细地考虑setkey是否允许再次进行语言环境排序,可能通过将语言环境名称与“排序”属性一起保存,这样data.table至少可以比较和检测当前语言环境是否与运行的语言环境不同setkey

这也是出于速度原因,因为根据语言环境进行排序比 C 语言环境慢得多。虽然,我们可以尽可能高效地做到这一点,并允许它随意选择将是理想的。

因此,这现在是一个功能请求,非常欢迎进一步的评论。

FR#4842 setkey 使用会话的语言环境而不是 C 语言环境进行排序



不错的收获!调用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

现在,让我们将“语言环境”更改为“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 之后。

因此,基本上,在“C”语言环境下,给出与'sorder相同的顺序。我的猜测是,调用的 C 函数自动在 C 语言环境上运行,它将比较“S”在“b”之前的 ascii 值。data.tablesetkeychorder

引起@MatthewDowle 的注意可能很重要(如果他还没有意识到的话)。因此,我建议您在此处将其作为错误提交(只是为了确定)。

于 2013-08-20T14:21:51.470 回答
2

好吧,我不确定最有效的方法是什么,但您可以执行以下操作来重现 data.frame 结果。

dt[order(dt$cn)]

           cn
1:     Ubuntu
2:        USA
3: Uzbekistan
于 2013-08-20T13:34:33.660 回答