user9798936
user9798936

Reputation:

how to apply a function item by item in for loop in R

I have a complicated function that works on a matrix row by row. The function returns values that must be used as entries of the matrix rows, row by row. I need to use a for loop to make sure that these values are stored correctly. I cannot apply the function at once using a simple lapply or for loop, as there must be a condition based on the values of each row. Is there a way to run the for loop on each item and store the result in a matrix before moving to the next item? Note that this is different from my other posted question. My last question was on applying a condition on a matrix. However, here, I need to use a function on items and store them in a matrix, row by row.

In a simple way:

Here I have a list of vectors (stored in a list x). I need the for loop to loop over each vector of x before moves to the elements of the second vector. For this case, I create an empty matrix (Mat). Then, I need to apply the square on the first vector of x (i.e, c(1:4)). Then, and before moving to square the next vector of x, if any entries of this row are != 0, then the result is stored in Mat (last row (row 5)), and the loop moves to the second vector. However, if all entries are ==0, then the loop must stop and return me an empty matrix. If the result of the second vector is all ==0, then the loop stores zeros to all rows (except the row 5) of Mat. If not, then the loop moves to the third vector, and so on.

My code gives me an error Error in Mat[k, i] <- res[[i]] : number of items to replace is not a multiple of replacement length In addition: Warning message: In seq_len(k - 1) : first element used of 'length.out' argument

    x <- list(c(1:4), c(2,0,0), c(0,0,0), 0)
res <- list() ## I would like to store the result of squares. 
Mat <- matrix(0,5,5) ## here is the matrix where the result 
d <- 5
for(k in d:2){
for (i in seq_along(k-1)){
  res[[i]] <- x[[i]]^2 ## here I would like to find the result of the first item only before moving to the next one.
  Mat[k,i] <- res[[i]] ## store the result of the vector sas a row (bottom to top)
  if(all(setdiff(Mat[k,i], 0) == 0, na.rm = TRUE)){ ## if the result of the current vector is `0` then, I want to stop. The current row and coming rows set to zero. 
    Mat[k,] <- 0
    break 
  }
}
}

Expected result:

   
 Mat
     [,1] [,2] [,3] [,4] [,5]
[1,]    0    0    0    0    0
[2,]    0    0    0    0    0
[3,]    0    0    0    0    0
[4,]    4    0    0    0    0
[5,]    1    4    9    16    0
        

Upvotes: 2

Views: 85

Answers (1)

ThomasIsCoding
ThomasIsCoding

Reputation: 102770

We can try for loop like this

x <- list(c(1:4), c(2, 0, 0), c(0, 0, 0), 0)
Mat <- matrix(0, 5, 5)
for (k in seq_along(x)) {
    r <- x[[k]]^2
    if (any(r != 0)) {
        Mat[nrow(Mat) - k + 1, seq_along(r)] <- r
    } else {
        break
    }
}

which gives

> Mat
     [,1] [,2] [,3] [,4] [,5]
[1,]    0    0    0    0    0
[2,]    0    0    0    0    0
[3,]    0    0    0    0    0
[4,]    4    0    0    0    0
[5,]    1    4    9   16    0

Upvotes: 0

Related Questions