使用data.table子集不相等

时间:2015-04-30 20:33:56

标签: r data.table

我有一个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)我想要一个标准,其中date&gt; =和date&lt; =但是这可以使用data.table吗?如果没有任何想法如何使子集更快?

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

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

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

谢谢。

1 个答案:

答案 0 :(得分:2)

当然,您只需将标准放在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()

enter image description here