【问题标题】:How to create a for loop in R for this peculiar calculation如何在 R 中为这种特殊的计算创建一个 for 循环
【发布时间】:2016-04-28 09:08:24
【问题描述】:

我无法弄清楚这种(显然)简单的操作:

鉴于这两个不同的数据帧 df(A) (nrow=10,ncol=3) 和 df(B) (nrow=3,ncol=3)

df(A)                    df(B)            
col1  col2  col3       col1 col2 col3                   
1      2      4          1  4     5
3      5      7          2  7     7
5      7      6          3  9     8
6      9      5.9          
9      11     8            
4.5   5.5     7.9           
21    6.7    13.6            
3.5   5       6          
6     7.9     1         
67     4      2

我想:

  • 将 df(A) 中各列的值与对应列的 df(B) 的值相乘
  • 然后从每一行开始对三个连续的结果求和。

我举个例子:

A[1,1]*B[1,1] + A[2,1]*B[2,1] + A[3,1]*B[3,1]= 1*1+3*2+5*3= 22 # first expected result 
A[2,1]*B[1,1] + A[3,1]*B[2,1] + A[4,1]*B[3,1]= 3*1+5*2+6*3 = 31 # second expected result
A[3,1]*B[1,1] + A[4,1]*B[2,1] + A[5,1]*B[3,1]= 5*1+6*2+9*3 = 44 # third expected result
 ...
A[8,1]*B[1,1] + A[9,1]*B[2,1] + A[10,1]*B[3,1]= 3.5*1+6*2+67*3 = 216.5 # last expected result

以此类推,从df(A) 的每一列的每个值开始,直到最后一个可能的三元组。

我尝试使用这个for 循环代码:

temp <- rep(NA,3)

my_matrix <- matrix(0,ncol=ncol(A),nrow=nrow(A))

for (i in 1:nrow(A)){
  for (j in 1:3){
    temp(j) <- A[i+j-1,]*B[i+j-1,]
  }
  my_matrix(i) <- sum(temp)
}

但 R 回复

Error in sum(temp) : invalid 'type' (list) of argument

In addition: There were 3 warnings (use warnings() to see them)

> warnings()



1: In 1:dim(A) : numerical expression has 2 elements: only the first used

2: In temp[j] <- A[i + (j - 1), ] * B[i + (j - 1), ] :

  number of items to replace is not a multiple of replacement length

提前谢谢你 最好的

安娜

【问题讨论】:

    标签: r for-loop dataframe


    【解决方案1】:

    在 R 中使用 for 循环很少是正确的选择 - 尤其是在涉及操作数据帧的任务时。 R 提供了大量矢量化函数,可用于完成您可能想要使用循环的大多数事情。虽然你一开始看不到重点(循环的性能优势对于现代计算机上的小型数据集并不十分明显)学习用向量而不是循环来思考将长期帮助你从使用中获得更多这种语言比总是使用循环来尝试用 C 口音说 R。

    例如:完成特定任务的一种方法是使用自定义函数和sapply 一起破解某些东西:

    A <- data.frame(1:10, 2:11, 3:12)
    B <- data.frame(1:3, 4:6, 7:9)
    
    f <- function(i) {
      return(colSums(A[i:(i+2),] * B))
    }
    
    C <- sapply(1:(nrow(A) - 2), f)
    t(C)
    

    样本输出:

    > A
       X1.10 X2.11 X3.12
    1      1     2     3
    2      2     3     4
    3      3     4     5
    4      4     5     6
    5      5     6     7
    6      6     7     8
    7      7     8     9
    8      8     9    10
    9      9    10    11
    10    10    11    12
    > B
      X1.3 X4.6 X7.9
    1    1    4    7
    2    2    5    8
    3    3    6    9
    > t(C)
         X1.10 X2.11 X3.12
    [1,]    14    47    98
    [2,]    20    62   122
    [3,]    26    77   146
    [4,]    32    92   170
    [5,]    38   107   194
    [6,]    44   122   218
    [7,]    50   137   242
    [8,]    56   152   266
    

    如果您是 R 新手,我绝对建议您阅读整个 apply 函数系列 - 它们非常有用。

    【讨论】:

      【解决方案2】:

      作为 user164385 的答案的替代方案,这非常好,您还可以使用以下循环来解决问题(即使它们并不总是最佳的,循环可以使从 R 开始时更容易)。请注意,对于全数字数据,您可以使用矩阵而不是数据框:

      A <- matrix(c(1,2,4,3,5,7,5,7,6,6,9,
                    5.9,9,11,8,4.5,5.5,7.9,
                    21,6.7,13.6,3.5,5,6,6,
                    7.9,1,67,4,2), ncol=3, byrow=T)
      B <- matrix(c(1,4,5,2,7,7,3,9,8), ncol=3, byrow=T)
      
      results <- matrix(nrow=8, ncol=3)
      for(i in 1:(nrow(A)-2)) {
        results[i,] <- colSums(A[i:(i+2),] * B)
      }
      results
            [,1]  [,2]  [,3]
      [1,]  22.0 106.0 117.0
      [2,]  31.0 150.0 124.2
      [3,]  44.0 190.0 135.3
      [4,]  37.5 162.5 148.7
      [5,]  81.0 142.8 204.1
      [6,]  57.0 113.9 182.7
      [7,]  46.0 132.9 118.0
      [8,] 216.5 111.3  53.0
      

      【讨论】:

        猜你喜欢
        • 2016-05-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-06-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多