Getting dimension values from matrix in R - r

Suppose this is the matrix I'm working with:
What is the R code I need to use to get the dimention coordinates of a value? Like, if I wanted to get the coordinates of where the value is '0' , it should return (A,A) , (B,B) , (C,C) , etc... I couldn't find an answer anywhere..

A crude way could be:
nms <- dimnames(distance)
mat<- which(distance == 0, TRUE)
cbind(nms[[1]][mat[,1]], nms[[2]][mat[,2]])
[,1] [,2]
[1,] "A" "A"
[2,] "B" "B"
[3,] "C" "C"
[4,] "D" "D"
[5,] "E" "E"
[6,] "F" "F"
[7,] "G" "G"
Or even
do.call(outer, c(dimnames(distance), paste))[which(distance == 0, TRUE)]
[1] "A A" "B B" "C C" "D D" "E E" "F F" "G G"
distance <- structure(c(0, 5, 6, 9, 10, 8, 8, 5, 0, 1, 10, 11, 7, 9, 6, 1,
0, 9, 10, 6, 8, 9, 10, 9, 0, 3, 7, 7, 10, 11, 10, 3, 0, 4, 4,
8, 7, 6, 7, 4, 0, 2, 8, 9, 8, 7, 4, 2, 0), .Dim = c(7L, 7L), .Dimnames = list(
c("A", "B", "C", "D", "E", "F", "G"), c("A", "B", "C", "D",
"E", "F", "G")))

We can use mapply + dinames + which like below (thank #Onyambu's data)
mapply(
`[`,
dimnames(distance),
data.frame(which(distance == 0, arr.ind = TRUE))
)
which gives
[,1] [,2]
[1,] "A" "A"
[2,] "B" "B"
[3,] "C" "C"
[4,] "D" "D"
[5,] "E" "E"
[6,] "F" "F"
[7,] "G" "G"

Related

How to print out the row names instead of their indices?

I have a matrix m and made some calculation on it, as the result I obtained a matrix ind. In the code below ind is the constant matrix.
k=10; n = 8
m <- matrix(c(1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1, 1, 0,
0, 0, 0, 0, 0, 0, 1, 0, 0, 1,
0, 0, 0, 0, 1, 0, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
0, 1, 1, 0, 0, 1, 0, 1, 0, 0), n, k, byrow = TRUE)
colnames(m)<-1:k; rownames(m)<-LETTERS[1:n]
# some calculation
ind <-matrix(c(
1, 1,
2, 2,
3, 6,
4, 7,
5, 8), 5, 2, byrow = TRUE)
I need to output the row names of m matrix instead of row indeces.
My attempt is:
noquote(rownames(m)[ind])
[1] A B C D E A B F G H
Expected result is:
[,1] [,2]
[1,] A A
[2,] B B
[3,] C F
[4,] D G
[5,] E H
You can use subsetting as follow:
rn = ind
rn[] <- rownames(m)[ind]
[,1] [,2]
[1,] "A" "A"
[2,] "B" "B"
[3,] "C" "F"
[4,] "D" "G"
[5,] "E" "H"
You can use apply
apply(ind, 2, function(x) rownames(m)[x])
# [,1] [,2]
#[1,] "A" "A"
#[2,] "B" "B"
#[3,] "C" "F"
#[4,] "D" "G"
#[5,] "E" "H"
Here is a solution as you expect it, with noquotes
noquote(matrix(rownames(m)[ind], nrow(ind)), right = T)
-output
[,1] [,2]
[1,] A A
[2,] B B
[3,] C F
[4,] D G
[5,] E H

What is attempt to apply non-function in r Matrix?

The Matrix
a<-matrix(c(2,3,-1)
(0,-2,4)
(0,-4,3),nrow = 3)
The Error
Error in matrix((c(2, 3, -1)(0, -2, 4))(0, -4, 3)) :
attempt to apply non-function
Do you want this?
> matrix(c(2, 3, -1, 0, -2, 4, 0, -4, 3), nrow = 3, byrow = TRUE)
[,1] [,2] [,3]
[1,] 2 3 -1
[2,] 0 -2 4
[3,] 0 -4 3

How shift values in rows in R (dplyr or data.table)?

Here is data set 'before' and 'after' shifting.
# Data set 'before'
df_before <- t(data.table(
x = c(1, 2, 3, 4, 5),
y = c(0, 6, 7, 8, 9),
z = c(0, 0, 11, 12, 13)))
# Shift operation
# ...
# Data set 'after'
df_after <- t(data.table(
x = c(1, 2, 3, 4, 5),
y = c(6, 7, 8, 9, NA),
z = c(11, 12, 13, NA, NA)))
How to make this kind of shifting on +1 cell only for all rows?
Thanks!
Something like this? Just start the rows always shifted by one and reset their length. The latter adds NAs.
t(sapply(1:nrow(DF), function(x) `length<-`(DF[x, x:ncol(DF)], ncol(DF))))
# [,1] [,2] [,3] [,4] [,5]
# [1,] 1 2 3 4 5
# [2,] 6 7 8 9 NA
# [3,] 11 12 13 NA NA
Data
DF <- structure(c(1, 0, 0, 2, 6, 0, 3, 7, 11, 4, 8, 12, 5, 9, 13), .Dim = c(3L,
5L), .Dimnames = list(c("x", "y", "z"), NULL))
Taking a guess at the logic:
t(apply(df_before, 1, function(x) `length<-`(x[x != 0], ncol(df_before))))
[,1] [,2] [,3] [,4] [,5]
x 1 2 3 4 5
y 6 7 8 9 NA
z 11 12 13 NA NA
You can un-transpose the df_before data.frame then use the lead function from dplyr
to shift the columns
library(data.table)
library(dplyr)
df_before <- data.table(
x = c(1, 2, 3, 4, 5),
y = c(0, 6, 7, 8, 9),
z = c(0, 0, 11, 12, 13))
df_after <- t(data.table(
x = c(1, 2, 3, 4, 5),
y = c(6, 7, 8, 9, NA),
z = c(11, 12, 13, NA, NA)))
df_before[] <-lapply(1:ncol(df_before), function(x){
dplyr::lead(df_before[[x]],n= x-1)
})
If you need to transpose the data after this step:
df_after2 <- t(df_before)
all.equal(df_after,df_after2) # TRUE

Split a vector using specific elements as delimiters

For example in the following vector I want to use the zero elements as delimiters
x <- c(12, 1, 2, 15, 18, 0, 15, 13, 14, 9, 1, 0, 22, 9, 14, 3, 9, 20)
and get (maybe in a list) the vectors
c(12, 1, 2, 15, 18)
c(15, 13, 14, 9, 1)
c(22, 9, 14, 3, 9, 20)
How would you do that in R?
For example:
splt <- cumsum(x == 0)
splt[x == 0] <- NA
split(x, splt)
# $`0`
# [1] 12 1 2 15 18
# $`1`
# [1] 15 13 14 9 1
# $`2`
# [1] 22 9 14 3 9 20
You may do like this,
x <- c(12, 1, 2, 15, 18, 0, 15, 13, 14, 9, 1, 0, 22, 9, 14, 3, 9, 20)
lapply(strsplit(paste(x, collapse = ";"), "^0;|;0$|;0;"), function(y) {strsplit(y, ";")})[[1]]
# [[1]]
# [1] "12" "1" "2" "15" "18"
# [[2]]
# [1] "15" "13" "14" "9" "1"
# [[3]]
# [1] "22" "9" "14" "3" "9" "20"
Another option is using rleid from library(data.table) to create the grouping variable and then split the values of 'x' that are not 0 (x[!!x]) with the grouping variable.
library(data.table)
split(x[!!x], rleid(!x)[!!x])

How to replace values with their mean?

I have two matrices
A = matrix(c(2, 2, 2, 3, 3, 3),nrow=3,ncol=2)
> A
[,1] [,2]
[1,] 2 3
[2,] 2 3
[3,] 2 3
B = matrix(c(2, 4, 3, 1, 5, 7),nrow=3, ncol=2)
> B
[,1] [,2]
[1,] 2 1
[2,] 4 5
[3,] 3 7
take the mean of all values in B that correspond to 3 in B:
Create a matrix with only the means:
Wanted matrix:
C
[,1] [,2]
[1,] 3 4.3
[2,] 3 4.3
[3,] 3 4.3
When the groups are not column specific this might help:
A <- matrix( c(2, 2, 2, 3, 3, 3),nrow=3,ncol=2)
B <- matrix(c(2, 4, 3, 1, 5, 7),nrow=3, ncol=2)
C <- matrix(nrow = dim(A)[1], ncol=dim(A)[2])
groups <- unique(c(A))
for(group in groups) {
C[which(A==group)] <- mean(B[which(A==group)])
}
If A contains NAvalues, then use
groups <- na.omit(unique(c(A)))
What about:
A <- matrix(c(2, 2, 2, 3, 3, 2, 3, 2), nrow=4, ncol=2)
B <- matrix(c(2, 4, 3, 1, 5, 7, 4, 2), nrow=4, ncol=2)
matrix(tapply(B, A, mean)[as.character(A)], nrow=nrow(A))
?

Resources