user805950
user805950

Reputation: 31

How to store results in a matrix with a loop function in R

I have been trying to create a vector or a matrix with a loop, but instead, it just creates a variable with the value of the last loop.

I have a 100x2 tableX and a 10x2 tableY. I need to multiply each row from table1 by rows in table2 and store the results in a matrix. (X[1,1]*Y[1,1]+X[1,2]*Y[1,2] and so on)

So in the end I need a 100x10 matrix that would contain the multiplications.

I manage to create the following loop just for the first row from tableY, so it prints the first vector of the resulting table that I need.

for (i in seq(1,100))) {
    results <- ((tableX[i,1]* tableY[1,1])+(tableX[i,2]* tableY[1,2]))
    print(results)
} 

My question is, how do I store this printout as a vector, and then do the same of other rows of tableY?

Thank you in advance!

Upvotes: 3

Views: 2462

Answers (4)

Sathish
Sathish

Reputation: 12703

Here is one way to do it:

Data:

x <- matrix(1:20, nrow = 10)
y <- matrix(1:6, nrow = 3)

Code:

method-1: (RECOMMENDED)

dimensions:

  • x = 10 by 2

  • t(y) = 2 by 3

  • x*t(y) = 10 by 3

    # dot product of x and transpose of y
    x %*% t(y)
    
    #      [,1] [,2] [,3]
    # [1,]   45   57   69
    # [2,]   50   64   78
    # [3,]   55   71   87
    # [4,]   60   78   96
    # [5,]   65   85  105
    # [6,]   70   92  114
    # [7,]   75   99  123
    # [8,]   80  106  132
    # [9,]   85  113  141
    # [10,]   90  120  150
    

method-2

y <- t(y)
apply(x, 1, function(m) colSums(m*y))
#      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
# [1,]   45   50   55   60   65   70   75   80   85    90
# [2,]   57   64   71   78   85   92   99  106  113   120
# [3,]   69   78   87   96  105  114  123  132  141   150

to convert to vector:

c(apply(x, 1, function(m) colSums(m*t(y))))   

method:3

rowSums(matrix( c(apply(expand.grid(x[,1],y[,1]), 1, prod), 
                  apply(expand.grid(x[,2],y[,2]), 1, prod)), 
                ncol = 2))

# [1]  45  50  55  60  65  70  75  80  85  90  57  64  71  78  85  92
# [17]  99 106 113 120  69  78  87  96 105 114 123 132 141 150

Upvotes: 3

akrun
akrun

Reputation: 886998

Here is another option with outer in base R

c(Reduce(`+`, Map(function(u, v) outer(u, v), asplit(x, 2), asplit(y, 2))))

#[1]  45  50  55  60  65  70  75  80  85  90  
#[11] 57  64  71  78  85  92  99 106 113 120  
#[21] 69  78  87  96 105 114 123 132 141 150

data

x <- matrix(1:20, nrow = 10)
y <- matrix(1:6, nrow = 3)

Upvotes: 2

DanY
DanY

Reputation: 6073

You need something with a [i] index on the left-hand side of your assignment. The general structure is something like this, assuming 100 iterations through the loop:

# initialize an empty object (here a vector) to store results
results <- rep(NA, 100)

# loop and store results
for (i in seq(100)) {
   <do some calcs>
   results[i] <- <value to save>
}

Then the object results will have the saved values from each iteration of the loop.

If you are storing more than 1 value each time through the loop, you could save your results in a matrix or list. For a list, the loop is basically the same, and you could initialize the empty list object as:

results <- vector(mode="list", length=100)

Upvotes: 1

Josh
Josh

Reputation: 321

Try setting up your result matrix with empty values before hand, to initialize it then use the indexing of the loop to fill it.

If your vector will always be the same length then you can change your results line to this: The length(vector) is obviously replaced with the number of columns you expect.

results[i,1:length(vector)] <- ((tableX[i,1]* tableY[1,1])+(tableX[i,2]* tableY[1,2]))

I'm not sure this answers your full questions, it sounds like you want to loop over two values. Do you have example tables to simplify the question?

Upvotes: 1

Related Questions