[R] matrix values linked to vector index
Bert Gunter
gunter.berton at gene.com
Sat Oct 12 17:37:19 CEST 2013
This seems to do it, but as I mentioned in my original post, my
"solution" was tricky. Thinking about it some more, I now realize that
it was too tricky and has the additional flaw of using underlying
representations of objects rather than their exposed interfaces -- i.e
it treats a matrix as a vector.
Here is, I think, a much better solution that treats a matrix as a
matrix by making use of a not-often-enough-used technique (mea culpa!)
of matrix indexing. It obviously needs to be cleaned up to check
inputs, etc. , but I think it should work. Feel free to publish and
clean up bugs.
makemx <- function(x,n)
{
out <- matrix(0, nr=length(x), nc=n)
ix <- cbind(rep(seq_along(x),x),unlist(sapply(x,seq_len)))
out[ix]<- 1
out
}
> makemx(c(3,2,1,4),4)
[,1] [,2] [,3] [,4]
[1,] 1 1 1 0
[2,] 1 1 0 0
[3,] 1 0 0 0
[4,] 1 1 1 1
> makemx(c(3,2,1,4),5)
[,1] [,2] [,3] [,4] [,5]
[1,] 1 1 1 0 0
[2,] 1 1 0 0 0
[3,] 1 0 0 0 0
[4,] 1 1 1 1 0
Cheers,
Bert
On Sat, Oct 12, 2013 at 1:02 AM, arun <smartpink111 at yahoo.com> wrote:
>
>
> Modified Bert's solution for non-square matrices. For the tested vectors, it worked. There, could still be some bugs.
>
> x1<- c(3,2,1,4)
> x2<- c(2,0,4,3,1)
> x3 <- c(2, 1, 2.2)
> x4 <- c("a",1,3)
>
> makeMat3 <- function(x,n){
> if(is.numeric(x)){
> x <- as.integer(round(x))
> x}
> stopifnot(is.integer(x))
> indx<-rep(rep(c(1,0),n),c(as.vector(rbind(x,n-x)),rep(c(0,n),n-length(x))))
> matrix(indx[seq_len(length(indx)-(n*(n-length(x))))],nc=n,byr=TRUE)
> }
> makeMat3(x1,4)
> makeMat3(x1,5)
> makeMat3(x1,6)
> makeMat3(x1,7)
>
>
> makeMat3(x2,7)
> makeMat3(x2,6)
> makeMat3(x2,4) # as length of vector > n
> #Error in rep(c(0, n), n - length(x)) : invalid 'times' argument
>
> makeMat3(x3,4)
> makeMat3(x3,5)
>
> makeMat3(x4,4)
> #Error: is.integer(x) is not TRUE
>
> makeMat3(c(4,0,1,0,6),6)
>
> A.K.
>
>
>
> On Saturday, October 12, 2013 1:40 AM, Bert Gunter <gunter.berton at gene.com> wrote:
> Your examples are the problem:
>
> On Fri, Oct 11, 2013 at 2:43 PM, arun <smartpink111 at yahoo.com> wrote:
>> Seems like a bug in the code:
>> x<- c(3,4,1)
>> n<- 3
>> matrix(rep(rep(c(1,0),n),rbind(x,n-x)),nc=n,byr=TRUE)
>> #Error in rep(rep(c(1, 0), n), rbind(x, n - x)) : invalid 'times' argument
>
> ## This can't work since x specifies 4 1's in the second row but you
> have specified a 3 column matrix with n.
>
>> n<- 4
>> matrix(rep(rep(c(1,0),n),rbind(x,n-x)),nc=n,byr=TRUE)
>> #Error in rep(rep(c(1, 0), n), rbind(x, n - x)) : invalid 'times' argument
>
> Yes, this shows that my claim that non-square matrices also work is
> false. I leave it as an exercise to fix it so that it works for
> non-square matrices.
>
> Cheers,
> Bert
>
>
>
>> x2
>> [1] 2 0 4 3 1
>>> matrix(rep(rep(c(1,0),n),rbind(x2,n-x2)),nc=n,byr=TRUE)
>> Error in rep(rep(c(1, 0), n), rbind(x2, n - x2)) :
>> invalid 'times' argument
>>
>>
>> A.K.
>>
>>
>>
>>
>> On Friday, October 11, 2013 5:17 PM, Bert Gunter <gunter.berton at gene.com> wrote:
>> simpler (and sloppier) but with **no looping or apply's **
>>
>> **IFF* the matrix is structured as in the OP's example, then lower.tri
>> (or upper.tri) should be used:
>>
>> n <- 4 ## number of columns in matrix -- note that I changed it from
>> the example; does not have to be square
>>
>> x <- 1:3 ## the number of 1's per row
>> lower.tri(matrix(0,nr=length(x),nc=n),diagA=TRUE)+0
>>
>> A general, fast, but **tricky** way to do it that depends on knowing
>> that a matrix is just a vector in column major order is to generate
>> the vector using rep and then structure it as a matrix. eg.
>>
>> x <- c(3,2,1,4) ## your vector of indices
>> n <- 4 ## number of columns in matrix ## does not have to be square
>> matrix(rep(rep(c(1,0),n),rbind(x,n-x)),nc=n,byr=TRUE)
>>
>> [,1] [,2] [,3] [,4]
>> [1,] 1 1 1 0
>> [2,] 1 1 0 0
>> [3,] 1 0 0 0
>> [4,] 1 1 1 1
>>
>>
>> Cheers,
>> Bert
>>
>> On Fri, Oct 11, 2013 at 1:41 PM, Dennis Murphy <djmuser at gmail.com> wrote:
>>> Attempting to follow the OP's conditions and assuming I understood
>>> them correctly, here is one way to wrap this up into a function:
>>>
>>> makeMat <- function(x)
>>> {
>>> stopifnot(is.integer(x))
>>> nr <- length(x)
>>> nc <- max(x)
>>>
>>> # Initialize a matrix of zeros
>>> m <- matrix(0, nr, nc)
>>> # Conditionally replace with ones
>>> for(i in seq_len(nr)) if(x[i] != 0) m[i, 1:x[i]] <- 1
>>> m
>>> }
>>>
>>> ## Examples:
>>> x1 <- 1:3
>>> x2 <- as.integer(c(2, 0, 4, 3, 1))
>>> x3 <- c(2, 1, 2.2)
>>>
>>> makeMat(x1)
>>> makeMat(x2)
>>> makeMat(x3)
>>> makeMat(4:6)
>>>
>>>
>>> On Fri, Oct 11, 2013 at 9:49 AM, arun <smartpink111 at yahoo.com> wrote:
>>>> Hi,
>>>>
>>>> In the example you showed:
>>>>
>>>> m1<- matrix(0,length(vec),max(vec))
>>>> 1*!upper.tri(m1)
>>>>
>>>> #or
>>>> m1[!upper.tri(m1)] <- rep(rep(1,length(vec)),vec)
>>>>
>>>> #But, in a case like below, perhaps:
>>>> vec1<- c(3,4,5)
>>>>
>>>> m2<- matrix(0,length(vec1),max(vec1))
>>>> indx <- cbind(rep(seq_along(vec1),vec1),unlist(tapply(vec1,list(vec1),FUN=seq),use.names=FALSE))
>>>> m2[indx]<- 1
>>>> m2
>>>> # [,1] [,2] [,3] [,4] [,5]
>>>> #[1,] 1 1 1 0 0
>>>> #[2,] 1 1 1 1 0
>>>> #[3,] 1 1 1 1 1
>>>>
>>>>
>>>>
>>>>
>>>> A.K.
>>>>
>>>>
>>>> Hi-
>>>>
>>>> I'd like to create a matrix of 0's and 1's where the number of
>>>> 1's in each row defined by the value indexed in another vector, and
>>>> where the (value-1) is back-filled by 0's.
>>>>
>>>> For example, given the following vector:
>>>> vec= c(1,2,3)
>>>>
>>>> I'd like to produce a matrix with dimensions (length(vec), max(vec)):
>>>>
>>>> 1,0,0
>>>> 1,1,0
>>>> 1,1,1
>>>>
>>>> Thank you!
>>>>
>>>> ______________________________________________
>>>> R-help at r-project.org mailing list
>>>> https://stat.ethz.ch/mailman/listinfo/r-help
>>>> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
>>>> and provide commented, minimal, self-contained, reproducible code.
>>
>>>
>>> ______________________________________________
>>> R-help at r-project.org mailing list
>>> https://stat.ethz.ch/mailman/listinfo/r-help
>>> PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
>>> and provide commented, minimal, self-contained, reproducible code.
>>
>>
>>
>> --
>>
>> Bert Gunter
>> Genentech Nonclinical Biostatistics
>>
>> (650) 467-7374
>
>>
>
>
>
> --
>
> Bert Gunter
> Genentech Nonclinical Biostatistics
>
> (650) 467-7374
>
--
Bert Gunter
Genentech Nonclinical Biostatistics
(650) 467-7374
More information about the R-help
mailing list