Use max on each element of a matrix

10,889

Solution 1

Use pmax:

pmax(x,0)
#     [,1] [,2] [,3] [,4] [,5]
#[1,]    0    0    0    2    6
#[2,]    0    0    0    3    7
#[3,]    0    0    0    4    8
#[4,]    0    0    1    5    9

Solution 2

You can use R's indexing function [ to do this directly:

x <- array(-10:10, dim=c(4,5))
x[x < 0] <- 0

This works because x < 0 creates a logical matrix output:

x < 0

     [,1] [,2]  [,3]  [,4]  [,5]
[1,] TRUE TRUE  TRUE FALSE FALSE
[2,] TRUE TRUE  TRUE FALSE FALSE
[3,] TRUE TRUE FALSE FALSE FALSE
[4,] TRUE TRUE FALSE FALSE FALSE

And the resulting matrix is:

     [,1] [,2] [,3] [,4] [,5]
[1,]    0    0    0    2    6
[2,]    0    0    0    3    7
[3,]    0    0    0    4    8
[4,]    0    0    1    5    9

The timing between the two methods is surprisingly similar. Here's a larger example illustrating the comparable timings:

xbigC <- xbigE <- matrix(sample(-100:100, 1e8, TRUE), ncol = 1e4)
system.time(xbigC[xbigC < 0] <- 0)
 #--- 
  user  system elapsed 
   4.56    0.37    4.93 
system.time(xbigE  <- pmax(xbigE,0))
#---
   user  system elapsed 
   4.10    0.51    4.62 
all.equal(xbigC, xbigE)
#---
[1] TRUE

Solution 3

It appears that the order of the arguments to pmax() affects the class of what is returned when the input is a matrix:

pmax(0,x)
[1] 0 0 0 0 0 0 0 0 0 0 0 1 2 3 4 5 6 7 8 9

pmax(x,0)
     [,1] [,2] [,3] [,4] [,5]
[1,]    0    0    0    2    6
[2,]    0    0    0    3    7
[3,]    0    0    0    4    8
[4,]    0    0    1    5    9
Share:
10,889
ManInMoon
Author by

ManInMoon

Updated on July 28, 2022

Comments

  • ManInMoon
    ManInMoon almost 2 years
    > x <- array(-10:10, dim=c(4,5))
    > x
         [,1] [,2] [,3] [,4] [,5]
    [1,]  -10   -6   -2    2    6
    [2,]   -9   -5   -1    3    7
    [3,]   -8   -4    0    4    8
    [4,]   -7   -3    1    5    9
    

    How do I apply "max(x, 0)" to each element so that I get this matrix:

         [,1] [,2] [,3] [,4] [,5]
    [1,]    0    0    0    2    6
    [2,]    0    0    0    3    7
    [3,]    0    0    0    4    8
    [4,]    0    0    1    5    9
    
  • Chase
    Chase almost 11 years
    @ManInMoon - yep, no worries. The direct indexing approach will be more flexible in that you can create more complicated conditions with other logical operators. For this task, it seems pmax() is ever so slightly more efficient.
  • Tim Kuipers
    Tim Kuipers about 10 years
    This did not work for me. I did > x=read.csv(...) > x2 = sapply(data,atanh) > pmax(x2,-20) but this produced a vector of -20's instead of a matrix of the original dimensions. (Note that > class(x2) [1] "matrix" eventhough > class(x) [1] "data.frame") @Chase his solution did work.
  • eddi
    eddi about 10 years
    @TimKuipers pmax preserves the dim of the object - you're probably leaving out a step or your x2 is not rectangular
  • Tim Kuipers
    Tim Kuipers about 10 years
    Ah no. The mistake I made was that since my matrix was really big, I tried looking at just a part of it by doing x2[1:10] instead of x2[1:10,]. I'm sorry!
  • eddi
    eddi about 10 years
    @TimKuipers np, glad you figured it out