matrix values linked to vector index

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
14 messages Options
Reply | Threaded
Open this post in threaded view
|

matrix values linked to vector index

Karen Davis
This post has NOT been accepted by the mailing list yet.
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!
Reply | Threaded
Open this post in threaded view
|

Re: matrix values linked to vector index

arun kirshna
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!

______________________________________________
[hidden email] 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.
Reply | Threaded
Open this post in threaded view
|

Re: matrix values linked to vector index

djmuseR
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 <[hidden email]> 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!
>
> ______________________________________________
> [hidden email] 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.

______________________________________________
[hidden email] 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.
Reply | Threaded
Open this post in threaded view
|

Re: matrix values linked to vector index

Bert Gunter
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 <[hidden email]> 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 <[hidden email]> 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!
>>
>> ______________________________________________
>> [hidden email] 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.
>
> ______________________________________________
> [hidden email] 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

______________________________________________
[hidden email] 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.
Reply | Threaded
Open this post in threaded view
|

Re: matrix values linked to vector index

arun kirshna
In reply to this post by djmuseR
Thanks Dennis.  I noticed I didn't take the "0" value into consideration and also didn't check the unsorted vector.vec1<- c(2,4,1)


is.numeric(vec1)
#[1] TRUE

makeMat(as.integer(vec1))

makeMatrix2<- function(x){
 if(is.numeric(x)){
x <- as.integer(round(x))
x}
stopifnot(is.integer(x))
m1<- matrix(0,length(x),max(x))
 indx <- cbind(rep(seq_along(x),x),seq_len(sum(x))-rep(cumsum(c(0L,x[-length(x)])),x))
m1[indx]<- 1
m1}


identical(makeMat(x1),makeMatrix2(x1))
#[1] TRUE
 identical(makeMat(x2),makeMatrix2(x2))
#[1] TRUE
 identical(makeMat(x3),makeMatrix2(x3))
#Error: is.integer(x) is not TRUE

makeMatrix2(x3)
#     [,1] [,2]
#[1,]    1    1
#[2,]    1    0
#[3,]    1    1


 identical(makeMat(4:6),makeMatrix2(4:6))
#[1] TRUE

x4 <- c("a",1,3)
identical(makeMat(x4),makeMatrix2(x4))
#Error: is.integer(x) is not TRUE

A.K.










On Friday, October 11, 2013 4:41 PM, Dennis Murphy <[hidden email]> 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 <[hidden email]> 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!
>
> ______________________________________________
> [hidden email] 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.


______________________________________________
[hidden email] 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.
Reply | Threaded
Open this post in threaded view
|

Re: matrix values linked to vector index

arun kirshna
In reply to this post by Bert Gunter
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
 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

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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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!
>>
>> ______________________________________________
>> [hidden email] 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.

>
> ______________________________________________
> [hidden email] 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


______________________________________________
[hidden email] 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.
Reply | Threaded
Open this post in threaded view
|

Re: matrix values linked to vector index

Bert Gunter
Your examples are the problem:

On Fri, Oct 11, 2013 at 2:43 PM, arun <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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!
>>>
>>> ______________________________________________
>>> [hidden email] 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.
>
>>
>> ______________________________________________
>> [hidden email] 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

______________________________________________
[hidden email] 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.
Reply | Threaded
Open this post in threaded view
|

Re: matrix values linked to vector index

arun kirshna


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 <[hidden email]> wrote:
Your examples are the problem:

On Fri, Oct 11, 2013 at 2:43 PM, arun <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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!
>>>
>>> ______________________________________________
>>> [hidden email] 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.
>
>>
>> ______________________________________________
>> [hidden email] 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


______________________________________________
[hidden email] 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.
Reply | Threaded
Open this post in threaded view
|

Re: matrix values linked to vector index

Bert Gunter
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 <[hidden email]> 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 <[hidden email]> wrote:
> Your examples are the problem:
>
> On Fri, Oct 11, 2013 at 2:43 PM, arun <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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!
>>>>
>>>> ______________________________________________
>>>> [hidden email] 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.
>>
>>>
>>> ______________________________________________
>>> [hidden email] 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

______________________________________________
[hidden email] 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.
Reply | Threaded
Open this post in threaded view
|

Re: matrix values linked to vector index

arun kirshna
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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> wrote:
> Your examples are the problem:
>
> On Fri, Oct 11, 2013 at 2:43 PM, arun <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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!
>>>>
>>>> ______________________________________________
>>>> [hidden email] 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.
>>
>>>
>>> ______________________________________________
>>> [hidden email] 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


______________________________________________
[hidden email] 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.
Reply | Threaded
Open this post in threaded view
|

Re: matrix values linked to vector index

arun kirshna
Some speed comparison:


set.seed(124)
 xtest<- sample(0:9,1e7,replace=TRUE)
system.time({res1 <- makemx(xtest,9)})
#   user  system elapsed
# 51.124   0.812  52.039
 system.time({res2 <- makeMatrix2(xtest,9)})
#   user  system elapsed
#  3.460   0.168   3.631


identical(res1,res2)
#[1] TRUE


Also, it looks like there is some bugs still in the "makeMat3"
system.time({res3 <- makeMat3(xtest,9)})
#Error in rep(c(0, n), n - length(x)) : invalid 'times' argument
#Timing stopped at: 0.616 0 0.616


A.K.


On Saturday, October 12, 2013 12:06 PM, arun <[hidden email]> wrote:
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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> wrote:
> Your examples are the problem:
>
> On Fri, Oct 11, 2013 at 2:43 PM, arun <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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!
>>>>
>>>> ______________________________________________
>>>> [hidden email] 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.
>>
>>>
>>> ______________________________________________
>>> [hidden email] 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



______________________________________________
[hidden email] 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.

______________________________________________
[hidden email] 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.
Reply | Threaded
Open this post in threaded view
|

Re: matrix values linked to vector index

arun kirshna





Apologies, in case it is double posting (I think my previous message didn't make it to the list)


Hope the new version of `makeMat3` is bug free:
makeMat3 <- function(x,n){
            if(is.numeric(x)){
x <- as.integer(round(x))
x}
stopifnot(is.integer(x))
if(length(x)>=n & max(x)<=n){
indx<-rep(rep(c(1,0),max(length(x),n)),rbind(x,n-x))

m1<-  matrix(indx,nc=n,byr=TRUE)
}

else if(length(x) < n) {
indx<-rep(rep(c(1,0),n),c(as.vector(rbind(x,n-x)),rep(c(0,n),n-length(x))))
 m1<-matrix(indx[seq_len(length(indx)-(n*(n-length(x))))],nc=n,byr=TRUE)
}
else print(paste("Not possible: Number of columns less than the maximum value of ", max(x), "or length of vector"))
m1
}

 system.time(res3<- makeMat3(xtest,9))
#   user  system elapsed
 # 1.908   0.328   2.237
 identical(res3,res2)
#[1] TRUE

identical(makemx(x3,4),makeMat3(x3,4))
#[1] TRUE
 identical(makemx(x2,5),makeMat3(x2,5))
#[1] TRUE
 identical(makemx(x2,14),makeMat3(x2,14))
#[1] TRUE
 makemx(x2,3)
#Error in out[ix] <- 1 : subscript out of bounds
 makeMat3(x2,3)
#[1] "Not possible: Number of columns less than the maximum value of  4 or length of vector"
#Error in makeMat3(x2, 3) : object 'm1' not found



A.K.




On Saturday, October 12, 2013 12:28 PM, arun <[hidden email]> wrote:
Some speed comparison:


set.seed(124)
 xtest<- sample(0:9,1e7,replace=TRUE)
system.time({res1 <- makemx(xtest,9)})
#   user  system elapsed
# 51.124   0.812  52.039
 system.time({res2 <- makeMatrix2(xtest,9)})
#   user  system elapsed
#  3.460   0.168   3.631


identical(res1,res2)
#[1] TRUE


Also, it looks like there is some bugs still in the "makeMat3"
system.time({res3 <- makeMat3(xtest,9)})
#Error in rep(c(0, n), n - length(x)) : invalid 'times' argument
#Timing stopped at: 0.616 0 0.616


A.K.


On Saturday, October 12, 2013 12:06 PM, arun <[hidden email]> wrote:
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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> wrote:
> Your examples are the problem:
>
> On Fri, Oct 11, 2013 at 2:43 PM, arun <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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 <[hidden email]> 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!
>>>>
>>>> ______________________________________________
>>>> [hidden email] 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.
>>
>>>
>>> ______________________________________________
>>> [hidden email] 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




______________________________________________
[hidden email] 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.

______________________________________________
[hidden email] 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.

______________________________________________
[hidden email] 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.
Reply | Threaded
Open this post in threaded view
|

Re: matrix values linked to vector index

Christoph.H
In reply to this post by arun kirshna
Just a further suggestion:

vec <- c(3,2,5,0,1)

mat <- t(sapply(vec,">=",1:max(vec)))

ifelse(mat,1,0)


Cheers,
Christoph

2013/10/11 arun <[hidden email]>:

> 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!
>
> ______________________________________________
> [hidden email] 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.

______________________________________________
[hidden email] 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.
Reply | Threaded
Open this post in threaded view
|

Re: matrix values linked to vector index

arun kirshna
Also:
mat+0
#or


mat*1

#However, sapply() based solutions would be slower in large matrices.

#Speed
makeMat3 <- function(x,n){
            if(is.numeric(x)){
x <- as.integer(round(x))
x}
stopifnot(is.integer(x))
if(length(x)>=n & max(x)<=n){
indx<-rep(rep(c(1,0),max(length(x),n)),rbind(x,n-x))

m1<-  matrix(indx,nc=n,byr=TRUE)
}

else if(length(x) < n) {
indx<-rep(rep(c(1,0),n),c(as.vector(rbind(x,n-x)),rep(c(0,n),n-length(x))))
 m1<-matrix(indx[seq_len(length(indx)-(n*(n-length(x))))],nc=n,byr=TRUE)
}
else print(paste("Not possible: Number of columns less than the maximum value of ", max(x), "or length of vector"))
m1
}

set.seed(124)
  xtest<- sample(0:9,1e7,replace=TRUE)
 system.time(res3<- makeMat3(xtest,9))
#   user  system elapsed
 # 2.000   0.528   2.533
 system.time({res4<- t(sapply(xtest,">=",1:max(xtest)))
 res4<- res4*1})
#   user  system elapsed
# 42.648   0.728  43.461
identical(res3,res4)
#[1] TRUE

A.K.


On Sunday, October 13, 2013 3:55 AM, Christoph Häni <[hidden email]> wrote:
Just a further suggestion:

vec <- c(3,2,5,0,1)

mat <- t(sapply(vec,">=",1:max(vec)))

ifelse(mat,1,0)


Cheers,
Christoph


2013/10/11 arun <[hidden email]>:

> 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!
>
> ______________________________________________
> [hidden email] 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.


______________________________________________
[hidden email] 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.