R:使用循环/应用创建矩阵(原始代码Fortran)

时间:2022-12-25 21:42:31

Any help appreciated, I have been struggling with this problem far too long today, and I hope a fresh pair of eyes and set of braincells can help. Suggestions on how to make the code more efficient will also be greatly appreciated.

任何帮助表示赞赏,今天我一直在努力解决这个问题太久了,我希望一副新鲜的眼睛和一套braincells可以提供帮助。关于如何提高代码效率的建议也将不胜感激。

I am in the process of rewriting a program from Fortran into R. The eventual matrix, once all the data comes in, will be bigger that 1000x1000.

我正在将一个程序从Fortran重写为R.最终的矩阵,一旦所有数据进入,将大于1000x1000。

The first element of the code looked like this:

代码的第一个元素如下所示:

allocate (S(nrecords))
do i=1,nrecords
    S(i)=ZZ(i,i)
  end do

which in R simply became this: S<-diag(ZZ) **nrecords in the example data = 10

在R中简单地变成这样:S <-diag(ZZ)** nrecords in example data = 10

The example dataset I am using consists of a 10x10 matrix ZZ:

我使用的示例数据集包含一个10x10矩阵ZZ:

167315  136626  138035  150376  137080  136561  139467  137161  151010  140947
136626  171188  139660  138286  138161  138709  139713  138422  138138  140265
138035  139660  170362  138202  138643  138168  140629  139121  137675  139288
150376  138286  138202  167354  138025  138029  140168  137797  144110  139955
137080  138161  138643  138025  168606  144637  140715  138636  142043  141936
136561  138709  138168  138029  144637  167756  140256  138348  140914  152011
139467  139713  140629  140168  140715  140256  172119  141704  140553  140769
137161  138422  139121  137797  138636  138348  141704  169635  137902  138752
151010  138138  137675  144110  142043  140914  140553  137902  169823  142444
140947  140265  139288  139955  141936  152011  140769  138752  142444  173183

so S is a vector containing the diagonal values.

所以S是包含对角线值的向量。

I am stuck in translating this Fortran element though:

我仍然坚持翻译这个Fortran元素:

 allocate(D(nrecords,nrecords))
  sumD=0
do i=1,nrecords
   do j=1,nrecords
    D(i,j)=S(i)+S(j)-2*ZZ(i,j)
    sumD=sumD+D(i,j)
   end do
end do

       deallocate(ZZ)
sumD=sumD/(nrecords*nrecords)

I know that at the end of the day I am supposed to end up with another 10x10 matrix, where D1,1 will equal to 0, and D1,2 will be 65251. But between reading-up on for-loops, apply(), sapply() and tapply() I am rather lost and confused.

我知道在一天结束时我应该得到另一个10x10矩阵,其中D1,1将等于0,而D1,2将是65251.但是在读取for循环之间,应用() ,sapply()和tapply()我很迷茫和困惑。

This is another element that has already been translated, and I wanted to base the fortran translation on this, but I think I have been staring at it too long, and I strongly suspect that there is a more efficient answer:

这是另一个已被翻译过的元素,我想在此基础上进行Fortran翻译,但我认为我已经盯着它看了太久,我强烈怀疑有一个更有效的答案:

n <-6


sumA <- 0
for (i in 1:n) {
   for (j in 1:n) {
  sumA <- sumA+A[i,j]
              }
            }

sumA2 <- 0
for (i in 1:n) {
   for (j in 1:n) {
  sumA2 <- sumA2+A[i,j]^2
                 }
            }

with the corresponding fortran:

与相应的fortran:

 sumA2=0.0;sumA=0.0
     do i=1,nrecords
      do j=1,nrecords
        if(A(i,j) > 0.0) then
           sumA2=sumA2+(A(i,j)*A(i,j))
           sumA=sumA+A(i,j)
        end if
      end do
    end do



 sumMMA=0.0;sumZZ=0.0
  do i=1,nrecords
   do j=1,nrecords
    sumMMA=sumMMA+(ZZ(i,j)*A(i,j))
   sumZZ=sumZZ+ZZ(i,j)  !this will not work using the sum(ZZ) function
  end do
 end do

Matrix A is simply

矩阵A很简单

1   0   0   0   0   0   0   0   0   0
0   0.75    0   0   0   0   0   0   0   0
0   0   1   0   0   0   0   0   0   0
0   0   0   1   0   0   0   0   0   0
0   0   0   0   1   0   0   0   0   0
0   0   0   0   0   0.5 0   0   0   0
0   0   0   0   0   0   0.75    0   0   0
0   0   0   0   0   0   0   1   0   0
0   0   0   0   0   0   0   0   1   0
0   0   0   0   0   0   0   0   0   1

Thanks in advance!

提前致谢!

1 个解决方案

#1


1  

The purpose of the apply functions is to improve readability. If you don't understand them you don't need to use them. They are more or less wrappers for for loops. In your case, you can almost translate your code verbatim.

应用功能的目的是提高可读性。如果您不理解它们,则不需要使用它们。它们或多或少是for循环的包装器。在您的情况下,您几乎可以逐字翻译您的代码。

R

[R

nrecords <- 10
ZZ <- as.matrix(read.table(header=F, text='
167315  136626  138035  150376  137080  136561  139467  137161  151010  140947
136626  171188  139660  138286  138161  138709  139713  138422  138138  140265
138035  139660  170362  138202  138643  138168  140629  139121  137675  139288
150376  138286  138202  167354  138025  138029  140168  137797  144110  139955
137080  138161  138643  138025  168606  144637  140715  138636  142043  141936
136561  138709  138168  138029  144637  167756  140256  138348  140914  152011
139467  139713  140629  140168  140715  140256  172119  141704  140553  140769
137161  138422  139121  137797  138636  138348  141704  169635  137902  138752
151010  138138  137675  144110  142043  140914  140553  137902  169823  142444
140947  140265  139288  139955  141936  152011  140769  138752  142444  173183
                 '))

S <- diag(ZZ)

Fortran

Fortran语言

 allocate(D(nrecords,nrecords))
  sumD=0
do i=1,nrecords
   do j=1,nrecords
    D(i,j)=S(i)+S(j)-2*ZZ(i,j)
    sumD=sumD+D(i,j)
   end do
end do

       deallocate(ZZ)
sumD=sumD/(nrecords*nrecords)

R

[R

D <- matrix(0, nrecords, nrecords)
sumD = 0
for(i in 1:nrecords){
  for(j in 1:nrecords){
    D[i,j] = S[i] + S[j] - 2*ZZ[i,j]
    sumD = sumD + D[i,j]
  }
}
sumD = sumD/(nrecords*nrecords)

Fortran

Fortran语言

do i=1,nrecords
  do j=1,nrecords
    if(A(i,j) > 0.0) then
       sumA2=sumA2+(A(i,j)*A(i,j))
       sumA=sumA+A(i,j)
    end if
  end do
end do    

sumMMA=0.0;sumZZ=0.0
  do i=1,nrecords
   do j=1,nrecords
    sumMMA=sumMMA+(ZZ(i,j)*A(i,j))
   sumZZ=sumZZ+ZZ(i,j)  !this will not work using the sum(ZZ) function
  end do
 end do

R

[R

A <- matrix(0, nrecords, nrecords)
diag(A) <- c(1,.75,1,1,1,.5,.75,1,1,1)

sumA2 = 0
sumA = 0
for(i in 1:nrecords){
  for(j in 1:nrecords){
    if(A[i,j] > 0){
      sumA2=sumA2+(A[i,j]*A[i,j])
      sumA = sumA+A[i,j]
    }
  }
}

sumMMA=0
sumZZ=0
for(i in 1:nrecords){
  for(j in 1:nrecords){
    sumMMa=sumMMA+(ZZ[i,j]*A[i,j])
    sumZZ=sumZZ+ZZ[i,j]
  }
}

#1


1  

The purpose of the apply functions is to improve readability. If you don't understand them you don't need to use them. They are more or less wrappers for for loops. In your case, you can almost translate your code verbatim.

应用功能的目的是提高可读性。如果您不理解它们,则不需要使用它们。它们或多或少是for循环的包装器。在您的情况下,您几乎可以逐字翻译您的代码。

R

[R

nrecords <- 10
ZZ <- as.matrix(read.table(header=F, text='
167315  136626  138035  150376  137080  136561  139467  137161  151010  140947
136626  171188  139660  138286  138161  138709  139713  138422  138138  140265
138035  139660  170362  138202  138643  138168  140629  139121  137675  139288
150376  138286  138202  167354  138025  138029  140168  137797  144110  139955
137080  138161  138643  138025  168606  144637  140715  138636  142043  141936
136561  138709  138168  138029  144637  167756  140256  138348  140914  152011
139467  139713  140629  140168  140715  140256  172119  141704  140553  140769
137161  138422  139121  137797  138636  138348  141704  169635  137902  138752
151010  138138  137675  144110  142043  140914  140553  137902  169823  142444
140947  140265  139288  139955  141936  152011  140769  138752  142444  173183
                 '))

S <- diag(ZZ)

Fortran

Fortran语言

 allocate(D(nrecords,nrecords))
  sumD=0
do i=1,nrecords
   do j=1,nrecords
    D(i,j)=S(i)+S(j)-2*ZZ(i,j)
    sumD=sumD+D(i,j)
   end do
end do

       deallocate(ZZ)
sumD=sumD/(nrecords*nrecords)

R

[R

D <- matrix(0, nrecords, nrecords)
sumD = 0
for(i in 1:nrecords){
  for(j in 1:nrecords){
    D[i,j] = S[i] + S[j] - 2*ZZ[i,j]
    sumD = sumD + D[i,j]
  }
}
sumD = sumD/(nrecords*nrecords)

Fortran

Fortran语言

do i=1,nrecords
  do j=1,nrecords
    if(A(i,j) > 0.0) then
       sumA2=sumA2+(A(i,j)*A(i,j))
       sumA=sumA+A(i,j)
    end if
  end do
end do    

sumMMA=0.0;sumZZ=0.0
  do i=1,nrecords
   do j=1,nrecords
    sumMMA=sumMMA+(ZZ(i,j)*A(i,j))
   sumZZ=sumZZ+ZZ(i,j)  !this will not work using the sum(ZZ) function
  end do
 end do

R

[R

A <- matrix(0, nrecords, nrecords)
diag(A) <- c(1,.75,1,1,1,.5,.75,1,1,1)

sumA2 = 0
sumA = 0
for(i in 1:nrecords){
  for(j in 1:nrecords){
    if(A[i,j] > 0){
      sumA2=sumA2+(A[i,j]*A[i,j])
      sumA = sumA+A[i,j]
    }
  }
}

sumMMA=0
sumZZ=0
for(i in 1:nrecords){
  for(j in 1:nrecords){
    sumMMa=sumMMA+(ZZ[i,j]*A[i,j])
    sumZZ=sumZZ+ZZ[i,j]
  }
}