我有两个矩阵,我想做几个统计,我将dataframe1的每一行与dataframe2进行比较。这些是大型数据框架(300,000行和40,000行),因此需要进行比较。
我做了一些函数来应用统计数据。我想知道的是,是否可以将dataframe1拆分成块,并在多个核心上并行运行这些块。
library(lawstat)
library(reshape2)
df1 = matrix(ncol= 100, nrow=100)
for ( i in 1:100){
df1[,i] =floor(runif(100, min = 0, max =3))
}
df2 = matrix(ncol= 100, nrow=1000)
for ( i in 1:100){
df2[,i] =runif(1000, min = 0, max =1000)
}
testFunc<- function(df1, df2){
x=apply(df1, 1, function(x) apply(df2, 1, function(y) levene.test(y,x)$p.value))
x=melt(x)
return(x)
}
system.time(res <- testFunc(df1,df2 ))
一些统计数据(例如levene测试)需要相当长的时间来计算,所以任何我可以加快速度的方法都会很棒。
答案 0 :(得分:2)
您的功能有优化空间,但以下是使用parallel
包进行改进的示例:
library(parallel)
library(snow)
# I have a quad core processor so I am using 3 cores here.
cl <- snow::makeCluster(3)
testFunc2<- function(df1, df2){
x=parallel::parApply(cl = cl, X = df1, 1, function(x, df2) apply(df2, 1,
function(y) lawstat::levene.test(y,x)$p.value), df2)
x=melt(x)
return(x)
}
system.time(res <- testFunc2(df1,df2 ))
在我的机器上,如果群集大小为3,则至少将运行时间减半。
编辑:我觉得你的代码不好,所以下面是一个精简的levene.test函数,可以提高大多数家庭/工作机器上的性能。
lev_lite = function(y, group){
N = 100 # or length(y)
k = 3 # or length(levels(group)) after setting to as.factor below
reorder <- order(group)
group <- group[reorder]
y <- y[reorder]
group <- as.factor(group)
n <- tapply(y,group, FUN = length)
yi_bar <- tapply(y,group, FUN = median)
zij = abs(y - rep(yi_bar, n))
zidot = tapply(zij, group, FUN = mean)
zdotdot = mean(zij)
# test stat, see wiki
W = ((N - k)/(k - 1)) * (
sum(n*(zidot - zdotdot)^2)/
sum((zij - rep(zidot, n))^2))
#p val returned
1 - pf(W, k-1, N-k)
}
testFunc2<- function(df1, df2){
x=apply(df1, 1, function(x) apply(df2, 1, lev_lite, group = x))
x=melt(x)
return(x)
}
> system.time(res <- testFunc(df1[1:50, ],df2[1:50,] ))
user system elapsed
5.53 0.00 5.56
> system.time(res2 <- testFunc2(df1[1:50, ],df2[1:50, ] ))
user system elapsed
1.13 0.00 1.14
> max(res2 - res)
[1] 2.220446e-15
这是没有并行化的约5倍。