R 设置键时data.table如何对字符串排序

R 设置键时data.table如何对字符串排序,r,data.table,R,Data.table,昨天我花了一些时间试图在我的代码中找到一个bug,我发现data.table包对字符串的排序方式与base略有不同。这是一种正常的行为吗?最有效的方法是什么(它具有data.table的优点)来重现使用baseorder函数获得的结果?以下是一个可复制的玩具示例: library(data.table) options(stringsAsFactors = FALSE) d <- data.frame(cn=c("USA","Ubuntu","Uzbekistan")) d[order(

昨天我花了一些时间试图在我的代码中找到一个bug,我发现
data.table
包对字符串的排序方式与base略有不同。这是一种正常的行为吗?最有效的方法是什么(它具有
data.table
的优点)来重现使用base
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())
库(data.table)
选项(stringsAsFactors=FALSE)

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

dt[order(dt$cn)]

           cn
1:     Ubuntu
2:        USA
3: Uzbekistan

2014年3月更新

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

考虑在您的区域设置中设置键控表,并让同事在不同的区域设置中设置键控表。当它们连接到该表时,如果是区域设置排序顺序,则该表可能不再正常工作。如果
setkey
允许再次进行区域设置排序,我们必须更仔细地考虑,可能是通过将区域设置名称与“sorted”属性一起保存,这样
data.table
至少可以比较和检测当前区域设置是否与运行
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
?订单

字符向量的排序顺序将取决于所用区域设置的排序顺序:请参阅
比较

?比较

字符向量中字符串的比较是使用所用语言环境的排序顺序在字符串中进行字典排序的:请参阅语言环境。像en_US这样的区域设置的排序顺序通常与C(应该使用ASCII)不同,这可能会令人惊讶。注意不要对排序顺序做出任何假设:例如,在爱沙尼亚语中,Z位于S和T之间,排序不一定是逐字符的——在丹麦语中,aa排序为单个字母,在Z之后

因此,基本上,
order
以及在“C”语言环境下,给出了与
数据相同的顺序。我的猜测是,
chorder
调用的C函数自动在C-locale上运行,它将比较“S”在“b”之前的ascii值


让@MatthewDowle注意到这一点可能很重要(如果他还没有意识到的话)。因此,我建议您将其作为一个bug进行归档(只是为了确保)。

这很好,但对于更大的数据集,它可能比我同意的setkey慢得多。这似乎与setkey中使用的排序方法有关。这是它在?setkey中所说的(但是我找不到在setkey中设置排序方法的选项)。尝试使用sort.list中的非常快的“基数”方法进行排序。如果失败,排序将按顺序恢复为默认方法。这种逻辑是逐列重复的。也许其他人知道得更多?干得不错,但我不会称之为bug,也许是功能请求这是一个老问题,指的是1.8.x(2013)左右的data.table版本
Sys.setlocale("LC_ALL", "C")
# [1] "C/C/C/C/C/en_US.UTF-8"

order(x)
# [1] 1 2 3