This question already has answers here:
3 Dimensional Array Names in R
(2 answers)
Closed 6 years ago.
I have a existing array that I made and I want to name the dimensions of this array. I can't use the dimnames= argument of array() because I need to make this array with a different function. I need to rename the dimensions with something similar to this names(my.array)<-my.names.
Thanks for the help (and I'm new to this if you can't already tell)
Use dimnames(x) <- list(d1names, d2names, ...) where d1names, d2names and so forth are character vectors whose lengths match the lengths of your dimensions.
If your array is bidimensional (a matrix), you can use rownames(x) <- d1names and colnames(x) <- d2names instead.
Example:
> A <- outer(outer(1:3,1:4),1:2)
> A
, , 1
[,1] [,2] [,3] [,4]
[1,] 1 2 3 4
[2,] 2 4 6 8
[3,] 3 6 9 12
, , 2
[,1] [,2] [,3] [,4]
[1,] 2 4 6 8
[2,] 4 8 12 16
[3,] 6 12 18 24
> dimnames(A)
NULL
> dimnames(A) <- list(LETTERS[1:3],LETTERS[1:4],LETTERS[1:2])
> A
, , A
A B C D
A 1 2 3 4
B 2 4 6 8
C 3 6 9 12
, , B
A B C D
A 2 4 6 8
B 4 8 12 16
C 6 12 18 24
Example with matrix:
> B <- matrix(1:12,3,4)
> B
[,1] [,2] [,3] [,4]
[1,] 1 4 7 10
[2,] 2 5 8 11
[3,] 3 6 9 12
> rownames(B) <- letters[1:3]
> B
[,1] [,2] [,3] [,4]
a 1 4 7 10
b 2 5 8 11
c 3 6 9 12
> colnames(B) <- LETTERS[1:4]
> B
A B C D
a 1 4 7 10
b 2 5 8 11
c 3 6 9 12
you can still use dimnames<-
For example:
someArray <- array(1:30, dim=c(2, 3, 5))
dimnames(someArray) <- list(c("Hello", "World"), LETTERS[6:8], letters[1:5])
someArray
# , , a
# F G H
# Hello 1 3 5
# World 2 4 6
# , , b
# F G H
# Hello 7 9 11
# World 8 10 12
# , , c
# F G H
# Hello 13 15 17
# World 14 16 18
# , , d
# F G H
# Hello 19 21 23
# World 20 22 24
# , , e
# F G H
# Hello 25 27 29
# World 26 28 30
Related
This question already has answers here:
Most Efficient way to create a symmetric matrix
(4 answers)
How can I generate random real symmetric matrix in R [duplicate]
(1 answer)
Closed 2 years ago.
I currently have a matrix output from a program that looks like the following where the bottom left has all 1s:
B C D E
A 0 1 2 3
B 1 1 3 3
C 1 1 1 3
D 1 1 1 0
Is there a way to convert it into a symmetrical matrix instead of having all the 1s?
I do not think that the solution of #RonakShah is correct.
M = matrix(1:16, nrow=4)
M
[,1] [,2] [,3] [,4]
[1,] 1 5 9 13
[2,] 2 6 10 14
[3,] 3 7 11 15
[4,] 4 8 12 16
M[lower.tri(M)] <- M[upper.tri(M)]
M
[,1] [,2] [,3] [,4]
[1,] 1 5 9 13
[2,] 5 6 10 14
[3,] 9 13 11 15
[4,] 10 14 15 16
This is not symmetric. Instead, use
M = matrix(1:16, nrow=4)
M[lower.tri(M)] <- t(M)[lower.tri(M)]
M
[,1] [,2] [,3] [,4]
[1,] 1 5 9 13
[2,] 5 6 10 14
[3,] 9 10 11 15
[4,] 13 14 15 16
You can copy the upper triangular values to lower triangle.
mat[lower.tri(mat)] <- mat[upper.tri(mat)]
mat
# B C D E
#A 0 1 2 3
#B 1 1 3 3
#C 2 3 1 3
#D 3 3 3 0
I am having trouble using mapply to add ID columns to lists (within a larger function).
With most lists the code below works fine...
m1 <- matrix(data = 1:32, nrow = 8, ncol = 4)
m2 <- matrix(data = 1:8, nrow = 2, ncol = 4)
m3 <- matrix(data = 1:16, nrow = 4, ncol = 4)
m4 <- matrix(data = 1:4, nrow = 1, ncol = 4)
colnames(m1) <- colnames(m2) <- colnames(m3) <- colnames(m4) <- LETTERS[1:4]
a <- list(m1, m2, m3, m4)
mapply(cbind, a, m = 1:4)
# [[1]]
# A B C D m
# [1,] 1 9 17 25 1
# [2,] 2 10 18 26 1
# [3,] 3 11 19 27 1
# [4,] 4 12 20 28 1
# [5,] 5 13 21 29 1
# [6,] 6 14 22 30 1
# [7,] 7 15 23 31 1
# [8,] 8 16 24 32 1
#
# [[2]]
# A B C D m
# [1,] 1 3 5 7 2
# [2,] 2 4 6 8 2
#
# [[3]]
# A B C D m
# [1,] 1 5 9 13 3
# [2,] 2 6 10 14 3
# [3,] 3 7 11 15 3
# [4,] 4 8 12 16 3
#
# [[4]]
# A B C D m
# [1,] 1 2 3 4 4
but when I have lists that contain matrices of the same dimensions a list is no longer returned...
a <- list(m2, m2, m2, m2)
mapply(cbind, a, m = 2)
# [,1] [,2] [,3] [,4]
# [1,] 1 1 1 1
# [2,] 2 2 2 2
# [3,] 3 3 3 3
# [4,] 4 4 4 4
# [5,] 5 5 5 5
# [6,] 6 6 6 6
# [7,] 7 7 7 7
# [8,] 8 8 8 8
# [9,] 2 2 2 2
# [10,] 2 2 2 2
I cannot find any explanation as to why this is happening or a possible workaround (where the output would be a list in a similar format to first example above)?
That is exactly the difference between mapply and Map, mapply by default has simplify = TRUE argument which means
SIMPLIFY - logical or character string; attempt to reduce the result to a vector, matrix or higher dimensional array; see the simplify argument of sapply.
Hence, in this case, to get output same as the first example we should use Map
Map(cbind, a, m = 2)
#[[1]]
# A B C D m
#[1,] 1 3 5 7 2
#[2,] 2 4 6 8 2
#[[2]]
# A B C D m
#[1,] 1 3 5 7 2
#[2,] 2 4 6 8 2
#[[3]]
# A B C D m
#[1,] 1 3 5 7 2
#[2,] 2 4 6 8 2
#[[4]]
# A B C D m
#[1,] 1 3 5 7 2
#[2,] 2 4 6 8 2
I have a 6x6 matrix:
M = matrix(0,nrow = 6, ncol = 6);
for(i in 1:6)
for(j in 1:6)
M[i,j]<- i+j
> M
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 2 3 4 5 6 7
[2,] 3 4 5 6 7 8
[3,] 4 5 6 7 8 9
[4,] 5 6 7 8 9 10
[5,] 6 7 8 9 10 11
[6,] 7 8 9 10 11 12
I am using table() function to build a contingency table of the counts at each combination of factor levels.
table(M)
output:
> table(M)
M
2 3 4 5 6 7 8 9 10 11 12
1 2 3 4 5 6 5 4 3 2 1
Now I want to convert the table(M) to a data.frame using following:
pmfY <- data.frame(table(M))
But the pmfY$M changes to the follwong:
> pmfY$M
[1] 1 2 3 4 5 6 7 8 9 10 11
I am expecting pmfY$M to be the following vector in data frame.
2 3 4 5 6 7 8 9 10 11 12
Why pmfY$M is changed when converting table(M) to data frame and how to fix it?
For example suppose I have matrix A
x y z f
1 1 2 A 1005
2 2 4 B 1002
3 3 2 B 1001
4 4 8 C 1001
5 5 10 D 1004
6 6 12 D 1004
7 7 11 E 1005
8 8 14 E 1003
From this matrix I want to find the repeated values like 1001, 1005, D, 2 (in third column) and I also want to find their index (which row, or which position).
I am new to R!
Obviously it is possible to do with simple searching element by element by using a for loop, but I want to know, is there any function available in R for this kind of problem.
Furthermore, I tried using duplicated and unique, both functions are giving me the duplicated row number or column number, they are also giving me how many of them were repeated, but I can not search for whole matrix using both of them!
You can write a rather simple function to get this information. Though note that this solution works with a matrix. It does not work with a data.frame. A similar function could be written for a data.frame using the fact that the data.frame data structure is a subset of a list.
# example data
set.seed(234)
m <- matrix(sample(1:10, size=100, replace=T), 10)
find_matches <- function(mat, value) {
nr <- nrow(mat)
val_match <- which(mat == value)
out <- matrix(NA, nrow= length(val_match), ncol= 2)
out[,2] <- floor(val_match / nr) + 1
out[,1] <- val_match %% nr
return(out)
}
R> m
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] 8 6 6 7 6 7 4 10 6 9
[2,] 8 6 6 3 10 4 5 4 6 9
[3,] 1 6 9 2 9 2 3 6 4 2
[4,] 8 6 7 8 3 9 9 4 9 2
[5,] 1 1 5 6 7 1 5 1 10 6
[6,] 7 5 4 7 8 2 4 4 7 10
[7,] 10 4 7 8 3 1 8 6 3 4
[8,] 8 8 2 2 7 5 6 4 10 4
[9,] 10 2 9 6 6 9 7 2 4 7
[10,] 3 9 9 4 2 7 7 2 9 6
R> find_matches(m, 8)
[,1] [,2]
[1,] 1 1
[2,] 2 1
[3,] 4 1
[4,] 8 1
[5,] 8 2
[6,] 4 4
[7,] 7 4
[8,] 6 5
[9,] 7 7
In this function, the row index is output in column 1 and the column index is output in column 2
I am trying to create a matrix by drawing random block rows from another matrix. I have managed to do so with a loop.
set.seed(1)
a_matrix <- matrix(1:10,10,5) # the matrix with original sample
b_matrix <- matrix(NA,10, 5) # a matrix to store the bootstrap sample
S2<- seq(from =1 , to = 10, by =2) #[1] 1 3 5 7 9
m <- 2 # block size of m
for (r in S2){ start_point<-sample(1:(nrow(a_matrix)-1), 1, replace=T)
#randomly choose a number 1 to length of a_matrix -1
b_block <- a_matrix[start_point:(start_point+(m-1)), 1:ncol(a_matrix)]
# randomly select blocks from matrix a
b_matrix[r,]<-as.matrix((b_block)[1,])
b_matrix[(r+1),]<-as.matrix((b_block)[2,]) # put the blocks into matrix b
}
b_matrix
#we now have a b_matrix that is made of random blocks (size m=2)
#of the original a_matrix
The loop method works but it is clearly not very efficient and it is not possible to extend it to other block size (for e.g. having a blocksize of 3) .What is a cleaner and expandable approach ? Thanks in advance
Here I tried to clean it up a bit and generalize the use of m:
random_block_sample <- function(a_matrix, m = 2L) {
N <- nrow(a_matrix)
stopifnot(m <= N)
n <- ceiling(N / m)
s <- sample(N - m + 1L, n, TRUE) # start_point
i <- unlist(lapply(s, seq, length.out = m))
b_matrix <- a_matrix[i, , drop = FALSE]
head(b_matrix, N)
}
set.seed(1L)
random_block_sample(a_matrix, m = 2L)
# [,1] [,2] [,3] [,4] [,5]
# [1,] 3 3 3 3 3
# [2,] 4 4 4 4 4
# [3,] 4 4 4 4 4
# [4,] 5 5 5 5 5
# [5,] 6 6 6 6 6
# [6,] 7 7 7 7 7
# [7,] 9 9 9 9 9
# [8,] 10 10 10 10 10
# [9,] 2 2 2 2 2
# [10,] 3 3 3 3 3
set.seed(1L)
random_block_sample(a_matrix, m = 5L)
# [,1] [,2] [,3] [,4] [,5]
# [1,] 2 2 2 2 2
# [2,] 3 3 3 3 3
# [3,] 4 4 4 4 4
# [4,] 5 5 5 5 5
# [5,] 6 6 6 6 6
# [6,] 3 3 3 3 3
# [7,] 4 4 4 4 4
# [8,] 5 5 5 5 5
# [9,] 6 6 6 6 6
# [10,] 7 7 7 7 7