【问题标题】:Using data.table Subsettting for non equality使用 data.table 子集进行不等式
【发布时间】:2015-04-30 20:33:56
【问题描述】:

我有一个包含 400k 行的数据表,我正在做子集,它非常慢。

这是一个示例数据框:

                 date   name value size car1 car2
1 2015-01-01 07:44:00    bob     1    5    A    D
2 2015-02-02 09:46:00 george   522    2    B    F

现在我使用subset() 以慢速方式对其进行子集化:

main<- data.frame(date = as.POSIXct(c("2015-01-01 07:44:00","2015-02-02 09:46:00"),tz="GMT"),name= c("bob","george"),value=c(1,522), size= c(5,2), car1=c("A","B"), car2=c("D","F"))
main$date
subset(main,    size >1 
       &  value == 522
       &  name == "george" 
       &  date >= as.POSIXct("2015-01-01 03:44:00",tz="GMT") &  date >= as.POSIXct("2015-01-01 08:44:00",tz="GMT")
       &  (car1 == "F" | car2 == "F")
)

                 date   name value size car1 car2
2 2015-02-02 09:46:00 george   522    2    B    F

这可行并返回 1 行,但速度很慢。

感谢对另一个问题的一些回应,使用 data.table 看起来要快得多,所以我想使用 data.table 来做与上面相同的事情,但我有很多问题。

这是我目前为止的:

   library(data.table)  
 mdt<- as.data.table(main)
 setkey(mdt, date, name, value,size,car1,car2)
  mdt[.(as.POSIXct("2015-01-01 03:44:00"),"george", 522,2,"F","F")]

这会返回:

date   name value size car1 car2
1: 2015-01-01 03:44:00 george   522    2   NA    F

这是我的问题:

(1) 我想要一个条件,其中日期 >= 和日期

(2) 我想要一个标准,其中 (car1 == "F" | car2 == "F") 但这可能吗?如果没有任何想法如何使子集更快?

(3) 您可以看到 mdt[] 的输出日期为 2015-01-01 03:44:00,但该日期不在原始“主”数据框中。这里发生了什么?

(4) 您可以在 mdt[] 的输出中看到,当原始“主”数据帧中的 car1 不是 NA 时,car1 的值为 NA。这里发生了什么?

谢谢。

【问题讨论】:

  • 对于 (1),我认为 roll 参数可能对不等式有帮助,但我自己还没有学会。我会把它留给 eddi 或其他比我更有知识的人之一。您也可以查看 wiki 或课程以了解可行的方法:github.com/Rdatatable/data.table/wikidatacamp.com/courses/data-table-data-manipulation-r-tutorial
  • 对于 (2),您能否扩展您的示例以涵盖该应用程序?
  • 我认为您的setkey 应该更加明确。除非您使用每个字段,否则您不需要包含每个字段。但是所有这些都应该在data.table 中是可行的——我只是不经常处理日期。 xmpl &lt;- data.table(v1 = c("a", "a", "b", "c"), v2 = 1:4); xmpl[v1 == "a" &amp; v2 &gt; 1 &amp; v2 &lt; 4];setkey(xmpl, v1); xmpl["j"] 请注意,一旦您在带键的 data.table 上给出了值,它将根据您给它的值返回——无论该键是否在表中。
  • @ Frank -- 我不知道如何扩展 or 语句的 data.table 语法。我在问有没有可能。
  • 对于 (3) 和 (4),它旨在做到这一点。 J 的每一行将在输出中至少有一行。如果没有匹配,它将有NA 用于未连接的列。要禁用此功能,请尝试 mdt[.(as.POSIXct("2015-01-01 03:44:00"),"george", 522,2,"F","F"),nomatch=FALSE]

标签: r data.table


【解决方案1】:

当然,您只需将条件放在i 表达式中即可。

setDT(main)
main[size >1 &
       value == 522 &
       name == "george" &
       date >= as.POSIXct("2015-01-01 03:44:00",tz="GMT") &
       date >= as.POSIXct("2015-01-01 08:44:00",tz="GMT") &
       (car1 == "F" | car2 == "F"), ]

结果:

                  date   name value size car1 car2
1: 2015-02-02 09:46:00 george   522    2    B    F

那么,这比subset 快吗?是的。

library(data.table)
library(ggplot2)
library(reshape2)

set.seed(1)

cf <- function(n) {
  main <- 
    data.frame(date = as.POSIXct(Sys.Date()+runif(n, 0, 100)),
               name = sample(c("bob","george"), n, replace=T),
               value = round(runif(n, 400,600), 0), 
               size= sample(1:5, n, replace=T), 
               car1= sample(LETTERS[1:6], n, replace=T), 
               car2= sample(LETTERS[1:6], n, replace=T),
               stringsAsFactors=F)
  mdt <- data.table(main)
  setkey(mdt, date, name, value,size,car1,car2)

  pre <- Sys.time()
  mdt[size > 1 & value > 100  & name == "george" &
         date >= as.POSIXct(Sys.Date()) & date <= as.POSIXct(Sys.Date()+50) &
         (car1 == "F" | car2 == "F"), ]
  dt_time <- Sys.time() - pre

  pre <- Sys.time()
  subset(main, 
         size > 1 & value > 100 & name == "george" &
         date >= as.POSIXct(Sys.Date()) & date <= as.POSIXct(Sys.Date()+50) &
         (car1 == "F" | car2 == "F"))
  subset_time <- Sys.time() - pre

  return(c(n=n, dt_time=dt_time, subset_time=subset_time))
}

result <- sapply(10^(2:7), cf)
result <- melt(data.frame(t(result)), id.var='n')

ggplot(result, aes(x=n, y=value, color=variable)) +
  geom_point() + geom_line() + theme_bw() +
  scale_x_log10()

【讨论】:

  • 所以您不能将 J 表达式(即 .() 或 list())与 >=、
  • 您想使用上述条件对 data.table 进行子集化,对吗? i 用于子集行,而不是 j。您可以在j 中使用表达式,但这是用于转换列,而不是子集行
  • 哦,你是对的。我在. 之前看到了一个逗号,实际上没有逗号。编辑
  • @Frank 实际上data.table 设置了辅助键,我认为在第一次运行之后,这段代码几乎和二进制连接一样快
  • 第一次没有setkey。刚刚更新,DT 似乎变得更好了
猜你喜欢
  • 1970-01-01
  • 2020-07-24
  • 2021-03-11
  • 1970-01-01
  • 2015-11-30
  • 1970-01-01
  • 1970-01-01
  • 2014-01-08
  • 2017-12-23
相关资源
最近更新 更多