【问题标题】:Quicker alternatives to apply function when performing row wise computations on a data frame [duplicate]在数据帧上执行逐行计算时应用函数的更快替代方法[重复]
【发布时间】:2021-10-31 13:57:39
【问题描述】:

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

library(sandwich)

# 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 = lm(x~cov$group)
vcov = vcovHC(mod)
coef = as.numeric(mod$coefficients[2])
se = sqrt(as.numeric(diag(vcov)[2]))
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 32.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 #

all.est = foreach(j = 1:length(df.list), .combine = cbind, .packages = 'sandwich') %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 列,其中每列都有相应数据集的统计估计值。任何帮助深表感谢!!提前致谢!

【问题讨论】:

  • 不是严格的主题,但也许使用 lapply/parlapply(或类似的)而不是 for 循环可以挤出几秒钟的时间。
  • @D.J 是的,可以使用 apply 系列来避免循环。然而,实际上我确实拥有这 1000 个数据集,所以在我的实际代码中我没有运行这个 for 循环。只是在这里创建示例数据集以进行说明。鉴于这 1000 个数据集,我主要关心的是加快“all.est”的计算。

标签: r dataframe function performance apply


【解决方案1】:

它在我的电脑中减半。

library(snowfall)
t1=Sys.time()
sfInit( parallel=TRUE, cpus=2 )

sfExport(list=list('get_est'))
sfLibrary('sandwich', character.only = TRUE)
sfExport('df')
sfExport('cov')


## call function using sfApply; will return values as a list object
out = sfApply(df, 1, function(x) get_est(x))

## stop parallel computing job
sfStop()
Sys.time()-t1

Time difference of 15.29727 secs

【讨论】:

  • 谢谢,sfapply 确实将单个数据帧减少了一半,但是,当我在 foreach 循环中实现它以计算“all.est”时,我的计算机冻结了。也许 sfapply 与 foreach 冲突?
  • @Capri 也许你电脑的 CPU 有 1 或 2 个内核。
  • 不,我刚刚检查过它有 12 个内核。您是否尝试在 foreach 中实现 sfApply 来计算“all.est”?成功了吗?
  • @Capri 哦,对不起。我混淆了all.estget_est。我的电脑也死机了。我会仰望all.est。对不起。
  • 不用担心。谢谢你的帮助!!
猜你喜欢
  • 2013-04-17
  • 1970-01-01
  • 1970-01-01
  • 2021-11-05
  • 1970-01-01
  • 2021-06-23
  • 2017-02-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多