使用R中的复杂调查设计提高查询速度

时间:2015-09-03 16:11:24

标签: r performance memory survey

我有一个大型数据集(超过2000万个障碍物),我使用survey包进行分析,运行简单查询需要花费很多时间。我试图找到一种方法来加快我的代码,但我想知道是否有更好的方法来提高效率。

在我的基准测试中,我使用svyby / svytotal来比较三个命令的速度:

  1. 简单命令svyby / svytotal
  2. 使用{内核foreach dopar进行并行计算
  3. 选项2的编译版本
  4. Spoiler:选项3的速度是第一个选项的两倍以上它不适合大型数据集,因为它依赖于并行计算,并且在处理大数据时会快速达到内存限制集。尽管我有16GB的RAM,但我也遇到了这个问题。有一些solutions to this memory limitation,但它们都不适用于调查设计对象。

    有关如何加快速度而不是因内存限制而崩溃的任何想法?

    我的代码带有可重复的示例:

    # Load Packages
    library(survey)
    library(data.table)
    library(compiler)
    library(foreach) 
    library(doParallel)
    options(digits=3)
    
    # Load Data
    data(api)
    
    # Convert data to data.table format (mostly to increase speed of the process)
    apiclus1 <- as.data.table(apiclus1)
    
    # Multiplicate data observations by 1000 
    apiclus1 <- apiclus1[rep(seq_len(nrow(apiclus1)), 1000), ]
    
    # create a count variable
    apiclus1[, Vcount := 1]
    
    # create survey design
    dclus1 <- svydesign(id=~dnum, weights=~pw, data=apiclus1, fpc=~fpc)
    

    1)简单代码

    t1 <- Sys.time()
    table1 <- svyby(~Vcount,
                    ~stype+dnum+cname,
                    design = dclus1,
                    svytotal)
    T1 <- Sys.time() - t1
    

    2)使用7个核心与foreach dopar进行并行计算

    # in this option, I create a list with different subsets of the survey design
    # that will be passed to different CPU cores to work at the same time
    
    subdesign <- function(i){ subset(dclus1, dnum==i)}
    groups <- unique(apiclus1$dnum)
    list_subsets <- lapply(groups[], subdesign) # apply function and get all     subsets in a list
    i <- NULL
    
    # Start Parallel
    registerDoParallel(cores=7)
    
    t2 <- Sys.time()
    table2 <- foreach (i = list_subsets,  .combine= rbind, .packages="survey")     %dopar% {
      options( survey.lonely.psu = "remove" )
      svyby(~Vcount,
            ~stype+dnum+cname,
            design = i,
            svytotal)}
    T2 <- Sys.time() - t2
    

    3。选项2

    的编译版本
    # make a function of the previous query
    query2 <- function (list_subsets) { foreach (i = list_subsets,  .combine=     rbind, .packages="survey") %dopar% {
      svyby(~Vcount,
            ~stype+dnum+cname,
            design = i,
            svytotal)}}
    
    # Compile the function to increase speed
    query3 <- cmpfun(query2 )
    
    t3 <- Sys.time()
    table3 <- query3 (list_subsets)
    T3 <- Sys.time() - t3
    

    结果

    >T1: 1.9 secs
    >T2: 1.13 secs
    >T3  0.58 secs
    
    barplot(c(T1, T2, T3),  
            names.arg = c("1) simple table", "2) parallel", "3) compiled parallel"),
            ylab="Seconds")
    

    enter image description here

1 个答案:

答案 0 :(得分:6)

感谢您提出这个问题。在R中使用大型调查数据集高效工作可能需要一些基本的SQL语法(比R更容易学习)。 MonetDB是唯一与survey软件包兼容的大数据选项,探索其他高性能软件包(可能)并不会有成效。通常当我正在探索一个巨大的数据集时,我直接在SQL查询中编写而不是使用调查包,因为标准错误计算是计算密集型的(并且在交互式数据探索期间差异不那么有用)。注意最后的SQL时间戳如何吹走所有其他选项。要计算快速加权平均值,请使用类似"SELECT by_column , SUM( your_column * the_weight ) / SUM( the_weight ) FROM yourdata GROUP BY by_column"

的内容

当您确实需要交互式标准错误时,线性化(svydesign)通常比复制(svrepdesign)更加计算密集,但有时会创建复制设计(就像我使用{{{ 1}}以下)需要比一些用户更熟悉的更多调查方法。

jk1w_dclus1