【问题标题】:How data.table sorts strings when setting key设置键时data.table如何对字符串进行排序
【发布时间】:2018-02-02 17:35:47
【问题描述】:

昨天我不得不花一些时间试图在我的代码中找到一个错误,我发现data.table 包对字符串进行排序的方式与 base 有点不同。这是正常行为吗?重现使用基本order 函数获得的结果的最有效方法是什么(具有data.table 的好处)?这是一个玩具可重现的例子:

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

操作系统 Windows 7

【问题讨论】:

  • 这是一个老问题,指的是 1.8.x (2013) 左右的 data.table 版本

标签: r data.table


【解决方案1】:

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

dt[order(dt$cn)]

           cn
1:     Ubuntu
2:        USA
3: Uzbekistan

【讨论】:

  • 这很好用,但是对于更大的数据集,它可能比 setkey 慢得多
  • 我同意。似乎它可能与 setkey 中使用的排序方法有关。这就是它在 ?setkey 中所说的(但是我找不到在 setkey 中设置排序方法的选项)尝试使用 sort.list 中非常快速的“基数”方法进行排序。如果失败,排序将按顺序恢复为默认方法。该逻辑逐列重复。也许其他人知道更多?
【解决方案2】:

2014 年 3 月更新

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

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

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

因此,现在这是一个功能请求,非常欢迎更多的 cmets。

FR#4842 setkey to sort using session's locale not C locale



不错的收获!对setkey 的调用依次调用setkeyvfastorder 对依次调用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....之后。

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

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

【讨论】:

  • 干得好,但我不认为这是一个错误,也许是一个功能请求
猜你喜欢
  • 2017-11-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多