I want to paste cells of matrix together, But when I do paste(),It returns a vector. Is there a direct function for same in R?
mat <- matrix(1:4,2,2)
paste(mat,mat,sep=",")
I want the output as
[,1] [,2]
[1,] 1,1 2,2
[2,] 3,3 4,4
A matrix in R is just a vector with an attribute specifying the dimensions. When you paste them together you are simply losing the dimension attribute.
So,
matrix(paste(mat,mat,sep=","),2,2)
Or, e.g.
mat1 <- paste(mat,mat,sep=",")
> mat1
[1] "1,1" "2,2" "3,3" "4,4"
> dim(mat1) <- c(2,2)
> mat1
[,1] [,2]
[1,] "1,1" "3,3"
[2,] "2,2" "4,4"
Here's just one example of how you might write a simple function to do this:
paste_matrix <- function(...,sep = " ",collapse = NULL){
n <- max(sapply(list(...),nrow))
p <- max(sapply(list(...),ncol))
matrix(paste(...,sep = sep,collapse = collapse),n,p)
}
...but the specific function you want will depend on how you want it to handle more than two matrices, matrices of different dimensions or possibly inputs that are totally unacceptable (random objects, NULL, etc.).
This particular function recycles the vector and outputs a matrix with the dimension matching the largest of the various inputs.
Another approach to the Joran's one is to use [] instead of reconstructing a matrix. In that way you can also keep the colnames for example:
truc <- matrix(c(1:3, LETTERS[3:1]), ncol=2)
colnames(truc) <- c("A", "B")
truc[] <- paste(truc, truc, sep=",")
truc
# A B
# [1,] "1,1" "C,C"
# [2,] "2,2" "B,B"
# [3,] "3,3" "A,A"
Or use sprintf withdim<-
`dim<-`(sprintf('%d,%d', mat, mat), dim(mat))
# [,1] [,2]
#[1,] "1,1" "3,3"
#[2,] "2,2" "4,4"
The ascii library has a function paste.matrix for element-wise paste across matrices. The output is the transpose to the desired outcome, but that's easy to address with t().
library(ascii)
mat <- matrix(1:4,2,2)
t(paste.matrix(mat,mat,sep=","))
[,1] [,2]
[1,] "1,1" "2,2"
[2,] "3,3" "4,4"
Related
I have created an example below, where I am trying to make a list of each row of a matrix, then use apply().
mat<-matrix(rexp(9, rate=.1), ncol=3)
my_list2 <- list()
for(i in 1:nrow(mat)) {
my_list2[[i]] <- mat[i,]
}
#DO NOT CHANGE THIS:
apply(my_list2[[i]],2,sum)
However the apply() function does not work, giving a dimension error. I understand that apply() is not the best function to use here but it is present in a function that I need so I cannot change that line.
Does anyone have any idea how I can change my "my_list2" to work better? Thank you!
Edit:
Here is an example that works (non reproducible)
Example
Note both the example above and this example have type "list"
This answer addresses "how to properly get a list of matrices", not how to resolve the use of apply.
By default in R, when you subset a matrix to a single column or a single row, it reduces the dimensionality. For instance,
mtx <- matrix(1:6, nrow = 2)
mtx
# [,1] [,2] [,3]
# [1,] 1 3 5
# [2,] 2 4 6
mtx[1,]
# [1] 1 3 5
mtx[,3]
# [1] 5 6
If you want a single row or column but to otherwise retain dimensionality, add the drop=FALSE argument to the [-subsetting:
mtx[1,,drop=FALSE]
# [,1] [,2] [,3]
# [1,] 1 3 5
mtx[,3,drop=FALSE]
# [,1]
# [1,] 5
# [2,] 6
In this way, your code to produce sample data can be adjusted to be:
set.seed(42) # important for reproducibility in questions on SO
mat<-matrix(rexp(9, rate=.1), ncol=3)
my_list2 <- list()
for(i in 1:nrow(mat)) {
my_list2[[i]] <- mat[i,,drop=FALSE]
}
my_list2
# [[1]]
# [,1] [,2] [,3]
# [1,] 1.983368 0.381919 3.139846
# [[2]]
# [,1] [,2] [,3]
# [1,] 6.608953 4.731766 4.101296
# [[3]]
# [,1] [,2] [,3]
# [1,] 2.83491 14.63627 11.91598
And then you can use akrun's most recent code to resolve how to get the row-wise sums within each list element, i.e., one of
lapply(my_list2, apply, 2, sum)
lapply(my_list2, function(z) apply(z, 2, sum))
lapply(my_list2, \(z) apply(z, 2, sum)) # R-4.1 or later
In your screenshot it works because the object part of the list ex[[1]] is an array. And in your example the elements of your list are vectors. You could try the following:
mat<-matrix(rexp(9, rate=.1), ncol=3)
my_list2 <- list()
for(i in 1:nrow(mat)) {
my_list2[[i]] <- as.matrix(mat[i,])
}
#DO NOT CHANGE THIS:
apply(my_list2[[1]],2,sum)
apply(my_list2[[2]],2,sum)
apply(my_list2[[3]],2,sum)
You should note that apply cannot be applied to all three elements of the array in one line. And to do it in one, that line should be changed.
I´m trying to get different elements from multiple diagonal saved as lists. My data looks something like this:
res <- list()
res[[1]] <- matrix(c(0.04770856,0.02854005,0.02854005,0.03260190), nrow=2, ncol=2)
res[[2]] <- matrix(c(0.05436957,0.04887182,0.04887182, 0.10484454), nrow=2, ncol=2)
> res
[[1]]
[,1] [,2]
[1,] 0.04770856 0.02854005
[2,] 0.02854005 0.03260190
[[2]]
[,1] [,2]
[1,] 0.05436957 0.04887182
[2,] 0.04887182 0.10484454
> diag(res[[1]])
[1] 0.04770856 0.03260190
> diag(res[[2]])
[1] 0.05436957 0.10484454
I would like to save the first and second elements of each diagonal of a given list into a vector similar to this:
d.1st.el <- c(0.04770856, 0.05436957)
d.2nd.el <- c(0.03260190, 0.10484454)
My issue is to write the function that runs for all given lists and get the diagonals. For some reason, when I use unlist() to extract the values of each matrix for a given level, it doesn't get me the number but the full matrix.
Does anyone have a simple solution?
sapply(res, diag)
[,1] [,2]
[1,] 0.04770856 0.05436957
[2,] 0.03260190 0.10484454
# or
lapply(res, diag)
[[1]]
[1] 0.04770856 0.03260190
[[2]]
[1] 0.05436957 0.10484454
If you want the vectors for some reason in your global environment:
alld <- lapply(res, diag)
names(alld) <- sprintf("d.%d.el", 1:length(alld))
list2env(alld, globalenv())
In two steps you can do:
# Step 1 - Get the diagonals
all_diags <- sapply(res, function(x) diag(t(x)))
print(all_diags)
[,1] [,2]
[1,] 0.04770856 0.05436957
[2,] 0.03260190 0.10484454
# Step 2 - Append to vectors
d.1st.el <- all_diags[1,]
d.2nd.el <- all_diags[2,]
I want to paste cells of matrix together, But when I do paste(),It returns a vector. Is there a direct function for same in R?
mat <- matrix(1:4,2,2)
paste(mat,mat,sep=",")
I want the output as
[,1] [,2]
[1,] 1,1 2,2
[2,] 3,3 4,4
A matrix in R is just a vector with an attribute specifying the dimensions. When you paste them together you are simply losing the dimension attribute.
So,
matrix(paste(mat,mat,sep=","),2,2)
Or, e.g.
mat1 <- paste(mat,mat,sep=",")
> mat1
[1] "1,1" "2,2" "3,3" "4,4"
> dim(mat1) <- c(2,2)
> mat1
[,1] [,2]
[1,] "1,1" "3,3"
[2,] "2,2" "4,4"
Here's just one example of how you might write a simple function to do this:
paste_matrix <- function(...,sep = " ",collapse = NULL){
n <- max(sapply(list(...),nrow))
p <- max(sapply(list(...),ncol))
matrix(paste(...,sep = sep,collapse = collapse),n,p)
}
...but the specific function you want will depend on how you want it to handle more than two matrices, matrices of different dimensions or possibly inputs that are totally unacceptable (random objects, NULL, etc.).
This particular function recycles the vector and outputs a matrix with the dimension matching the largest of the various inputs.
Another approach to the Joran's one is to use [] instead of reconstructing a matrix. In that way you can also keep the colnames for example:
truc <- matrix(c(1:3, LETTERS[3:1]), ncol=2)
colnames(truc) <- c("A", "B")
truc[] <- paste(truc, truc, sep=",")
truc
# A B
# [1,] "1,1" "C,C"
# [2,] "2,2" "B,B"
# [3,] "3,3" "A,A"
Or use sprintf withdim<-
`dim<-`(sprintf('%d,%d', mat, mat), dim(mat))
# [,1] [,2]
#[1,] "1,1" "3,3"
#[2,] "2,2" "4,4"
The ascii library has a function paste.matrix for element-wise paste across matrices. The output is the transpose to the desired outcome, but that's easy to address with t().
library(ascii)
mat <- matrix(1:4,2,2)
t(paste.matrix(mat,mat,sep=","))
[,1] [,2]
[1,] "1,1" "2,2"
[2,] "3,3" "4,4"
As the title suggests, I am looking for a way to get the standard deviation per element from two separate matrices. However, I am quite the beginner at R and I can't seem to figue out how to do this. Below is an example of what I am trying to accomplish with a small sample of my data (first three rows)
I have two matrices with coordinates (df143 and df143_2, or matrices A and B as you will)
A:
[1,] 21.729504 -55.66055 -37.26477
[2,] 39.445610 -67.67449 -32.19464
[3,] 57.604027 -54.16734 -28.48679
B:
[1,] 21.706865 -55.50722 -37.57840
[2,] 39.553314 -67.68414 -31.95995
[3,] 57.286247 -54.13008 -28.44446
I am looking for an matrix output that shows the standard deviation per element of the two combined matrices.
Or you can do base R:
matrix(mapply(function(x,y) sd(c(x,y)),A, B), ncol=ncol(A))
# [,1] [,2] [,3]
#[1,] 0.01600819 0.10842068 0.22176990
#[2,] 0.07615823 0.00682358 0.16595089
#[3,] 0.22470439 0.02634680 0.02993183
I believe this is what you're looking to do:
library(abind)
a <- c(21.729504, -55.66055, -37.26477, 39.445610, -67.67449, -32.19464, 57.604027, -54.16734, -28.48679)
a <- matrix(a, ncol=3, byrow=TRUE)
b <- c(21.706865, -55.50722, -37.57840, 39.553314, -67.68414, -31.95995, 57.286247, -54.13008, -28.44446)
b <- matrix(b, ncol=3, byrow=TRUE)
m <- abind(a, b, along=3)
apply(m, 1:2, sd)
## [,1] [,2] [,3]
## [1,] 0.01600819 0.10842068 0.22176990
## [2,] 0.07615823 0.00682358 0.16595089
## [3,] 0.22470439 0.02634680 0.02993183
Is there an easy way to convert a correlation-covariance matrix into a variance-covariance matrix? I always use nested for-loops as below, but I keep thinking there is probably a built-in function in base R.
my.matrix <- matrix(c(0.64901, 0.76519, -0.63620, -0.01923,
0.02114, 0.00118, -0.43198, 0.02480,
-0.21811, -0.00630, 0.18109, 0.05964,
-0.00710, 0.00039, 0.01162, 0.20972), nrow=4, byrow=TRUE)
new.matrix <- my.matrix
for(i in 1:nrow(my.matrix)) {
for(j in 1:ncol(my.matrix)) {
new.matrix[i,j] = ifelse(i<j, my.matrix[j,i], new.matrix[i,j])
}
}
new.matrix
# [,1] [,2] [,3] [,4]
# [1,] 0.64901 0.02114 -0.21811 -0.00710
# [2,] 0.02114 0.00118 -0.00630 0.00039
# [3,] -0.21811 -0.00630 0.18109 0.01162
# [4,] -0.00710 0.00039 0.01162 0.20972
I am aware of the lower.tri and upper.tri functions, but cannot seem to accomplish the task with a combination of them and t().
I think you might need to get the indices with which and then swap the rows and columns. Try this.
k <- which(lower.tri(my.matrix), arr.ind=TRUE)
my.matrix[k[,c(2,1)]] <- my.matrix[k]