【问题标题】:How to speed up row-wise computations on a data.frame using alternative functions to apply family?如何使用替代函数来加快对 data.frame 的逐行计算以应用族?
【发布时间】:2021-11-05 15:25:43
【问题描述】:

我有一个包含 10,000 行和 40 列的数据框。我正在尝试对这些行中的每一行应用一个函数。对于每一行,我期望返回一个标量,它是我在这个函数中计算的统计数据的值。以下是我到目前为止所做的;

library(dfadjust)
library(MASS)

# Creating example data #

nrows=10000
ncols=40
n1=20
n2=20
df=data.frame(t(replicate(nrows, rnorm(ncols, 100, 3))))
cov=data.frame(group=as.factor(rep(c(1,2),c(n1,n2))))

# Function to evaluate on each row of df #

get_est= function(x){
mod = rlm(x~cov$group)
fit = dfadjustSE(mod)
coef = fit$coefficients[2,1]
se = fit$coefficients[2,4]
stats = coef/se
return(stats)
}

# Applying above function to full data #

t1=Sys.time()
estimates=apply(df, 1, function(x) get_est(x))
t2=Sys.time()-t1

# Time taken by apply function

Time difference of 37.10623 secs

有没有办法显着减少对完整数据实施 get_est() 的时间?我需要在单个 df 上加快计算速度的主要原因是因为我还有 1000 个具有相同维度的数据帧,并且我必须将此函数同时应用于每个数据帧的每一行。为了说明,下面是我正在处理的更广泛的情况;

# Creating example data

set.seed(1234)
nrows = 10000
ncols = 40
n1 = 20
n2 = 20
df.list = list()
for(i in 1:1000){
  df.list[[i]] = data.frame(t(replicate(nrows, rnorm(ncols, 100, 3))))
}

# Applying get_est() to each row and to each of data frame in df.list #

pcks = c('MASS','dfadjust')
all.est = foreach(j = 1:length(df.list), .combine = cbind, .packages = pcks) %dopar% {
  cov=data.frame(group=as.factor(rep(c(1,2),c(n1,n2))))
  est = apply(df.list[[j]], 1, function(x) get_est(x))
  return(est)
}

即使在并行化之后也需要数小时才能完成。我的最终目标是显着缩短获取“all.est”的时间,该“all.est”将包含 10000 行和 1000 列,其中每列都有相应数据集的统计估计值。任何帮助深表感谢!!提前致谢!

【问题讨论】:

  • 使用data.table 可能是替代和/或并行计算。
  • @user2554330 我也尝试使用矩阵对象,但在使用应用时并没有减少太多时间。你有证据证明我的 MWE 使用矩阵更快吗?如果是这样,请您发布该答案。
  • @MartinGal 到目前为止,我还尝试了并行计算(在我的 MWE 中)、data.table 和 dplyr 的 rowwise 函数,但发现没有太大改进。如果您发现使用 data.table 有任何改进,您可以发布该答案吗?

标签: r dataframe performance statistics apply


【解决方案1】:

对数据进行一些预处理,我们可以调整rlm 函数,从而减少开销:

x3 <- as.matrix(cbind(1L, y))
colnames(x3) <- c('(Intercept)', 'x')
w = rep(1, nrow(x3))

get_est= function(x){
  mod = rlm(x3, x, weights = w, w = w)
  fit = dfadjustSE(mod)
  coef = fit$coefficients[2,1]
  se = fit$coefficients[2,4]
  stats = coef/se
  return(stats)
}

我有 12 秒而不是 18 秒的初始接近时间。约 33% 的改进

对于更大的加速,我建议研究 rlmdfadjustSE 函数并尝试根据您的特定需求优化它们(删除不必要的检查等,因为您正在调用这些函数数百万次)。但这可能会非常耗时,并且不能保证更好的性能。也许还有其他具有类似但更快功能的软件包?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-10-31
    • 1970-01-01
    • 2017-12-06
    • 2016-02-07
    • 2017-03-24
    • 2021-01-10
    • 2020-12-16
    • 2016-01-22
    相关资源
    最近更新 更多