r - 在 R 中使用多个条件对分类数据进行子集化的快速方法

标签 r performance dplyr subset

我在 R 中有一个大型数据集(例如 >40,000 行和 >20 个分类列),我反复对其进行子集化,因此我想尽可能加快速度。它需要是一个通用函数(每个分类列都有离散数量的可能值,例如字符串格式)。

每次子集化时,我都需要识别满足多个逻辑集成员资格条件(例如 >10 个条件)的行子集。即,我需要检查几列并检查该列中的值是否与某个集合成员资格匹配(因此使用 %in% )。

# simple dataset example
library(dplyr)
num_col <- 15
num_row <- 100000
dat_list <- list()
for (i in 1:num_col) {
  dat_list[[i]] <- data_frame(sample(letters[1:10], size = num_row, r = T))
}
dat <- bind_cols(dat_list)
names(dat) <- paste0("col", seq(15))

我在互联网上浏览了很多,但没有找到我正在寻找的性能讨论。我主要使用 dplyr 进行编码,如果data.table中有明显的性能改进,我们深表歉意。 ;我已经在两者之间尝试了一些简单的基准测试(但没有使用任何 data.table 索引等),并且是否更快并不明显。

我考虑过的示例选项(因为我不太擅长 data.table ,所以我从这里排除了 data.table 选项):

base_filter <- function(dat) {
  for (i in 1:7) {
    col_name <- paste0('col', i)
    dat <- dat[dat[[col_name]] %in% sample(letters[1:10], size = 4), ]
  }
  dat
}
dplyr_filter1 <- function(dat) {
  for (i in 1:7) {
    col_name <- paste0('col', i)
    dat <- filter_(dat,
                   .dots = interp(~ colname %in% vals,
                          colname = as.name(col_name),
                          vals = sample(letters[1:10], size = 4)))
  }
  dat
}
dplyr_filter2 <- function(dat) {
  dots_filter <- list()
  for (i in 1:7) {
    col_name <- paste0('col', i)
    dots_filter[[i]] <- interp(~ colname %in% vals,
                               colname = as.name(col_name),
                               vals = sample(letters[1:10], size = 4))
  }
  filter_(dat, .dots = dots_filter)
}

注意:实际上,在我的真实数据集上,dplyr_filter2实际上效果最快。我也尝试过dtplyr或将我的数据转换为 data.table ,但这似乎比没有慢。
注意:另一方面,在实践中,基本 R 函数的性能优于 dplyr数据行数和列数较少的示例(可能是由于复制速度?)。

因此,我想问一下,在多个(集合成员资格)条件下对分类数据帧进行子集化的一般、最有效的方法是什么。如果可能的话,请解释一下其中的机制?对于较小的数据集,这个答案是否有所不同?取决于复制时间还是搜索时间?

有用的相关链接

最佳答案

了解您不喜欢使用 data.table。下面仅提供一些时间供引用。通过索引,可以更快地执行子集设置,并且也可以在 data.table 中轻松完成 2 个表的内部联接。

# simple dataset example
library(dplyr)
library(lazyeval)
set.seed(0L)
num_col <- 15
num_row <- 100000
dat_list <- list()
for (i in 1:num_col) {
    dat_list[[i]] <- data_frame(sample(letters[1:10], size = num_row, r = T))
}
dat <- bind_cols(dat_list)
names(dat) <- paste0("col", seq(15))

selection <- lapply(1:7, function(n) sample(letters[1:10], size = 4))

base_filter <- function(df) {
    for (i in 1:7) {
        col_name <- paste0('col', i)
        df <- df[df[[col_name]] %in% selection[[i]], ]
    }
    df
}

dplyr_filter1 <- function(df) {
    for (i in 1:7) {
        col_name <- paste0('col', i)
        df <- filter_(df,
            .dots = interp(~ colname %in% vals,
                colname = as.name(col_name),
                vals = selection[[i]]))
    }
    df
}

dplyr_filter2 <- function(df) {
    dots_filter <- list()
    for (i in 1:7) {
        col_name <- paste0('col', i)
        dots_filter[[i]] <- interp(~ colname %in% vals,
            colname = as.name(col_name),
            vals = selection[[i]])
    }
    filter_(df, .dots = dots_filter)
}


library(data.table)

#convert data.frame into data.table
dt <- data.table(dat, key=names(dat)[1:7])

#create the sets of selection
dtSelection <- data.table(expand.grid(selection, stringsAsFactors=FALSE))


library(microbenchmark)
microbenchmark(
    base_filter(dat),
    dplyr_filter1(dat),
    dplyr_filter2(dat),
    dt[dtSelection, nomatch=0],   #perform inner join between dataset and selection
    times=5L)

#Unit: milliseconds
#                         expr       min        lq      mean    median        uq       max neval
#             base_filter(dat) 27.084801 27.870702 35.849261 32.045900 32.872601 59.372301     5
#           dplyr_filter1(dat) 23.130100 24.114301 26.922081 24.860701 29.804301 32.701002     5
#           dplyr_filter2(dat) 29.641101 30.686002 32.363681 31.103000 31.884701 38.503601     5
# dt[dtSelection, nomatch = 0]  3.626001  3.646201  3.829341  3.686601  3.687001  4.500901     5

关于r - 在 R 中使用多个条件对分类数据进行子集化的快速方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43622952/

相关文章:

r - 在 Shiny 中动态添加模块

r - 在 R 中使用 ggmap 在 get_map 中出错

function - 如何消除R函数中参数周围的引号?

java - Java 与 C++ 中的基元数组

performance - JBoss CPU利用率问题

r - 使用 R 中的 dplyr 计算和汇总表中的总距离

r - 从每个元素 dplyr 中减去平均值

r - 使用与 R 数据框中多个时间序列的最新日期相对应的值创建条形图

具有 HTTPS 和位置请求的 Android 后台服务

r - 分组矩阵相关