【问题标题】:subsetting in data.tabledata.table 中的子集
【发布时间】:2011-07-26 03:04:40
【问题描述】:

我正在尝试在 R(不是 data.frame)中对 data.table(来自包 data.table)进行子集化。我有一个 4 位数的年份作为密钥。我想通过一系列年份来细分。例如,我想拉取 1999、2000、2001 年的所有记录。

我尝试在我的DT[J(year)] 二进制搜索语法中传递以下内容:

1999,2000,2001
c(1999,2000,2001)
1999, 2000, 2001

但这些似乎都不起作用。任何人都知道如何做一个子集,其中您要选择的年份不仅仅是 1 年,而是多年?

【问题讨论】:

  • 很抱歉,我不是 Stackoverflow 上的好公民。现在会处理这个。还将更加注意包含参考资料,以便为那些试图帮助我的人节省时间。
  • @Andrie :对问题进行了编辑以包含它(@exl 这样做了,我只是让它更清楚一点),因此如果您愿意,可以撤销您的反对票。其余的问题至少是有效的。
  • @Joris,这已经是一个进步,所以我已经推翻了我的反对意见。然而,要成为一个好问题,它需要一个 library(data.table) 语句加上一些真实的示例代码。
  • -1 表示不提供错误消息或示例数据。
  • +1 以扭转一些过度降价。 -1 可能没有 data.table ref,但是 -5?为什么需要为如此简单的语法问题列出错误消息?

标签: r subset data.table


【解决方案1】:

适用于data.frames 的方法适用于data.tables。

subset(DT, year %in% 1999:2001)

【讨论】:

  • 并非所有内容:dt <- data.table(a=c(1,2,3), b=c(4,5,6), c=c(7,8,9)); dt[, c('b', 'c')] 返回列名向量 - 使用 data.frame,它返回列。
  • data.table 现在有自己的subsetsubset.data.table {data.table}
【解决方案2】:

这个问题不清楚,也没有提供足够的数据来处理,但它很有用,所以如果有人可以用我以后提供的数据对其进行编辑,欢迎提供。帖子的标题也可以完成:Matthew Dowle 经常回答 subsetting-over-two-vectors 问题,但较少回答 subsetting-according-a-in-statement-on-one-vector 的问题。我一直在寻找答案,直到找到一个字符向量here

让我们考虑一下这些数据:

library(data.table)
n <- 100
X <- data.table(a=sample(c(10,20,25,30,40),n,replace=TRUE),b=1:n)

X[X$a %in% c(10,20),] 对应的 data.table 样式查询有点令人惊讶:

setkey(X,a)
X[.(c(10,20))]
X[.(10,20)] # works for characters but not for integers
            # instead, treats 10 as the filter
            # and 20 as a new variable

# for comparison :
X[X$a %in% c(10,20),]

现在,哪个最好?如果您的密钥已经设置,显然是 data.table。否则,它可能不会,因为证明以下时间测量(在我的 1,75 Go RAM 计算机上):

n <- 1e7
X <- data.table(a=sample(c(10,20,25,30,40),n,replace=TRUE),b=1:n)
system.time(X[X$a %in% c(10,20),])
# utilisateur     système      écoulé (yes, I'm French) 
#        1.92        0.06        1.99
system.time(setkey(X,a))
# utilisateur     système      écoulé 
#       34.91        0.05       35.23 
system.time(X[J(c(10,20))])
# utilisateur     système      écoulé 
#        0.15        0.08        0.23

但也许马修有更好的解决方案……


[Matthew] 你发现排序类型numeric(又名double)比integer 慢得多。多年来,我们不允许 double 在密钥中使用,因为担心用户会掉入这个陷阱并报告这样的糟糕时机。我们允许double 带有一些恐惧的键,因为还没有为double 实现快速排序。 integercharacter 的快速排序非常好,因为它们是使用计数排序完成的。 希望有一天我们能对numeric 进行快速排序!(现已实施 - 见下文)。

data.table pre-1.9.0 上的时间

n <- 1e7
X <- data.table(a=sample(c(10,20,25,30,40),n,replace=TRUE),b=1:n)      
system.time(setkey(X,a))
#   user  system elapsed 
# 13.898   0.138  14.216 

X <- data.table(a=sample(as.integer(c(10,20,25,30,40)),n,replace=TRUE),b=1:n)
system.time(setkey(X,a))
#   user  system elapsed 
#  0.381   0.019   0.408 

请记住,2 默认是 R 中的 numeric 类型。 2Linteger。尽管data.table 接受numeric,但它仍然更喜欢integer


从 v1.9.0 开始实现了数字的快速基数排序。

从 v1.9.0 开始

n <- 1e7
X <- data.table(a=sample(c(10,20,25,30,40),n,replace=TRUE),b=1:n)      
system.time(setkey(X,a))
#    user  system elapsed 
#   0.832   0.026   0.871 

【讨论】:

  • 关于“不太频繁”的评论你能提供一些链接吗?我不知道我完全避免回答任何问题。另外我不遵循“适用于字符但不适用于整数”位,你有它适用于字符的例子吗?需要在对list()data.frame|table 的调用中使用c() 创建向量是常见的R 习惯用法。
  • 但是现在你已经回答了这个问题,我明白提问者现在在问什么了。但当时(2年前)我真的不明白。我通常猜我是否可以(如果问题中的第 1 次和第 3 次尝试是有效的语法,那会有所帮助)。我同意这实际上是一个很好的问题,在内心深处。
  • 我并不是说您实际上避免回答:) 只是这个问题很少被问到。好的,对于整数情况,我的错误。有关字符的示例,请参阅开头提供的链接。使用X &lt;- data.table(a=sample(as.character(c(10,20,25,30,40)),n,replace=TRUE),b=1:n),您可以根据aX[.('10','20')] 的子集来子集X
【解决方案3】:

和上面一样,但更多的是data.table esque:

DT[year %in% c(1999, 2000, 2001)]

【讨论】:

  • 是的,但我们不想鼓励矢量扫描。这个问题很糟糕。如果他们包含基本示例和错误消息,则可以使用二分搜索解决。
  • 这几天,我猜这是自动索引的正确答案。
【解决方案4】:

这将起作用:

sample_DT = data.table(year = rep(1990:2010, length.out = 1000), 
                       random_number = rnorm(1000), key = "year")
year_subset = sample_DT[J(c(1990, 1995, 1997))]

同样,您可以使用 setkey(existing_DT, year) 为已经存在的 data.table 设置键,然后使用如上所示的 J() 语法。

我认为问题可能在于您没有先键入数据。

【讨论】:

    猜你喜欢
    • 2013-01-08
    • 1970-01-01
    • 2014-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-12
    相关资源
    最近更新 更多