[R] [ifelse] how to maintain a value from original matrix without probs?

Marc Schwartz marc_schwartz at comcast.net
Fri Oct 31 18:09:12 CET 2008


on 10/31/2008 09:59 AM Diogo André Alagador wrote:
> Dear all,
>  
> I have a matrix with positive and negative values.
>>From this I would like to produce 2 matrices:
> 1st - retaining positives and putting NA in other positions
> 2nd - retaining negatives and putting NA in other positions
>  
> and then apply rowMeans for both.
>  
> I am trying to use the function ifelse in the exemplified form:
> ifelse(A>0,A,NA)
> but by putting A as a 2nd parameter it changes dimensions of the original
> object.
>  
> I wonder if I can do this, as it seems not to difficult.
>  
> thanks in advance

A couple of approaches, depending upon the size of the matrix.

The first, if the matrix is "small-ish":

set.seed(1)
mat <- matrix(sample(-10:10, 100, replace = TRUE), ncol = 10)

> mat
      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
 [1,]   -5   -6    9    0    7    0    9   -3   -1    -5
 [2,]   -3   -7   -6    2    3    8   -4    7    4    -9
 [3,]    2    4    3    0    6   -1   -1   -3   -2     3
 [4,]    9   -2   -8   -7    1   -5   -4   -3   -4     8
 [5,]   -6    6   -5    7    1   -9    3    0    5     6
 [6,]    8    0   -2    4    6   -8   -5    8   -6     6
 [7,]    9    5  -10    6  -10   -4    0    8    4    -1
 [8,]    3   10   -2   -8    0    0    6   -2   -8    -2
 [9,]    3   -3    8    5    5    3   -9    6   -5     7
[10,]   -9    6   -3   -2    4   -2    8   10   -7     2


> apply(mat, 1, function(x) mean(x[x > 0], na.rm = TRUE))
 [1] 8.333333 4.800000 3.600000 6.000000 4.666667 6.400000 6.400000
 [8] 6.333333 5.285714 6.000000

> apply(mat, 1, function(x) mean(x[x < 0], na.rm = TRUE))
 [1] -4.000000 -5.800000 -1.750000 -4.714286 -6.666667 -5.250000
 [7] -6.250000 -4.400000 -5.666667 -4.600000


This way, you avoid splitting the matrix. You did not specify how you
might want 0's to be handled, so adjust the logic above accordingly.


If the matrix is large, such that that splitting it and using rowMeans()
would be faster:


mat.pos <- mat
is.na(mat.pos) <- mat <= 0

> mat.pos
      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
 [1,]   NA   NA    9   NA    7   NA    9   NA   NA    NA
 [2,]   NA   NA   NA    2    3    8   NA    7    4    NA
 [3,]    2    4    3   NA    6   NA   NA   NA   NA     3
 [4,]    9   NA   NA   NA    1   NA   NA   NA   NA     8
 [5,]   NA    6   NA    7    1   NA    3   NA    5     6
 [6,]    8   NA   NA    4    6   NA   NA    8   NA     6
 [7,]    9    5   NA    6   NA   NA   NA    8    4    NA
 [8,]    3   10   NA   NA   NA   NA    6   NA   NA    NA
 [9,]    3   NA    8    5    5    3   NA    6   NA     7
[10,]   NA    6   NA   NA    4   NA    8   10   NA     2

> rowMeans(mat.pos, na.rm = TRUE)
 [1] 8.333333 4.800000 3.600000 6.000000 4.666667 6.400000 6.400000
 [8] 6.333333 5.285714 6.000000



mat.neg <- mat
is.na(mat.neg) <- mat >= 0

> mat.neg
      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
 [1,]   -5   -6   NA   NA   NA   NA   NA   -3   -1    -5
 [2,]   -3   -7   -6   NA   NA   NA   -4   NA   NA    -9
 [3,]   NA   NA   NA   NA   NA   -1   -1   -3   -2    NA
 [4,]   NA   -2   -8   -7   NA   -5   -4   -3   -4    NA
 [5,]   -6   NA   -5   NA   NA   -9   NA   NA   NA    NA
 [6,]   NA   NA   -2   NA   NA   -8   -5   NA   -6    NA
 [7,]   NA   NA  -10   NA  -10   -4   NA   NA   NA    -1
 [8,]   NA   NA   -2   -8   NA   NA   NA   -2   -8    -2
 [9,]   NA   -3   NA   NA   NA   NA   -9   NA   -5    NA
[10,]   -9   NA   -3   -2   NA   -2   NA   NA   -7    NA


> rowMeans(mat.neg, na.rm = TRUE)
 [1] -4.000000 -5.800000 -1.750000 -4.714286 -6.666667 -5.250000
 [7] -6.250000 -4.400000 -5.666667 -4.600000



See ?is.na and note the assignment variant.

HTH,

Marc Schwartz



More information about the R-help mailing list