Ahmad Zaenal
Ahmad Zaenal

Reputation: 148

How to make matrix with diagonal is data and 0 the other?

I have a dataframe with 90 row and 4 column, i want make matrix (4*90)x4 in software R with first column is 90 data and the other is 0 from 91 to 360. Second column is 0 from 1 to 90, from 91 to 180 fill with data then row 181 to 360 is 0. and so on.

i've been made the syntax like this


psi10<-c(c(data[,1]),rep(0,3*90))

psi20<-c(rep(0,90),c(data[,2]),rep(0,2*90))

psi30<-c(rep(0,90),rep(0,90),c(data[,3]),rep(0,90))

psi40<-c(rep(0,3*90),c(data[,4]))

Mpsi<-as.matrix(data.frame(psi10,psi20,psi30,psi40))

but it's too long i think, it's more difficult if I add more column please help me make the function to my problem. thanks

Upvotes: 0

Views: 150

Answers (3)

alexis_laz
alexis_laz

Reputation: 13122

Another idea could be:

DF = data.frame(c1 = 1:3, c2 = 4:6, c3 = 7:9)
DF
#  c1 c2 c3
#1  1  4  7
#2  2  5  8
#3  3  6  9

mat = matrix(0, nrow = prod(dim(DF)), ncol = ncol(DF))
mat[cbind(seq_len(prod(dim(DF))), rep(seq_along(DF), each = nrow(DF)))] = unlist(DF)
mat
#      [,1] [,2] [,3]
# [1,]    1    0    0
# [2,]    2    0    0
# [3,]    3    0    0
# [4,]    0    4    0
# [5,]    0    5    0
# [6,]    0    6    0
# [7,]    0    0    7
# [8,]    0    0    8
# [9,]    0    0    9

Upvotes: 1

akrun
akrun

Reputation: 886978

You could try

library(Matrix)
m1 <- as.matrix(bdiag(lapply(data, matrix, 1,90)))

Or use sapply from base R

n <- 4
m2 <- t(sapply(seq_len(n), function(i) {c(rep(0,90*(i-1)), data[,i],
                                              rep(0, 90*(n-i)))}))

all.equal(m1, m2, check.attributes=FALSE)
#[1] TRUE

Update

Seems like the OP wanted the "transpose", in that case

m1 <- as.matrix(bdiag(data))

which is the same as

 m1N <- as.matrix(t(bdiag(lapply(data, matrix, 1,90))))
 identical(m1, m1N)
 #[1] TRUE

data

set.seed(24)
 data <- as.data.frame(matrix(sample(1:4, 90*4, replace=TRUE), ncol=4))

Upvotes: 1

Mark C
Mark C

Reputation: 391

Something like this work?

df<-data.frame(a=100:189,b=100:189,c=100:189,d=100:189)
df<-as.matrix(df)

df<-rbind(df, matrix(0,nrow=(ncol(df)-1)*90,ncol=ncol(df)))
for (x in 1:ncol(df)){
  df[,x]<-c(rep(0,90*(x-1)),df[1:90,x],rep(0,90*(ncol(df)-x)))
}

Upvotes: 0

Related Questions