0
votes

I have an upgrade of this loop,(my previous post) How to create a for loop in R for this peculiar calculation But, this time i would like to apply the loop for different column. Given these different dataframes df(A) (nrow=10,ncol=5) , df(B) (nrow=3,ncol=2), df(C)(nrow=4, ncol=2), df(D) (nrow=6,ncol=1)

 df(A)                                    df(B)        df(C)         df(D)
col1  col2  col3  col4   col5           col1 col2     col3 col4      col5                 
1      2      4     4      2              1   4         5   4          5
3      5      7     2      1              2   7         7   5          6
5      7      6     6      3              3   9         8   7          1
6      9      5.9   8      6                            8   9          4
9      11     8     4      9                                           8
4.5   5.5     7.9   6      7.3                                        10
21    6.7    13.6   8.7    2     
3.5   5       6     6     6
6     7.9     1     9     7
67     4      2     2     6

I'd like to:

  • multiply each value of the columns in df(A) with those of df(B), df(C) and df(D) of the correspondant column (see te name of the column of df)
  • and than sum three,four or six consecutive results starting from every row.

Let me give you an example:

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[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

and so on starting from each value of the first two column of df(A) (until the last possible triplet), for df(B). Successively, the col3 and col4 of df(A)for col3 and col4 of df(C)summing for the 4 value,until the last 4 added value, like this:

`A[1,3]*C[1,1]+A[2,3]*C[2,1]+A[3,3]*C[3,1]+A[4,3]*C[4,1]= 4*5+7*7+6*8+5.9*8= 164.2 first expected result
A[2,3]*C[1,1]+A[3,3]*C[2,1]+A[4,3]*C[3,1]+A[5,3]*C[4,1]= second expected result
A[7,3]*C[1,1]+A[8,3]*C[2,1]+A[9,3]*C[3,1]+A[10,3]*C[4,1]= last expected result

and so on for the col3 and col4 of df(A) respectively for col 3 and 4 of df(C).

Finally the col5 of df(A) for df(D), until the last 6 possible value that can be added

A[1,5]*D[1,1]+A[2,5]*D[2,1]+A[3,5]*D[3,1]+A[4,5]*D[4,1]+A[5,5]*D[5,1]+A[6,5]*D[6,1]= 2*5+1*6+3*1+6*4+9*8+7.3*10= first result 


A[2,5]*D[1,1]+A[3,5]*D[2,1]+A[4,5]*D[3,1]+A[5,5]*D[4,1]+A[6,5]*D[5,1]+A[7,5]*D[6,1]=  second result       

A[5,5]*D[1,1]+A[6,5]*D[2,1]+A[7,5]*D[3,1]+A[8,5]*D[4,1]+A[9,5]*D[5,1]+A[10,5]*D[6,1]=  last expected result   

The expected result is a data frame with 5 colum, and number of row which depending for which column of df B C and D is multiply fos the respectively column of df(A). For this reason the number of row of the expected df can be equal to the last operation of df(A)col5 for df(C), with 5 total row.

I tried with this for loop code:

for (i in 1:dim(A)[1]){              
  for (j in 1:dim(A)[2]){
    if(j <=2){
      results[i,j] <-colSums(A[i:(i+2),1:2]* B)
    }   

    if(j >=3 & j<=4){
      results[i,j] <- colSums(A[i:(i+3),3:4]* C)
    }

    if(j>4){
      results[i,j] <- colSums(A[i:(i+5),5]* D)
    }
  }
}

but R replies

Error in results[i, j] <- colSums(A[i:(i + 2), 1:2] * B) : 
  number of items to replace is not a multiple of replacement length
1

1 Answers

2
votes

Import your data (please make this easier next time):

A <- read.table(text = "col1  col2  col3  col4   col5                 
1      2      4     4      2            
                3      5      7     2      1            
                5      7      6     6      3             
                6      9      5.9   8      6                        
                9      11     8     4      9                               
                4.5   5.5     7.9   6      7.3                                   
                21    6.7    13.6   8.7    2     
                3.5   5       6     6     6
                6     7.9     1     9     7
                67     4      2     2     6", header = TRUE)

B <- read.table(text = "col1 col2                 
1   4       
2   7         
3   9      ", header = TRUE)

C <- read.table(text = "ccol3 col4              
5   4   
7   5     
 8   7    
8   9 ", header = TRUE) 

D <- read.table(text = "col5                 
5
6
1
4
8
10", header = TRUE)

Combine B, C, D:

filters <- c(B, C, D)

Use filter:

mapply( #loop over corresponding pairs
  stats::filter, #function for linear filter 
  A, #use first, second, ... column of A 
  lapply(filters, rev), #use first, second, ... filter, but reverse them first
  sides = 1 #filter not centered, but for past values
)
#       col1  col2  col3  col4  col5
# [1,]    NA    NA    NA    NA    NA
# [2,]    NA    NA    NA    NA    NA
# [3,]  22.0 106.0    NA    NA    NA
# [4,]  31.0 150.0 164.2 140.0    NA
# [5,]  44.0 190.0 188.2 130.0    NA
# [6,]  37.5 162.5 198.5 146.0 188.0
# [7,]  81.0 142.8 257.5 172.3 143.4
# [8,]  57.0 113.9 252.1 160.9 165.2
# [9,]  46.0 132.9 190.7 190.5 217.3
#[10,] 216.5 111.3 134.0 145.8 230.8