How can I create a matrix as shown below in R - r

I am trying to create a matrix from a given vector in R, but I don't know how to achieve it in simple ways. I am giving an example below. The matrix was made using the "cbind" function.
Given x as
[1,] 1
[2,] 3
[3,] 4
how can I create the matrix below with simple method?
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 1 0 0 0 0 0
[2,] 3 1 0 0 0 0
[3,] 4 3 1 0 0 0
[4,] 0 4 3 1 0 0
[5,] 0 0 4 3 1 0
[6,] 0 0 0 4 3 1
[7,] 0 0 0 0 4 3
[8,] 0 0 0 0 0 4
Thank you for your help!

Using append and sapply
sapply(0:5, append, x = rep(0,5), values = c(1,3,4))
# [,1] [,2] [,3] [,4] [,5] [,6]
# [1,] 1 0 0 0 0 0
# [2,] 3 1 0 0 0 0
# [3,] 4 3 1 0 0 0
# [4,] 0 4 3 1 0 0
# [5,] 0 0 4 3 1 0
# [6,] 0 0 0 4 3 1
# [7,] 0 0 0 0 4 3
# [8,] 0 0 0 0 0 4

matrix(c(1,3,4,rep(0,6)),ncol=6,nrow=8)
You'll get a warning, but the correct matrix. If you don't like the warning just use suppressWarnings:
suppressWarnings(matrix(c(1,3,4,rep(0,6)),ncol=6,nrow=8))
Of course, be careful with that function if you are trying to abstract this to more general cases.

This method is very intuitive:
x <- c(1,3,4)
n <- 6
m <- matrix(0,ncol=n,nrow=n+length(x)-1)
diag(m) <- 1
diag(m[-1,]) <- 3
diag(m[-c(1, 2),]) <- 4
Assigning along diagonals can be automated easily, for example with a 'for' loop
for(i in seq_along(x)) diag(m[1:n + i - 1,]) <- x[i]
Both approaches yield:
R> m
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 1 0 0 0 0 0
[2,] 3 1 0 0 0 0
[3,] 4 3 1 0 0 0
[4,] 0 4 3 1 0 0
[5,] 0 0 4 3 1 0
[6,] 0 0 0 4 3 1
[7,] 0 0 0 0 4 3
[8,] 0 0 0 0 0 4

This works. (edit: no votes, maybe too telegraphic?) The idea is to create an all-zero matrix with the appropriate dimensions, and then use row/column arithmetic (using the row() and col() functions) to fill in the desired values in the elements where row-column is between 0 and 2 (i.e. the diagonal and the first two lower off-diagonals). This does rely on the column-major structure of matrices in R ...
x <- c(1,3,4)
n <- 6
m <- matrix(0,ncol=n,nrow=n+length(x)-1)
betw <- function(x,a,b) x>=a & x<= b
m[betw(row(m)-col(m),0,2)] <- x

Related

replace a vector to an upper Triangle matrix with different length

I want to have a triangle matrix by a vector when length of vector is less than replacement length.
for example:
v<- c(1,2,3,4,5,6)
and
mat<- matrix(0,5,5).
If I use
mat[upper.tri(mat, diag=FALSE)]<- v
,the result is:
[,1] [,2] [,3] [,4] [,5]
[1,] 0 1 2 4 1
[2,] 0 0 3 5 2
[3,] 0 0 0 6 3
[4,] 0 0 0 0 4
[5,] 0 0 0 0 0
But i don't want to replace more than length of vector in matrix. And i want to have:
[1,] 0 1 2 4 0
[2,] 0 0 3 5 0
[3,] 0 0 0 6 0
[4,] 0 0 0 0 0
[5,] 0 0 0 0 0
You could adjust the length of v to that of the upper triangle. This yields some NA values that you can replace with zeroes.
u.tri <- upper.tri(mat, diag=FALSE)
mat[u.tri] <- `length<-`(v, length(u.tri))
mat[is.na(mat)] <- 0
# [,1] [,2] [,3] [,4] [,5]
# [1,] 0 1 2 4 0
# [2,] 0 0 3 5 0
# [3,] 0 0 0 6 0
# [4,] 0 0 0 0 0
# [5,] 0 0 0 0 0

How to loop through a dataset subtracting the value in the row below - Using R

I need help with the below question in R language.
Lets say I have a data set:
X Y
1 1
2 2
3 3
4 4
How would I go about looping through the dataset subtracting the X value in the current row from the X value in the row below, then going to the second row etc?
Currently I have the below:
df <- (df[row(df)-1,1] - df[row(df)+1,1])
I would like to get the following:
X
-1
-1
-1
N/a
However it seems to being doing the calculations twice and I am getting?
X
-1
-1
-1
N/a
-1
-1
-1
N/a
I cant figure out why, any help would be appreciated?
As #Sotos pointed out, you can solve this with diff.
But the reason this isn't working is because row() returns row numbers for both columns
> row(df)
[,1] [,2]
[1,] 1 1
[2,] 2 2
[3,] 3 3
[4,] 4 4
If you select either column alone your code works:
df <- (df[row(df)[,1]-1,1] - df[row(df)[,1]+1,1])
You could use diff(). Also you could do it using a matrix multiplication approach.
Example
set.seed(42)
x <- sample(10, 10, replace=TRUE)
> x
[1] 10 10 3 9 7 6 8 2 7 8
> diff(x)
[1] 0 -7 6 -2 -1 2 -6 5 1
# difference matrix approach
lbd <- matrix(0, nrow=length(x) - 1, ncol=length(x)) # setup lambda
diag(lbd) <- -1
diag(lbd[, -1]) <- 1
> lbd
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] -1 1 0 0 0 0 0 0 0 0
[2,] 0 -1 1 0 0 0 0 0 0 0
[3,] 0 0 -1 1 0 0 0 0 0 0
[4,] 0 0 0 -1 1 0 0 0 0 0
[5,] 0 0 0 0 -1 1 0 0 0 0
[6,] 0 0 0 0 0 -1 1 0 0 0
[7,] 0 0 0 0 0 0 -1 1 0 0
[8,] 0 0 0 0 0 0 0 -1 1 0
[9,] 0 0 0 0 0 0 0 0 -1 1
> lbd %*% x # matrix multiplication, same result as in `diff(x)` above
[,1]
[1,] 0
[2,] -7
[3,] 6
[4,] -2
[5,] -1
[6,] 2
[7,] -6
[8,] 5
[9,] 1
Using your data:
x1 <- 1:4
lbd1 <- matrix(0, nrow=length(x1) - 1, ncol=length(x1))
diag(lbd1) <- -1
diag(lbd1[, -1]) <- 1
> lbd1 %*% x1
[,1]
[1,] 1
[2,] 1
[3,] 1
> diff(x1) # same
[1] 1 1 1

Change the values in binary matrix only couple of columns

Consider the 8 by 6 binary matrix, M:
M <- matrix(c(0,0,1,1,0,0,1,1,
0,1,1,0,0,1,1,0,
0,0,0,0,1,1,1,1,
0,1,0,1,1,0,1,0,
0,0,1,1,1,1,0,0,
0,1,1,0,1,0,0,1),nrow = 8,ncol = 6)
Here is the M
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 0 0 0 0 0 0
[2,] 0 1 0 1 0 1
[3,] 1 1 0 0 1 1
[4,] 1 0 0 1 1 0
[5,] 0 0 1 1 1 1
[6,] 0 1 1 0 1 0
[7,] 1 1 1 1 0 0
[8,] 1 0 1 0 0 1
The following matrix contains the column index of the 1's in matrix M
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 3 2 5 2 3 2
[2,] 4 3 6 4 4 3
[3,] 7 6 7 5 5 5
[4,] 8 7 8 7 6 8
Let's denote that
ind <- matrix(c(3,4,7,8,
2,3,6,7,
5,6,7,8,
2,4,5,7,
3,4,5,6,
2,3,5,8),nrow = 4, ncol=6)
I'm trying to change a single position of 1 into 0only in SOME columns of M.
For an example, consider the case for changing two ones in every two columns. One possibility is given changing two positions in first two columns. Let N be the resulting matrices. This will produce the following matrix N
N <- matrix(c(0,0,0,1,0,0,1,1,
0,1,1,0,0,0,1,0,
0,0,0,0,1,1,1,1,
0,1,0,1,1,0,1,0,
0,0,1,1,1,1,0,0,
0,1,1,0,1,0,0,1),nrow = 8,ncol = 6)
Here is that N
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 0 0 0 0 0 0
[2,] 0 1 0 1 0 1
[3,] 0 1 0 0 1 1
[4,] 1 0 0 1 1 0
[5,] 0 0 1 1 1 1
[6,] 0 0 1 0 1 0
[7,] 1 1 1 1 0 0
[8,] 1 0 1 0 0 1
For EACH of the resulting matrices of N, I do the following calculations.
X <- cbind(c(rep(1,nrow(N))),N)
ans <- sum(diag(solve(t(X)%*%X)[-1,-1]))
Then, I want to obtain the matrix N, which produce the smallest value of ans. This 8 by 6 matrix is just one example. How do I do this?
I asked a question similar to this one before which changes positions in every column. Here is the link to that.

R which function displays wrong row numbers

I am trying to save the row number for values equal to one, for every column seperatly in a matrix (matx). The matrix should contain 0's for every other object. It somehow worked to give me numbers which are just a little bit smaller (1 value smaller in the beginning, two and three later on), but not the right values. The original matrix has just values of 0 and 1.
My try:
matx<-replicate(n=100,rbinom(n= 250, size=1, prob = 0.01))
maty<-apply(!matx, 2, function(x) ifelse(x==0,
which(x %in% 1),
x==0))
also tried:
maty<-apply(!matx, 2, function(x) ifelse(x>0, as.integer(rownames(matx)), 0))
The second attempt just leaves me with NA's and 0's instead of the row number.
Assuming that #akrun's interpretation is correct (it's also how I read the question) you can also use the row function:
matx * row(matx)
# [,1] [,2] [,3] [,4] [,5]
# [1,] 0 1 0 0 0
# [2,] 0 0 2 0 0
# [3,] 3 3 3 0 0
# [4,] 4 4 0 0 0
# [5,] 5 0 0 5 0
# [6,] 6 6 6 0 0
# [7,] 0 0 0 7 0
# [8,] 8 0 8 8 0
# [9,] 9 9 9 9 0
# [10,] 0 0 0 10 0
If we need to replace the '1s' (in the binary matrix) with the corresponding row numbers leaving the '0s' as such, we can can which with arr.ind=TRUE to get the row/column index of non-zero numbers, use that index to replace the 1s with the row index column from 'ind'. Here, I created a copy of 'matx' (ie. 'maty') in case the original matrix is needed.
maty <- matx
ind <- which(matx!=0, arr.ind=TRUE)
maty[ind] <- ind[,1]
maty
# [,1] [,2] [,3] [,4] [,5]
#[1,] 0 1 0 0 0
#[2,] 0 0 2 0 0
#[3,] 3 3 3 0 0
#[4,] 4 4 0 0 0
#[5,] 5 0 0 5 0
#[6,] 6 6 6 0 0
#[7,] 0 0 0 7 0
#[8,] 8 0 8 8 0
#[9,] 9 9 9 9 0
#[10,] 0 0 0 10 0
and original matrix
matx
# [,1] [,2] [,3] [,4] [,5]
#[1,] 0 1 0 0 0
#[2,] 0 0 1 0 0
#[3,] 1 1 1 0 0
#[4,] 1 1 0 0 0
#[5,] 1 0 0 1 0
#[6,] 1 1 1 0 0
#[7,] 0 0 0 1 0
#[8,] 1 0 1 1 0
#[9,] 1 1 1 1 0
#[10,] 0 0 0 1 0
NOTE: This could be also used for non-numeric elements
Or a base R modification of apply solution in #eipi's post would be
apply(matx, 2,function(x) ifelse(x!=0, seq_along(x), 0) )
data
set.seed(24)
matx <- matrix(sample(0:1, 10*5, replace=TRUE), nrow=10)
If your original matx is purely 0s and 1s then this show work:
maty <- matx * row(matx)
an example:
> matx # stealing from akrun
[,1] [,2] [,3] [,4] [,5]
[1,] 0 1 0 0 0
[2,] 0 0 1 0 0
[3,] 1 1 1 0 0
[4,] 1 1 0 0 0
[5,] 1 0 0 1 0
[6,] 1 1 1 0 0
[7,] 0 0 0 1 0
[8,] 1 0 1 1 0
[9,] 1 1 1 1 0
[10,] 0 0 0 1 0
> matx * row(matx)
[,1] [,2] [,3] [,4] [,5]
[1,] 0 1 0 0 0
[2,] 0 0 2 0 0
[3,] 3 3 3 0 0
[4,] 4 4 0 0 0
[5,] 5 0 0 5 0
[6,] 6 6 6 0 0
[7,] 0 0 0 7 0
[8,] 8 0 8 8 0
[9,] 9 9 9 9 0
[10,] 0 0 0 10 0
Here's a way to do it using apply:
library(zoo) # For index function
apply(matx, 2, function(x) ifelse(x==1, index(x), 0))

Generate large matrix filled with 0's or 1's in R

In R language, I am trying to generate a large matrix filled with 0's and 1's.
I have generated a large matrix but its filled with values between 0 and 1.
Here is how I did that:
NCols=500
NRows=700
mr<-matrix(runif(NCols*NRows), ncol=NCols)
I think you are asking how to generate a matrix with just zero and 1
Here is how I would do it
onezero <- function(nrow,ncol)
matrix(sample(c(0,1), replace=T, size=nrow*ncol), nrow=nrow)
With nrow and ncol the rows and columns of the matrix
R> onezero(5,5)
[,1] [,2] [,3] [,4] [,5]
[1,] 1 1 0 1 0
[2,] 1 1 1 1 0
[3,] 1 1 0 0 0
[4,] 1 0 0 1 0
[5,] 0 0 0 0 0
You can use rbinomtoo. And can change the probability of success on each trial. In this case, it's .5.
nrow<-700
ncol<-500
mat01 <- matrix(rbinom(nrow*ncol,1,.5),nrow,ncol)
> number.of.columns = 5
> number.of.rows = 10
> matrix.size = number.of.columns*number.of.rows
> ones.and.zeros.samples = sample(0:1, matrix.size, replace=TRUE)
> A = matrix(ones.and.zeros.samples, number.of.rows)
> A
[,1] [,2] [,3] [,4] [,5]
[1,] 0 0 0 1 1
[2,] 1 0 0 0 1
[3,] 0 1 1 0 0
[4,] 0 0 1 1 1
[5,] 1 0 1 1 0
[6,] 0 1 0 1 1
[7,] 0 0 1 1 0
[8,] 0 1 0 0 0
[9,] 0 0 0 0 0
[10,] 0 0 0 1 1

Resources