This looks better. My previous solution (makeMatrix2) also did the matrix indexing without using sapply() route. Replacing the max(x) by n for non-symmetric matrix:
makeMatrix2<- function(x,n){ #including "n" if(is.numeric(x)){ x <- as.integer(round(x)) x} stopifnot(is.integer(x)) m1<- matrix(0,length(x),n) #change max(x) to n indx <- cbind(rep(seq_along(x),x),seq_len(sum(x))-rep(cumsum(c(0L,x[-length(x)])),x)) m1[indx]<- 1 m1} identical(makeMatrix2(x3,4),makemx(x3,4)) #[1] TRUE identical(makeMatrix2(x1,5),makemx(x1,5)) #[1] TRUE identical(makeMatrix2(x2,7),makemx(x2,7)) #[1] TRUE A.K. On Saturday, October 12, 2013 11:37 AM, Bert Gunter <gunter.ber...@gene.com> wrote: 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 <smartpink...@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.ber...@gene.com> > wrote: > Your examples are the problem: > > On Fri, Oct 11, 2013 at 2:43 PM, arun <smartpink...@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.ber...@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 <djmu...@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 <smartpink...@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@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@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 ______________________________________________ R-help@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.