3

我正在使用Hmisc包计算两个连续变量的分位数并在交叉表中比较结果。您可以在下面找到我的代码。

我的问题是,如果观察次数增加,分位数的计算需要相当长的时间。

data.table有没有可能通过使用,ddply或任何其他包来加快这个过程?

谢谢。

library(Hmisc)

# Set seed
set.seed(123)

# Generate some data
a <- sample(1:25, 1e7, replace=TRUE)
b <- sample(1:25, 1e7, replace=TRUE)
c <- data.frame(a,b)

# Calculate quantiles
c$a.quantile <- cut2(a, g=5)
c$b.quantile <- cut2(b, g=5)

# Output some descriptives
summaryM(a.quantile ~ b.quantile, data=c, overall=TRUE)

# Time spent for calculation:
#       User      System verstrichen 
#      25.13        3.47       28.73 
4

3 回答 3

3

正如 jlhoward 和 Ricardo Saporta 所说,data.table在这种情况下似乎并没有加快速度。cut2功能显然是这里的瓶颈。我使用另一个函数来计算分位数(请参阅Is there a better way to create quantile "dummies" / factor in R?)并且能够将计算时间减少一半:

qcut <- function(x, n) {
  if(n<=2)
    { 
    stop("The sample must be split in at least 3 parts.")
  }
  else{
    break.values <- quantile(x, seq(0, 1, length = n + 1), type = 7)
    break.labels <- c(
      paste0(">=",break.values[1], " & <=", break.values[2]),
      sapply(break.values[3:(n)], function(x){paste0(">",break.values[which(break.values == x)-1], " & <=", x)}),
      paste0(">",break.values[(n)], " & <=", break.values[(n+1)]))
    cut(x, break.values, labels = break.labels,include.lowest = TRUE)
  }
}

c$a.quantile.2 <- qcut(c$a, 5)
c$b.quantile.2 <- qcut(c$b, 5)
summaryM(a.quantile.2 ~ b.quantile.2, data=c, overall=TRUE)

# Time spent for calculation:
#       User      System verstrichen 
#      10.22        1.47       11.70 

使用data.table会将计算时间再缩短一秒,但我更喜欢Hmisc包的摘要。

于 2013-12-03T13:48:57.423 回答
2

您可以使用data.table' .N内置变量来快速制表。

library(data.table)
library(Hmisc)

DT <- data.table(a,b)
DT[, paste0(c("a", "b"), ".quantile") := lapply(.SD, cut2, g=5), .SDcols=c("a", "b")]

DT[, .N, keyby=list(b.quantile, a.quantile)][, setNames(as.list(N), as.character(b.quantile)), by=a.quantile]

你可以把最后一行分成两个步骤,看看发生了什么。第二个"[ "只是以干净的格式重塑数据。

DT.tabulated <- DT[, .N, keyby=list(b.quantile, a.quantile)]
DT.tabulated

DT.tabulated[, setNames(as.list(N), as.character(b.quantile)), by=a.quantile]
于 2013-12-02T17:01:09.687 回答
1

数据表似乎并没有改善这里的情况:

library(Hmisc)
set.seed(123)
a <- sample(1:25, 1e7, replace=TRUE)
b <- sample(1:25, 1e7, replace=TRUE)

library(data.table)
# original approach
system.time({
  c <- data.frame(a,b)
  c$a.quantile <- cut2(a, g=5)
  c$b.quantile <- cut2(b, g=5)
  smry.1 <-summaryM(a.quantile ~ b.quantile, data=c, overall=TRUE)
})
   user  system elapsed 
  72.79    6.22   79.02 

# original data.table approach
system.time({
  DT <- data.table(a,b)
  DT[, paste0(c("a", "b"), ".quantile") := lapply(.SD, cut2, g=5), .SDcols=c("a", "b")]
  smry.2 <- DT[, .N, keyby=list(b.quantile, a.quantile)][, setNames(as.list(N), as.character(b.quantile)), by=a.quantile]
})
   user  system elapsed 
  66.86    5.11   71.98 

# different data.table approach (simpler, and uses table(...))
system.time({
  dt     <- data.table(a,b)
  smry.3 <- table(dt[,lapply(dt,cut2,g=5)])
})
   user  system elapsed 
  67.24    5.02   72.26 
于 2013-12-02T20:39:59.697 回答