Double For Loop计算平均值并将其存储在矩阵中 [英] Double For Loop to calculate averages and store them in matrix

查看:147
本文介绍了Double For Loop计算平均值并将其存储在矩阵中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我无法运行这个double for循环来正确地将计算值存储到矩阵中(下面将提到)。我之所以选择使用双For循环而不应用()或mean()是因为我想要获得两列的唯一组合,并消除冗余(如下所述)。见下面的例子:

  A< -c(1,2,3,4,5)
B< ; -c(2,3,4,5,6)
Q1< -data.frame(cbind(A,B))
mean< -matrix(nrow = 5,ncol = 5)
for(i in 1:length(Q1 $ A)){
for(j in 2:length(Q1 $ B)){
mean [i,j] <-sum Q1 $ A [i] + Q1 $ B [j])/ 2
}
}

在这里,我试图在整个B向量中运行整个A向量,同时消除冗余,使得A [1]具有来自B [2]的四个值,并且A [2]具有来自B [ 3]。然而,这是我的结果。

  [,1] [,2] [,3] [,4] [,5 ] 
[1,] NA 2.0 2.5 3.0 3.5
[2,] NA 2.5 3.0 3.5 4.0
[3,]不适用3.0 3.5 4.0 4.5
[4, 4.0 4.5 5.0
[5,]不适用4.0 4.5 5.0 5.5

我所期望的,我有我不想要的价值。我想要的是下面的矩阵输出:

pre $ [,1] [,2] [,3] [,4] [,5]
[1,] NA 2.0 2.5 3.0 3.5
[2,]不适用3.0 3.5 4.0
[3,]不适用NA 4.0 4.5
[ ]不适用不适用不适用不适用5.0
[5,]不适用不适用不适用不适用不适用不适用不适用不适用不适用不适用不适用不适用?解决方案<原始解决方案(更快解决方案见更新2)]

(Q1),ncol = nrow(Q1),ncol = nrow(Q1)(nrow = nrow(Q1),ncol = nrow(Q1 ))
b< - 行(z)< col(z)
z [b] < - (Q1 $ A [col(z)[b]] + Q1 $ B [row(z)[b]])/ 2
z
}

[样本输出]

  fm(Q1)
#[,1] [,2] [,3] [,4] [,5]
# [1,] NA 2 2.5 3.0 3.5
#[2,] NA NA 3.0 3.5 4.0
#[3,] NA NA NA 4.0 4.5
#[4,] NA NA NA NA 5.0
#[5,]不适用不适用不适用不适用不适用不适用不适用不适用不适用不适用不适用不适用不适用不适用不适用不适用不适用不适用不适用不适用不适用不适用不适用不适用不适用不适用不适用]

  f0 < - 函数(Q1){
mean< -matrix(nrow = nrow (Q1),ncol = nrow(Q1))
for(i in 1:length(Q1 $ A)){
for(j in 2:length(Q1 $ B)){
表示[i,j] <-sum(Q1 $ A [i] + Q1 $ B [j])/ 2
}
}
表示
}

f1 < - 函数(Q1){
mean <-matrix(nrow = nrow(Q1),ncol = nrow(Q1))
Q1 $ A)){
for(j in i:length(Q1 $ B)){
mean [i,j] <-sum(Q1 $ A [i] + Q1 $ B [ j])/ 2
}
}
mean
}

#请注意,f0()和f1()不会返回样本输出
$所需的结果b $ b f2 < - 函数(Q1){
mean< -outer(1:长度(Q1 $ A),
1:长度(Q1 $ B),
Vectorize (i,j){
if(i> j)
return(NA)
else
return(sum(Q1 $ A [i] + Q1 $ B [ j))/ 2)
}))
mean
}

library(rbenchmark)

[标杆结果]

  A (A,B)

基准(f0(Q1),f1(Q1),f2(Q1),..., fm(Q1),replications = 10)
相对于user.self的测试重复次数sys.self user.child sys.child
4 fm(Q1)10 0.011 1.000 0.012 0.000 0 0
1 f0(Q1)10 3.018 274.364 3.007 0.008 0 0
2 f1(Q1)10 1.477 134.273 1.474 0.003 0 0
3 f2(Q1)10 1.777 161.545 1.774 0.002 0 0

  f.m2 < - 函数(Q1 )外部(Q1 $ A,Q1 $ B,'+')* 0.5 

另一部分基准:

pre $ A <-B <-1:1000
Q1 <-data.frame(A,B )
#benchmark(f0(Q1),f1(Q1),f2(Q1),fm(Q1),复制= 10)
基准(fm(Q1),f.m2(Q1),复制= 10)

相对于user.self的测试复制sys.self user.child sys.child
1 fm(Q1)10 1.839 10.274 1.746 0.093 0 0
2 f .m2(Q1)10 0.179 1.000 0.144 0.035 0 0

[Update 2]



1)正如David Arenburg指出的那样,函数 f.m2()并不能完全产生期望的输出,因为左下三角和主输出的对角线应该用NAs填充。可以固定 f.m2()这个函数,以性能为代价产生正确的答案(见下面的基准测试)。

 #David Arenburg推荐
f.m2.1 < - 函数(Q1){
Res < - outer(Q1 $ A,Q1 $ B, '+')* 0.5;
Res [lower.tri(Res,diag = TRUE)] < - NA;
Res





这是David Arenburg提出的另一种方法,它使用 data.table 包中的 CJ 函数:


$ b (数据表)
f.DA < - 函数(Q1){
Res < - matrix(rowMeans(CJ(Q1 $ A,Q1 $ B)),ncol = nrow(Q1))
Res [lower.tri(Res,diag = TRUE)] < - NA
Res
}



<3>下面是一个 Rcpp / b>

  library(Rcpp)
cppFunction('NumericMatrix fC(NumericVector A,NumericVector B){

int n = A.size();
NumericMatrix out(n,n);
std :: fill(out.begin(),out.end(),NumericVector :: get_na() );
$ b for(int i = 0; i< n; i ++){
for(int j = i + 1; j< n; j ++){
$($,$)
$'
$'
$' / code>

4)另一个基准研究:
(A,B)
基准(f,b,b,b),其中b <

  A <-B <-1:3000 
Q1 < m2(Q1),f.m2.1(Q1),f.DA(Q1),fC(Q1 $ A,Q1 $ B),复制= 10)

已经过相对用户的测试重复。 self sys.self user.child sys.child
3 f.DA(Q1)10 7.442 11.556 6.200 1.209 0 0
2 f.m2.1(Q1)10 5.111 7.936 4.404 0.661 0 0
1 f.m2(Q1)10 1.007 1.564 0.733 0.263 0 0
4 fC(Q1 $ A,Q1 $ B)10 0.644 1.000 0.525 0.116 0 0


I'm having trouble running this double for loop to properly store the calculated values into the matrix (mentioned below). The reason why I elected to use the double For Loop and not apply() or mean() is that I want to obtain the unique combinations of the two columns and eliminate redundancy (explained below). See below for an example:

A<-c(1,2,3,4,5)
B<-c(2,3,4,5,6)
Q1<-data.frame(cbind(A,B))
mean<-matrix(nrow=5, ncol = 5)
for(i in 1: length(Q1$A)){
  for(j in 2: length(Q1$B)){
    mean[i,j]<-sum(Q1$A[i]+Q1$B[j])/2
  }
}

Here, I attempted to run the entire A vector through the entire B vector while eliminating redundancy, such that A[1] has four values from B[2], and A[2] has three values from B[3]. However, this was my result.

     [,1] [,2] [,3] [,4] [,5]
[1,]   NA  2.0  2.5  3.0  3.5
[2,]   NA  2.5  3.0  3.5  4.0
[3,]   NA  3.0  3.5  4.0  4.5
[4,]   NA  3.5  4.0  4.5  5.0
[5,]   NA  4.0  4.5  5.0  5.5

While the first column was what I expected, I have values I didn't want. What I want instead is the below matrix output:

     [,1] [,2] [,3] [,4] [,5]
[1,]   NA  2.0  2.5  3.0  3.5
[2,]   NA   NA  3.0  3.5  4.0
[3,]   NA   NA   NA  4.0  4.5
[4,]   NA   NA   NA   NA  5.0
[5,]   NA   NA   NA   NA   NA

Any suggestions?

解决方案

[Original Solution (see Update 2 for the faster solutions)]

f.m <- function(Q1) {
    z <- matrix(nrow=nrow(Q1),ncol=nrow(Q1))
    b <- row(z) < col(z)
    z[b] <- (Q1$A[col(z)[b]] + Q1$B[row(z)[b]])/2
    z
}

[Sample output]

f.m(Q1)
#      [,1] [,2] [,3] [,4] [,5]
# [1,]   NA    2  2.5  3.0  3.5
# [2,]   NA   NA  3.0  3.5  4.0
# [3,]   NA   NA   NA  4.0  4.5
# [4,]   NA   NA   NA   NA  5.0
# [5,]   NA   NA   NA   NA   NA

[Benchmarking Setup]

f0 <- function(Q1) {
    mean<-matrix(nrow=nrow(Q1), ncol = nrow(Q1))
    for(i in 1: length(Q1$A)){
        for(j in 2: length(Q1$B)){
            mean[i,j]<-sum(Q1$A[i]+Q1$B[j])/2
        }
    }
    mean
}

f1 <- function(Q1) {
    mean<-matrix(nrow=nrow(Q1), ncol = nrow(Q1))
    for(i in 2: length(Q1$A)){
        for(j in i: length(Q1$B)){
            mean[i,j]<-sum(Q1$A[i]+Q1$B[j])/2
        }
    }
    mean
} 

# Note that f0() and f1() don't return the desired result for the sample output

f2 <- function(Q1) {
    mean<-outer(1: length(Q1$A), 
                1: length(Q1$B),
                Vectorize(function(i,j){
                    if(i >= j)
                        return(NA)
                    else 
                        return(sum(Q1$A[i]+Q1$B[j])/2)
                }))
    mean
}

library(rbenchmark)

[Benchmarking Result]

A <- B <- 1:100
Q1<-data.frame(A,B)

benchmark(f0(Q1), f1(Q1), f2(Q1), f.m(Q1), replications = 10)
     test replications elapsed relative user.self sys.self user.child sys.child
4 f.m(Q1)           10   0.011    1.000     0.012    0.000          0         0
1  f0(Q1)           10   3.018  274.364     3.007    0.008          0         0
2  f1(Q1)           10   1.477  134.273     1.474    0.003          0         0
3  f2(Q1)           10   1.777  161.545     1.774    0.002          0         0

[Update 1]

Another order of running time could be saved by direct calculation of the entire matrix, which avoids messing with costly (comparing to summation) subsetting:

f.m2 <- function(Q1) outer(Q1$A,Q1$B,'+')*0.5

Another portion of benchmarking:

A <- B <- 1:1000
Q1<-data.frame(A,B)
#benchmark(f0(Q1), f1(Q1), f2(Q1), f.m(Q1), replications = 10)
benchmark(f.m(Q1), f.m2(Q1), replications = 10)

      test replications elapsed relative user.self sys.self user.child sys.child
1  f.m(Q1)           10   1.839   10.274     1.746    0.093          0         0
2 f.m2(Q1)           10   0.179    1.000     0.144    0.035          0         0

[Update 2]

1) As noted by David Arenburg, function f.m2() does not produce exactly the expected output, because lower left triangle and main diagonal of the output should be filled with NAs. The function f.m2() can be fixed to produce the proper answer at the cost of performance (see benchmarking below).

# Suggested by David Arenburg
f.m2.1 <- function(Q1) { 
   Res <- outer(Q1$A,Q1$B,'+')*0.5; 
   Res[lower.tri(Res, diag = TRUE)] <- NA; 
   Res 
}

2) Here is another approach suggested by David Arenburg, which makes use of the CJ function from the data.table package:

library(data.table)
f.DA <- function(Q1){ 
  Res <- matrix(rowMeans(CJ(Q1$A, Q1$B)), ncol = nrow(Q1))
  Res[lower.tri(Res, diag = TRUE)] <- NA
  Res 
}

3) Here is an Rcpp-based approach:

library(Rcpp)
cppFunction('NumericMatrix fC(NumericVector A, NumericVector B) {

  int n = A.size();
  NumericMatrix out(n,n);
  std::fill( out.begin(), out.end(), NumericVector::get_na() ) ;

  for (int i = 0; i < n; i++) {
    for (int j = i+1; j < n; j++) {
      out(i,j) = 0.5*(A[i] + B[j]);
    }
  }
  return out;
}')

4) And another benchmarking study:

A <- B <- 1:3000
Q1<-data.frame(A,B)
benchmark(f.m2(Q1), f.m2.1(Q1), f.DA(Q1), fC(Q1$A, Q1$B), replications = 10)

            test replications elapsed relative user.self sys.self user.child sys.child
3       f.DA(Q1)           10   7.442   11.556     6.200    1.209          0         0
2     f.m2.1(Q1)           10   5.111    7.936     4.404    0.661          0         0
1       f.m2(Q1)           10   1.007    1.564     0.733    0.263          0         0
4 fC(Q1$A, Q1$B)           10   0.644    1.000     0.525    0.116          0         0

这篇关于Double For Loop计算平均值并将其存储在矩阵中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆