【问题标题】:R data.table join with inequality conditionsR data.table 连接不等式条件
【发布时间】:2013-10-03 21:26:51
【问题描述】:

我想使用 data.table 包根据多个不等式条件对我的数据进行子集化。 data.table 手册中的示例显示了如何使用字符变量而不是数值不等式来执行此操作。我还看到了如何使用子集函数来做到这一点。但我真的很想利用 data.table 的二进制搜索速度。下面是我正在尝试做的一个示例。

library(data.table)

data <- data.table(X=seq(-5,5,1), Y=seq(-5,5,1), Z=seq(-5,5,1))
data

setkey(data, X, Y, Z)

#the data.frame way
data[X > 0 & Y > 0 & Z > 0]

#the data.table way (does not work as I expected)
data[J(>0, >0, >0)]

【问题讨论】:

  • 等等,但是......“data.frame 方式”在这里有效,对吧?事实上,它会因为 data.frame 而失败。 J 用于“加入”,将对象子集作为第一步;但“data.frame 方式”是不等式子集的正常方式。
  • 另外,澄清一下,J 将采用 X、Y 和 Z 的值,而不是它们的条件;然后合并/加入这些值。并且需要键入“数据”才能使其正常工作。
  • @Frank +1 我们可能应该对i 进行一些优化,以便不等式使用引擎盖下的关键。我想人们在介绍小插曲中明白不要使用==,然后期望类似的概念适用于矢量扫描&gt;。也许甚至== 应该使用引擎盖下的钥匙,因为它更自然。
  • @Frank 更简单:DT[X &gt; 0 &amp; Y &gt; 0 &amp; Z &gt; 0] 只会自动使用密钥。由于这是 R,我们可以采用 i 表达式并在评估之前对其进行优化。
  • @Frank 没错。如果我们可以将==&gt;&lt;|&amp; 的任意组合结合使用,那么这将是一个开始。如果它不是优化的模式,那么它只会退回到常规矢量扫描。辅助键可以自动构建和缓存。

标签: r data.table subset inequality


【解决方案1】:

使用包 dplyr 的解决方案非常快速和直接。

install.packages(dplyr)
library(dplyr)

newdata <- filter(data, X > 0 , Y > 0 , Z > 0)

dplyr 被证明是管理数据帧的最简单和最快的软件包之一。在这里查看这个很棒的教程:http://cran.rstudio.com/web/packages/dplyr/vignettes/introduction.html

RStudio 团队还制作了一份不错的备忘单,在这里:http://www.rstudio.com/resources/cheatsheets/

【讨论】:

  • 它比data[X &gt; 0 &amp; Y &gt; 0 &amp; Z &gt; 0]更快或更简单吗???你有基准吗?还是你觉得写filter比写[简单?
  • 我不是说 fastEr 或 simplEr ,只是 dplyr 以一种快速简单的方式解决了这个问题。感谢您的提醒。
【解决方案2】:

我运行了一些基准测试

library(dplyr)
library(data.table)
library(microbenchmark)

dt.data.frame.way <- function(data) data[X > 0 & Y > 0 & Z > 0]
dplyr.way <- function(df) filter(df, X > 0, Y > 0, Z > 0)
real.data.frame.way <- function(df) df[df$X > 0 & df$Y > 0 & df$Z > 0,]

data <- data.table(X=seq(-5,5,1), Y=seq(-5,5,1), Z=seq(-5,5,1))
setkey(data, X, Y, Z)
df <- as.data.frame(data)

microbenchmark(times = 10,
               dt.data.frame.way(data),
               dplyr.way(df),
               real.data.frame.way(df))
# Unit: microseconds
#                     expr     min       lq       mean    median       uq        max neval
#  dt.data.frame.way(data) 710.426  754.287   871.8784  824.7565  942.998   1180.458    10
#            dplyr.way(df) 951.309 1045.246 12303.3462 1142.7440 1246.668 112775.934    10
#  real.data.frame.way(df) 137.239  162.591   181.5254  187.9785  197.373    231.594    10

将示例数据简单克隆到 550 万行。

data <- data.table(X=seq(-5,5,1), Y=seq(-5,5,1), Z=seq(-5,5,1))
data <- rbindlist(lapply(1:5e5, function(i) data)) # 5500000 rows
setkey(data, X, Y, Z)
df <- as.data.frame(data)

microbenchmark(times = 10,
               dt.data.frame.way(data),
               dplyr.way(df),
               real.data.frame.way(df))
# Unit: milliseconds
#                     expr      min        lq      mean    median        uq       max neval
#  dt.data.frame.way(data) 656.2978  668.0560  730.9246  696.6560  831.0877  846.0517    10
#            dplyr.way(df) 632.4096  639.1141  709.4308  678.9436  717.3018 1015.7663    10
#  real.data.frame.way(df) 964.4298 1022.1772 1075.8448 1077.4437 1125.0037 1192.7410    10

该任务的性能似乎很难提高。这通常取决于数据。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-04-29
    • 1970-01-01
    • 2016-11-12
    • 2022-12-18
    • 1970-01-01
    • 2014-03-02
    • 2020-09-16
    • 1970-01-01
    相关资源
    最近更新 更多