[R] efficient way to replace a range of numeric with a integer in a matrix

David Winsemius dwinsemius at comcast.net
Tue Aug 12 01:49:33 CEST 2014


On Aug 11, 2014, at 3:27 PM, Jinsong Zhao wrote:

> On 2014/8/11 14:50, William Dunlap wrote:
>> You can use
>>     m[m > 0 & m <= 1.0] <- 1
>>     m[m > 1 ] <- 2
>> or, if you have lots of intervals, something based on findInterval().  E.g.,
>>     m[] <- findInterval(m, c(-Inf, 0, 1, Inf)) - 1
>> 

OR, if you have irregularly spaced intervals or particular values to match to the intervals,  you can use findInterval to define categories and select with "[":

> set.seed(42); m <- matrix( rnorm(100, 10, 5), 10)
> round( m, 2)
       [,1]  [,2]  [,3]  [,4]  [,5]  [,6]  [,7]  [,8]  [,9] [,10]
 [1,] 16.85 16.52  8.47 12.28 11.03 11.61  8.16  4.78 17.56 16.96
 [2,]  7.18 21.43  1.09 13.52  8.19  6.08 10.93  9.55 11.29  7.62
 [3,] 11.82  3.06  9.14 15.18 13.79 17.88 12.91 13.12 10.44 13.25
 [4,] 13.16  8.61 16.07  6.96  6.37 13.21 17.00  5.23  9.40 16.96
 [5,] 12.02  9.33 19.48 12.52  3.16 10.45  6.36  7.29  4.03  4.45
 [6,]  9.47 13.18  7.85  1.41 12.16 11.38 16.51 12.90 13.06  5.70
 [7,] 17.56  8.58  8.71  6.08  5.94 13.40 11.68 13.84  8.91  4.34
 [8,]  9.53 -3.28  1.18  5.75 17.22 10.45 15.19 12.32  9.09  2.70
 [9,] 20.09 -2.20 12.30 -2.07  7.84 -4.97 14.60  5.57 14.67 10.40
[10,]  9.69 16.60  6.80 10.18 13.28 11.42 13.60  4.50 14.11 13.27

> m[] <- c(1,2,4,8,16, 32) [ findInterval(m, c(-Inf, 2, 5, 10, 15, 18, Inf) ) ]
> m
      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
 [1,]   16   16    4    8    8    8    4    2   16    16
 [2,]    4   32    1    8    4    4    8    4    8     4
 [3,]    8    2    4   16    8   16    8    8    8     8
 [4,]    8    4   16    4    4    8   16    4    4    16
 [5,]    8    4   32    8    2    8    4    4    2     2
 [6,]    4    8    4    1    8    8   16    8    8     4
 [7,]   16    4    4    4    4    8    8    8    4     2
 [8,]    4    1    1    4   16    8   16    8    4     2
 [9,]   32    1    8    1    4    1    8    4    8     8
[10,]    4   16    4    8    8    8    8    2    8     8

-- 
David.


>> (What do you want to do with non-positive numbers?)
>> 
>> Bill Dunlap
>> TIBCO Software
>> wdunlap tibco.com
> 
> Thank you very much.
> 
> I think findInterval() is what I want.
> 
> Regards,
> Jinsong
> 
>> 
>> 
>> On Mon, Aug 11, 2014 at 2:40 PM, Jinsong Zhao <jszhao at yeah.net> wrote:
>>> Hi there,
>>> 
>>> I hope to replace a range of numeric in a matrix with a integer. For
>>> example, in the following matrix, I want to use 1 to replace the elements
>>> range from 0.0 to 1.0, and all larger than 1. with 2.
>>> 
>>>> (m <- matrix(runif(16, 0, 2), nrow = 4))
>>>           [,1]       [,2]      [,3]     [,4]
>>> [1,] 0.7115088 0.55370418 0.1586146 1.882931
>>> [2,] 0.9068198 0.38081423 0.9172629 1.713592
>>> [3,] 1.5210150 0.93900649 1.2609942 1.744456
>>> [4,] 0.3779058 0.03130103 0.1893477 1.601181
>>> 
>>> so I want to get something like:
>>> 
>>>      [,1] [,2] [,3] [,4]
>>> [1,]    1    1    1    2
>>> [2,]    1    1    1    2
>>> [3,]    2    1    2    2
>>> [4,]    1    1    1    2
>>> 
>>> I wrote a function to do such thing:
>>> 
>>> fun <- function(x) {
>>>     if (is.na(x)) {
>>>         NA
>>>     } else if (x > 0.0 && x <= 1.0) {
>>>         1
>>>     } else if (x > 1.0) {
>>>         2
>>>     } else {
>>>         x
>>>     }
>>> }
>>> 
>>> Then run it as:
>>> 
>>>> apply(m,2,function(i) sapply(i, fun))
>>> 
>>> However, it seems that this method is not efficient when the dimension is
>>> large, e.g., 5000x5000 matrix.
>>> 
>>> Any suggestions? Thanks in advance!
>>> 
>>> Best regards,
>>> Jinsong

> 

David Winsemius
Alameda, CA, USA



More information about the R-help mailing list