【问题标题】:R: Creating a matrix with loops/apply (Original code Fortran)R:使用循环/应用创建矩阵(原始代码 Fortran)
【发布时间】:2014-11-14 15:38:29
【问题描述】:

感谢您的帮助,我今天已经为这个问题苦苦挣扎了太久,我希望一双新的眼睛和一组脑细胞可以提供帮助。关于如何使代码更高效的建议也将不胜感激。

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

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

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

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

我使用的示例数据集包含一个 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

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

我一直在翻译这个 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)

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

这是另一个已经翻译过的元素,我想以此为基础进行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
                 }
            }

用对应的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

矩阵 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

提前致谢!

【问题讨论】:

    标签: r for-loop matrix fortran apply


    【解决方案1】:

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

    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

     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

    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

    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

    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]
      }
    }
    

    【讨论】:

    • 非常感谢@cdeterman!有人告诉我,我试图使事情过于复杂,我没有意识到答案会如此简单:)
    猜你喜欢
    • 2014-09-03
    • 1970-01-01
    • 1970-01-01
    • 2021-03-25
    • 2018-05-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-04
    相关资源
    最近更新 更多