I would like to make a new matrix from another matrix but only with rows which do not contain 0, how can I do that?
Here is a more vectorized way.
x <- matrix(c(0,0,0,1,1,0,1,1,1,1), ncol = 2, byrow = TRUE)
x[rowSums(x==0)==0,]
I found that it could by done very simply
x <- matrix(c(0,0,0,1,1,0,1,1,1,1), ncol = 2, byrow = TRUE)
y <- cbind (x[which(x[,1]*x[,2] >0), 1:2])
I am only piecing together the great suggestions others have already given. I like the ability to store this as a function and generalize to values besides 1 including categorcal values (also selects positively or negatively using the select argument):
v.omit <- function(dataframe, v = 0, select = "neg") {
switch(select,
neg = dataframe[apply(dataframe, 1, function(y) !any(y %in% (v))), ],
pos = dataframe[apply(dataframe, 1, function(y) any(y %in% (v))), ])
}
Let's try it.
x <- matrix(c(0,0,0,1,1,0,1,1,1,1,NA,1), ncol = 2, byrow = TRUE)
v.omit(x)
v.omit(mtcars, 0)
v.omit(mtcars, 1)
v.omit(CO2, "chilled")
v.omit(mtcars, c(4,3))
v.omit(CO2, c('Quebec', 'chilled'))
v.omit(x, select="pos")
v.omit(CO2, c('Quebec', 'chilled'), select="pos")
v.omit(x, NA)
v.omit(x, c(0, NA))
Please do not mark my answer as the correct one as others have answered before me, this is just to extend the conversation. Thanks for the code and the question.
I'm sure there are better ways, but here's one approach. We'll use apply() and the all() function to create a boolean vector to index into the matrix of interest.
x <- matrix(c(0,0,0,1,1,0,1,1,1,1), ncol = 2, byrow = TRUE)
x
> x
[,1] [,2]
[1,] 0 0
[2,] 0 1
[3,] 1 0
[4,] 1 1
[5,] 1 1
> x[apply(x, 1, function(y) all(y > 0)) ,]
[,1] [,2]
[1,] 1 1
[2,] 1 1
Related
I have two matrices, one of them has a NA value and I want to use a function that only runs if there are NAs present in the data, so if I run the function it should only work on df2 and not df1. How would I do this?
df1 <- matrix(1:4, nrow = 2, ncol = 2)
df2 <- matrix(1,2,3,NA, nrow = 2, ncol = 2)
Based on the comment above, here is a complete answer (assuming I understand what you are getting at). The function is set up to do something or not to the matrix depending on whether it has NA values.
df1 <- matrix(1:4, nrow = 2, ncol = 2)
df2 <- matrix(c(1,2,3,NA), nrow = 2, ncol = 2)
myfunc <- function(m) {
ret <- m
if (all(!is.na(m))) {
print("This matrix has no NAs")
} else {
print("This matrix has NAs")
}
return(ret)
}
myfunc(df1)
# [1] "This matrix has no NAs"
# [,1] [,2]
# [1,] 1 3
# [2,] 2 4
myfunc(df2)
# [1] "This matrix has NAs"
# [,1] [,2]
# [1,] 1 3
# [2,] 2 NA
I have been googeling and stackoverflowing this for a while but I cant seem to find the right answer.
I have a matrix that contains different characters strings like "a", or "gamma", or even numbers coerced to characters.
How do I get the array indices of matrix m if an element of m matches a value in a vector of candiate values (note that these values could be any character string). Here is what I tried. I though which(m %in% ...) would do it but it doesnt return what I expected.
m <- matrix(c(0, "a", "gamma", 0, 0.5, 0, 0, 0, 0), ncol = 3)
m
#> [,1] [,2] [,3]
#> [1,] "0" "0" "0"
#> [2,] "a" "0.5" "0"
#> [3,] "gamma" "0" "0"
which(m == "a", arr.ind = TRUE) # as expected
#> row col
#> [1,] 2 1
which(m == "a" | m == "gamma", arr.ind = TRUE) # also obvious
#> row col
#> [1,] 2 1
#> [2,] 3 1
candidates <- c("a", "gamma", "b")
which(m %in% candidates, arr.ind = TRUE) # not what I expected
#> [1] 2 3
Created on 2019-09-11 by the reprex package (v0.3.0)
The result I want is the row and column index of elements in m that
match a value in candiates.
I prefer a base R solution if possible.
Any help?
The problem is that %in% doesn't preserve the dimensions of the input. You can write your own function that would do that. For example
`%matin%` <- function(x, table) {
stopifnot(is.array(x))
r <- x %in% table
dim(r) <- dim(x)
r
}
candidates <- c("a", "gamma", "b")
which(m %matin% candidates, arr.ind = TRUE)
# row col
# [1,] 2 1
# [2,] 3 1
MrFlick's solution is probably one of the best you'll get but if you must stick with in-built functions in base R, here's one way -
which(matrix(m %in% candidates, dim(m)), arr.ind = T)
row col
[1,] 2 1
[2,] 3 1
Another way with lapply and Reduce but above should be faster -
which(Reduce("|", lapply(candidates, function(x) m == x)), arr.ind = T)
row col
[1,] 2 1
[2,] 3 1
The following function is a variant of %in% that behaves more consistently with ==, this include the behavior with matrices, but also other classes, and it makes sure NAs stay NAs.
`%in{}%` <- function(x, table) {
table <- unlist(table)
if (is.list(x) && !is.data.frame(x)) {
x <- switch(
typeof(table),
logical = as.logical(x),
integer = as.integer(x),
double = as.double(x),
complex = as.complex(x),
character = as.character(x),
raw = as.raw(x))
}
# convert to character
if (is.factor(table)) {
table <- levels(table)[table]
}
if (is.data.frame(x)){
res <- sapply(x, `%in%`, table)
} else if (is.matrix(x)){
res <- apply(x, 2, `%in%`, table)
} else {
res <- x %in% table
}
res[is.na(x)] <- NA
res
}
m <- matrix(c(0, "a", "gamma", 0, 0.5, 0, 0, 0, 0), ncol = 3)
candidates <- c("a", "gamma", "b")
which(m %in{}% candidates, arr.ind = TRUE)
#> row col
#> [1,] 2 1
#> [2,] 3 1
How can I simply pad (append/prepend) a slice of NA's to a (say) 3D array along (say) dimension 2?
Suppose the initial array is given as
A <- array(1:8,c(2,2,2))
I initially thought this would work:
cbind(A,NA)
but it results in an 8x2 matrix instead of a 2x3x2 array. I then tried
abind(A,NA,along=2)
but that results in an error.
I'm hoping there is a much simpler solution than
dimSlice <- dim(A)
dimSlice[2] <- 1
abind(A,array(NA,dimSlice),along=2)
Background
This padding happens as part of a "remove slice and pad opposite side" operation that shifts an array by one position along some dimension, filling in with NA elements at the vacated positions. The one-dimensional equivalent would be, for example, c(A[-1],NA) for vector A, If there is a simple way to accomplish such an operation without an explicit padding sub-operation, that would be even better.
Subsetting with NAs results in NAs (?Extract):
v = 1:3; m = matrix(1:4, 2, 2); a = array(1:6, c(2, 2, 2))
v[c(NA, 1)]
#[1] NA 1
m[, c(2, NA)]
# [,1] [,2]
#[1,] 3 NA
#[2,] 4 NA
a[, c(1, 2, NA), ]
#, , 1
#
# [,1] [,2] [,3]
#[1,] 1 3 NA
#[2,] 2 4 NA
#
#, , 2
#
# [,1] [,2] [,3]
#[1,] 5 1 NA
#[2,] 6 2 NA
So, to pad with NAs, we could subset using the appropriate indices. Putting the above in a more general function to append/prepend "n" indices with NA in dimension "k" of an array:
pad = function(x, k, n = 1L, append = TRUE)
{
dims = replicate(length(dim(x)), substitute(), simplify = FALSE)
if(append) dims[[k]] = c((n + 1):dim(x)[[k]], rep_len(NA, n))
else dims[[k]] = c(rep_len(NA, n), 1:(dim(x)[[k]] - n))
do.call("[", c(list(x), dims))
}
arr = array(1:24, c(3, 2, 2, 2))
pad(arr, 1, 2, FALSE)
pad(arr, 2)
I'm sure this is trivial - nonetheless, any help would be appreciated.
The problem is simple: given a matrix, I'd like to get TRUE if the matrix in question has at least one element equal to zero. So, checking
A <- matrix(c(1, 2, 3, 4, 5, 0), nrow = 2, ncol = 3, byrow = TRUE)
> A
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 4 5 0
would return TRUE, while
B <- matrix(c(1, 2, 3, 4, 5, 6), nrow = 2, ncol = 3, byrow = TRUE)
> B
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 4 5 6
would return FALSE.
Something like
if ( A == 0 ) { cat("\nZero detected")}
gives a warning. Is there a simple way to do this?
The warning is generated because you're presenting a vector of logical to if, which expects a single value. any is a function to tell if any of the logical values are TRUE:
any(A==0)
## [1] TRUE
any(B==0)
## [1] FALSE
There's also a function all which determines if all of the values in a logical vector are TRUE.
Try
0 %in% A
It should return TRUE or FALSE. It works for NA too:
x = matrix(1:24, ncol = 4)
x[3, 3] = NA
NA %in% x
#TRUE
Given a matrix:
[,1] [,2]
[1,] 0 0.0
[2,] -1 0.8
What is the quickest way in R to iterate over the matrix and return the position of all non-zero entries as an index?
Here is one approach
mat = matrix(rnorm(9), 3, 3)
which(mat !=0, arr.ind = T)
m <- matrix(c(0, 1, 1, 0), nrow = 2)
which(m != 0)
or maybe
which(m != 0, TRUE)