Home > Blockchain >  How to write an apply() function that only applies to odd-numbered columns in r matrix?
How to write an apply() function that only applies to odd-numbered columns in r matrix?

Time:11-15

Suppose we have a "test" matrix that looks like this: (1,2,3, 4,5,6, 7,8,9, 10,11,12) generated by running test <- matrix(1:12, ncol = 4). A simple 3 x 4 (rows x columns) matrix of numbers running from 1 to 12.

Now suppose we'd like to add a value of 1 to each element in each odd-numbered matrix column, so we end up with a matrix of the following values: (2,3,4, 4,5,6, 8,9,10, 10,11,12). How would we use an apply() function to do this?

Note that this is a simplified example. In the more complete code I'm working with, the matrix dynamically expands/contracts based on user inputs so I need an apply() function that counts the actual number of matrix columns, rather than using a fixed assumption of 4 columns per the above example. (And I'm not adding a value of 1 to the elements; I'm running the parallel minima function test[,1] <- pmin(test1[,1], 5) to say limit each value to a max of 5).

With my current limited understanding of the apply() family of functions, all I can so far do is apply(test, 2, function(x) {return(x 1)}) but this is adding a value of 1 to all elements in all columns rather than only the odd-numbered columns.

CodePudding user response:

You may simply subset the input data frame to access only odd or even numbered columns. Consider:

test[c(TRUE, FALSE)] <- apply(test[c(TRUE, FALSE)], 2, function(x) f(x))
test[c(FALSE, TRUE)] <- apply(test[c(FALSE, TRUE)], 2, function(x) f(x))

This works because the recycling rules in R will cause e.g. c(TRUE, FALSE) to be repeated however many times is needed to cover all columns in the input test data frame.

For a matrix, we need to use the drop=FALSE flag when subsetting the matrix in order to keep it in matrix form when using apply():

test <- matrix(1:12, ncol = 4)
test[,c(TRUE, FALSE)] <- apply(test[,c(TRUE, FALSE),drop=FALSE], 2, function(x) x 1)
test

     [,1] [,2] [,3] [,4]
[1,]    2    4    8   10
[2,]    3    5    9   11
[3,]    4    6   10   12
        ^         ^ ... these columns incremented by 1

CodePudding user response:

You may use modulo %% 2.

odd <- !seq(ncol(test)) %% 2 == 0
test[, odd] <- apply(test[, odd], 2, function(x) {return(x   1)}) 
#      [,1] [,2] [,3] [,4]
# [1,]    2    4    8   10
# [2,]    3    5    9   11
# [3,]    4    6   10   12
  • Related