How do I label the rows and columns in a diagonal matrix? - r

I'm creating a diagonal matrix of variances in R, thus:
D <- diag(data $ Variances,
length(data $ Variances),
length(data $ Variances))
Does anyone know how to add row and column labels? The labels are species names in the column "Species" from dataframe "data", where the column "Variances" was also taken from.

Just use colnames(D) <- your.col.names and rownames(D) <- your.row.names to add column and row names to your matrix D.

dimnames is another useful function, see ?dimnanes for further details.
> Mat <- matrix(1:12, ncol=3) # creating a matrix
> Mat # no dimnames
[,1] [,2] [,3]
[1,] 1 5 9
[2,] 2 6 10
[3,] 3 7 11
[4,] 4 8 12
> dimnames(Mat) <- list(letters[1:4], LETTERS[1:3])
> Mat # with dimnames
A B C
a 1 5 9
b 2 6 10
c 3 7 11
d 4 8 12

Related

Extract specific elements in a matrix with a character vector in R

I want to extract specific elements column wise from the matrix A with the information from a character vector B (contain elements in the row names of the matrix) such as:
A <- matrix(seq(1,12),ncol=4)
rownames(A) <- letters[1:3]
A
[,1] [,2] [,3] [,4]
a 1 4 7 10
b 2 5 8 11
c 3 6 9 12
B <- c("a","c","c","b")
I want to get 1,6,9,11. Thanks :)
Two possible ways:
> A[cbind(match(B, rownames(A)), seq_len(ncol(A)))]
[1] 1 6 9 11
>
> diag(A[B, seq_along(B)]) # or diag(A[B, seq_len(ncol(A))])
[1] 1 6 9 11

Create a specific number of vertors for a list

I need to create a list of "N" vectors with a length "L" that begin in number "B" . If I specify that N=3, L=4 and B=5. I would need a list of the following three vectors.
5 ,6,7,8,
9,10,11,12
13,14,15,16
I can do it manually one by one but I have sometimes 20 or 30 vectors to create with always different lengths.
I would appreciate if someone could give me a hand with this.
Cheers
Carlos
If you are happy with matrix as an output...
N <- 3
L <- 4
B <- 5
x <- seq(from = B, to = B + N * L - 1)
y <- matrix(x, nrow = N, byrow = TRUE)
y
# [,1] [,2] [,3] [,4]
# [1,] 5 6 7 8
# [2,] 9 10 11 12
# [3,] 13 14 15 16
Taking the matrix to list via transposition and data.frame...
as.list(as.data.frame(t(y)))
# $V1
# [1] 5 6 7 8
#
# $V2
# [1] 9 10 11 12
#
# $V3
# [1] 13 14 15 16
I'm showing it in this way partly because I've never liked the coercion of numbers to colnames, certainly other ways to handle that. The transposition may be removed if you set y <- matrix(x, nrow = L) instead. And drop the as.list because technically the data.frame is a list.
as.data.frame(y)
# V1 V2 V3
# 1 5 9 13
# 2 6 10 14
# 3 7 11 15
# 4 8 12 16
You can use split() to get a list output.
split(seq(B, B + L*N - 1), (1:(L*N)-1) %/% N)

How to use data from every row to create a matrix by loop

I have a data frame like
df<-data.frame(a=c(1,2,3),b=c(4,5,6),c=c(7,8,9),d=c(10,11,12))
a b c d
1 1 4 7 10
2 2 5 8 11
3 3 6 9 12
I want to use every row to create 3 (nrow(df)) 2*2 matrixes. 1st use 1,4,7,10, 2nd use 2,5,8,11, 3rd use 3,6,9,12. So that I can get 3 matrixes. Thank you.
We can use split to split up the dataset into list and use matrix
lapply(split.default(as.matrix(df), row(df)), matrix, 2)
If we need the matrix columns to be 1, 7 followed by 4, 10, use the byrow=TRUE
lapply(split.default(as.matrix(df), row(df)), matrix, 2, byrow=TRUE)
Or use apply with MARGIN = 1 and wrap it with list to get a list output
do.call("c", apply(df, 1, function(x) list(matrix(x, ncol=2))))
If we need a for loop, preassign a as a list with length equal to the number of rows of 'df'
a <- vector("list", nrow(df))
for(i in 1:nrow(df)){ a[[i]] <- matrix(unlist(df[i,]), ncol=2)}
a
Or if it can be stored as array
array(t(df), c(2, 2, 3))
Or using map:
m <- matrix(c(t(df)), ncol = 2, byrow = T)
p <- 2 # number of rows
Map(function(i,j) m[i:j,], seq(1,nrow(m),p), seq(p,nrow(m),p))
# [[1]]
# [,1] [,2]
# [1,] 1 4
# [2,] 7 10
# [[2]]
# [,1] [,2]
# [1,] 2 5
# [2,] 8 11
# [[3]]
# [,1] [,2]
# [1,] 3 6
# [2,] 9 12

Moving Data from Matrix A to Matrix B in R

I want to cut/move/replace some data (to be precise 2500) from Matrix A to Matrix B in R.
for example Move cell(i,j) from matrix A to cell(i,j) in matrix B. both i and j have some fixed value(50 to be precise) and replace that cell(i,j) in matrix A with "0".
Since I am newto programming can anyone help me with the coding?
Thanks in Advance
Regards
You can first define a two column coordinate-matrix of the values you want to replace, where the first column refers is the row-index and the second column is the column-index. As an example, suppose you want to replace the cells c(2,1), c(2,2) and c(1,2) in a 3x3 matrix B with the calues from a 3x3 matrix A:
ind <- cbind(c(2,2,1), c(1,2,2))
A <- matrix(1:9, ncol = 3)
B <- matrix(NA, ncol = 3, nrow = 3)
B[ind] <- A[ind]; A[ind] <- 0
B
[,1] [,2] [,3]
[1,] NA 4 NA
[2,] 2 5 NA
[3,] NA NA NA
A
[,1] [,2] [,3]
[1,] 1 0 7
[2,] 0 0 8
[3,] 3 6 9

Naming elements of matrix dimensions one at a time, when dimname is NULL

When dimnames is currently NULL, is it possible to re-name a matrix's dimestions one at a time?
For example, this fails:
mtx <- matrix(1:16,4)
dimnames(mtx)[[2]][1] <- 'col1'
with Error in dimnames(mtx)[[2]][1] <- "col1" : 'dimnames' must be a list
However this works:
mtx <- matrix(1:16,4)
dimnames(mtx)[[1]] <- letters[1:4]
dimnames(mtx)[[2]] <- LETTERS[1:4]
dimnames(mtx)[[2]][1] <- 'col1'
dimnames(mtx)[[2]][2] <- 'col2'
My objective is to seperately replace dimnames(mtx)[[2]][1] and dimnames(mtx)[[2]][2] etc ... if this is not possible, i can re-write the loop.
Thanks folks, I have ended up with the below -- I pass the names in via prepend:
mtxNameSticker <- function(mtx, prepend = NULL, MARGIN=2)
{
if (MARGIN == 1) max <- nrow(mtx) else
max <- ncol(mtx)
if (is.null(prepend)) if (MARGIN == 2) prepend <- 'C' else
prepend <- 'R'
if (length(prepend) == 1) prepend <- paste0(prepend, 1:dim(mtx)[[MARGIN]])
dimnames(mtx)[[MARGIN]] <- seq(from=1, by=1, length.out=dim(mtx)[[MARGIN]])
for (i in 1:max){
dimnames(mtx)[[MARGIN]][i] <- prepend[i]
}
return(mtx)
}
For as long as dimnames is NULL and not an appropriate list, you cannot make assignments to it at particular positions. One easy way to create a dummy but complete list of dimnames is to run:
dimnames(mtx) <- lapply(dim(mtx), seq_len)
mtx
# 1 2 3 4
# 1 1 5 9 13
# 2 2 6 10 14
# 3 3 7 11 15
# 4 4 8 12 16
Then, you can make assignments one at a time like you were wishing:
dimnames(mtx)[[2]][1] <- 'col1'
mtx
# col1 2 3 4
# 1 1 5 9 13
# 2 2 6 10 14
# 3 3 7 11 15
# 4 4 8 12 16
You are assigning a vector even though you are asked to supply a list.
Try this:
R> M <- matrix(1:4,2,2)
R> M
[,1] [,2]
[1,] 1 3
[2,] 2 4
R>
Columns:
R> M1 <- M; dimnames(M1) <- list(NULL, c("a","b")); M1
a b
[1,] 1 3
[2,] 2 4
R>
Rows:
R> M2 <- M; dimnames(M2) <- list(c("A","B"), NULL); M2
[,1] [,2]
A 1 3
B 2 4
R>
In response to your comment. #DirkEddelbuettel is correct, you are assigning a vector to what should be a list.
The reason for this is that you are assigning dimnames when the dimnames are NULL (not assigned yet)
The way R evaluates the following
x <- NULL
x[[2]][1] <- 'col1'
str(x)
## chr [1:2] NA "col1"
R returns a vector of length 2, not a list of length 2.
For your assignment to work, R would have to evaluate
x <- NULL
x[[2]][1] <- 'col1'
str(x)
to give
## List of 2
## $ : NULL
## $ : chr "col1"
Which is what would happen if x was originally defined as x <- list(NULL,NULL)
however, the dimnames must be NULL or a list of appropriate length vectors
The following does work (and is really #flodel solution)
dimnames(mtx) <- list(character(nrow(mtx)), character(ncol(mtx)))
# or
# dimnames(mtx) <- lapply(dim(mtx), character)
dimnames(mtx)[[2]][1] <- 'col1'
It seems you are allowed to set the name of the dimension without actually having any names for the dimension:
dimnames(mtx) = list(NULL,col1=NULL)
mtx
# col1
# [,1] [,2] [,3] [,4]
# [1,] 1 5 9 13
# [2,] 2 6 10 14
# [3,] 3 7 11 15
# [4,] 4 8 12 16

Resources