Get column and row names of matrix indices in a vector - r

I have a 4x4 matrix and I want to identify elements of this matrix that are equal to a specific value such as 1. I want to save the indices of these elements as well as column and row names to two separate vectors. Finally, I want to write all of this information to a txt file.
I managed to get the indices to a txt file but I have no idea how to retrieve the column and row names from the matrix. To test, I am using following example:
mat <- matrix(c(1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6), ncol=4, nrow=4)
colnames(mat) <- c("C1","C2","C3","C4")
rownames(mat) <- c("R1", "R2","R3","R4")
r.indices <- c()
c.indices <- c()
for (row in 1:nrow(mat)){
for (col in 1:(ncol(mat)-row+1)){
if (mat[row,col] == cutoff){
#print("this is one!")
r.indices <- c(r.indices,row)
c.indices <- c(c.indices,col)
}
}
}
write.csv(cbind(r.indices, c.indices), file="data.txt")

The which function already provides a nice interface to getting all the row and column indices of a matrix that meet a certain criterion, using the arr.ind=TRUE argument. This is both much less typing and much more efficient than looping through each matrix element. For instance, if you wanted to get all the indices where your matrix equaled 5, you could use:
(idx <- which(mat == 5, arr.ind=TRUE))
# row col
# R1 1 2
# R3 3 4
Now all that remains is a simple lookup using the row and column names of your matrix:
cbind(rownames(mat)[idx[,"row"]], colnames(mat)[idx[,"col"]])
# [,1] [,2]
# [1,] "R1" "C2"
# [2,] "R3" "C4"
You could write this result out to a file using write.csv.

Related

Creating vectors with different names in for loop using R

I want to create vectors having a different character name in a loop but without indexing them to a number as it is shown in this post.
The names I want for the vectors are already in a vector I created.
Id <- c("Name1","Name2")
My current code creates a list
ListEx<- vector("list", length(Id))
## add names to list entries
names(ListEx) <- Id
## We run the loop
for (i in 1:length(Id)){
ListEx[[i]]<-getbb(Id[i])
}
##The getbb function returns a 2x2 matrix with the maximum
#and the minimum of the latitute/longitude of the city (which name is "Namei")
## Check the values of a matrix inside the list
ListEx[["Name1"]]
I woud like to have Name1 as a vector containing the values of ListEx[["Name1"]]
You are just missing one line of code. I have created a dummy function that creates a 2x2 matrix here:
Id <- c("Name1","Name2")
ListEx<- vector("list", length(Id))
## add names to list entries
names(ListEx) <- Id
f <- function(v) { return(matrix(rnorm(4), nrow=2))}
## We run the loop
for (i in 1:length(Id)){
ListEx[[i]]<-f(Id[i])
}
## Check the values of a matrix inside the list
ListEx[["Name1"]]
list2env(ListEx, globalenv()) # This is the relevant line
Name1
# [,1] [,2]
# [1,] -0.4462014 0.3178423
# [2,] 1.8384113 0.7546780
Name2
# [,1] [,2]
# [1,] -1.3315121 2.1159171
# [2,] 0.2517896 0.1966196

How do you calculate the sum of a specific row in a list of matrices

I have data in matrices and the matrices are stored in a list, and I want the sum of the a specific row in each matrix.
some example data
A1<-matrix(0:9, nrow=5, ncol=2)
A2<-matrix(10:19, nrow=5, ncol = 2)
A3<-matrix(20:29, nrow=5, ncol = 2)
Mylist<-list(A1, A2, A3)
I can get the sum of all rows in each matrix with
lapply(Mylist, function(x) apply(x, 1, sum) )
but I only want the sum of a specific row, could be row 1, could be row 4, depending on what I want to look at. I know I can read it off of the results I generate with the code above but I want a cleaner solution that only gives me the results. Thanks
You can use purrr:map().
If you know the output type (in this case, seems to be all integers), you can be more specific, like map_int(). With map() you'll get a list back, with a specific map version, like map_int(), you get a vector back instead.
library(tidyverse)
ix <- 3 # let's say we want the sum of the third row
map_int(Mylist, ~sum(.x[ix, ]))
[1] 9 29 49
If the row index you care about changes per matrix, you can use map2() instead, which takes two inputs of the same length:
ixs <- c(1, 2, 3)
map2_int(Mylist, ixs, ~sum(.x[.y, ]))
[1] 5 27 49
Alternately, if you need to work in base R, you can just take the desired index (here, ix) of sum(), you don't need apply() inside lapply():
lapply(Mylist, function(x) sum(x[ix, ]))
[[1]]
[1] 9
[[2]]
[1] 29
[[3]]
[1] 49
one.row.sum <- function(df, row.num) lapply(Mylist, function(df) sum(df[row.num, ]))
one.row.sum(Mylist, 1)
[[1]]
[1] 5
[[2]]
[1] 25
[[3]]
[1] 45

subsetting values of matrix with a vector (conditions)

I have the following matrices :
> matrix <- matrix(c(1,3,4,NA,NA,NA,3,0,4,6,0,NA,2,NA,NA,2,0,1,0,0), nrow=5,ncol=4)
> n <- matrix(c(1,2,5,6,2),nrow=5,ncol=1)
As you can see, for each rows I have
multiple NAs - the number NAs is undefined
ONE single "0"
I would like to subset the 0 for the values of the n. Intended output below.
> output <- matrix(c(1, 3, 4,NA,NA,NA,3,5,4,6,1,NA,2,NA,NA,2,2,1,6,2), nrow=5,ncol=4)
I have tried the following
subset <- matrix == 0 & !is.na(matrix)
matrix[subset] <- n
#does not give intended output, but subset locates the values i want to change
When used on my "real" data i get the following message :
Warning message: In m[subset] <- n : number of items to replace is not
a multiple of replacement length
Thanks
EDIT : added a row to the matrix, as my real life problem is with an unbalanced matrix. I am using Matrices and not DF here, because i think (not sure)that with very large datasets, R is quicker with large matrices rather than subsets of dataframes.
We can do this using
out1 <- matrix+n[row(matrix)]*(matrix==0)
identical(output, out1)
#[1] TRUE
It appears you want to replace the values by row, but subsetting is replacing the values by column (and maybe that's not a completely thorough explanation). Transposing the matrix will get the desired output:
matrix <- t(matrix)
subset <- matrix == 0 & !is.na(matrix)
matrix[subset] <- n
matrix <- t(matrix)
setequal(output, matrix)
[1] TRUE
You can try this option with ifelse:
ifelse(matrix == 0, c(n) * (matrix == 0), matrix)
# [,1] [,2] [,3] [,4]
#[1,] 1 NA 1 2
#[2,] 3 NA NA 2
#[3,] 4 3 5 NA
#[4,] NA 6 NA 2
zero = matrix == 0
identical(ifelse(zero, c(n) * zero, matrix), output)
# [1] TRUE

Keep column name when select one column from a data frame/matrix in R

In R, when I select only one column from a data frame/matrix, the result will become a vector and lost the column names, how can I keep the column names?
For example, if I run the following code,
x <- matrix(1,3,3)
colnames(x) <- c("test1","test2","test3")
x[,1]
I will get
[1] 1 1 1
Actually, I want to get
test1
[1,] 1
[2,] 1
[3,] 1
The following code give me exactly what I want, however, is there any easier way to do this?
x <- matrix(1,3,3)
colnames(x) <- c("test1","test2","test3")
y <- as.matrix(x[,1])
colnames(y) <- colnames(x)[1]
y
Use the drop argument:
> x <- matrix(1,3,3)
> colnames(x) <- c("test1","test2","test3")
> x[,1, drop = FALSE]
test1
[1,] 1
[2,] 1
[3,] 1
Another possibility is to use subset:
> subset(x, select = 1)
test1
[1,] 1
[2,] 1
[3,] 1
The question mentions 'matrix or dataframe' as an input. If x is a dataframe, use LIST SUBSETTING notation, which will keep the column name and will NOT simplify by default!
`x <- matrix(1,3,3)
colnames(x) <- c("test1","test2","test3")
x=as.data.frame(x)
x[,1]
x[1]`
Data frames possess the characteristics of both lists and matrices: if you subset with a single vector, they behave like lists; if you subset with two vectors, they behave like matrices.
There's an important difference if you select a single
column: matrix subsetting simplifies by default, list
subsetting does not.
source: See http://adv-r.had.co.nz/Subsetting.html#subsetting-operators for details

How do I retrieve a matrix column and row name by a matrix index value?

So let's say I have a matrix, mdat and I only know the index number. How do I retrieve the column and row names? For example:
> mdat <- matrix(c(1,2,3, 11,12,13), nrow = 2, ncol=3, byrow=TRUE,
dimnames = list(c("row1", "row2"), c("C.1", "C.2", "C.3")))
> mdat[4]
[1] 12
> names(mdat[4])
NULL
> colnames(mdat[4])
NULL
> rownames(mdat[4])
NULL
> dimnames(mdat[4])
NULL
First you need to get the row and column of that index using arrayInd.
k <- arrayInd(4, dim(mdat))
You can then get the right name by getting that element of the row and column names
rownames(mdat)[k[,1]]
colnames(mdat)[k[,2]]
Or both at once using mapply:
mapply(`[[`, dimnames(mdat), k)
Subsetting the matrix first results in a one-element vector that has no names, as you show in your question. Remember that subsetting creates a completely new object via copying. There's no way to reference the original mdat after subsetting.
This is more clear if you assign the result of subsetting to another object.
> m <- mdat[4]
> m
[1] 12
> names(m) # no names were printed above... so
NULL
You really want to access the column/row names first and subset them.
> colnames(mdat)[3]
[1] "C.3"
> rownames(mdat)[2]
[1] "row2"
You can re-assign column/row names similarly.
> colnames(mdat)[3] <- "C3"
> rownames(mdat)[2] <- "row.2"
> mdat
C.1 C.2 C3
row1 1 2 3
row.2 11 12 13

Resources