I want to take a logical matrix and and all of the columns in the matrix together to create a vector. An example:
a = c(TRUE, TRUE, FALSE, TRUE, FALSE, FALSE)
A = matrix(a, nrow = 3, ncol = TRUE, byrow = TRUE)
I would like to produce
[1] TRUE FALSE FALSE
Currently I am doing this with
apply(A, 1, function(x) Reduce('&', x))
However, this goes very slow with the size of my input, and I was wondering if there was a more efficient way to do this.
It will be faster to use:
apply(A,1,all)
instead of a call to Reduce.
Also, the rowSums function is equivalent to apply(x,1,sum) but much faster, so it will probably be even faster to do:
rowSums(A)==ncol(A)
Instead of using Reduce within apply, an option would be to either convert the 'A' to data.frame and then do
Reduce(`&`, as.data.frame(A))
#[1] TRUE FALSE FALSE
Or split by col and then
Reduce(`&`, split(A, col(A)))
#[1] TRUE FALSE FALSE
Related
I'm new to R and I've got a question:
choice <- c(TRUE, FALSE, FALSE, FALSE)
rep(sample(choice, size = 4, replace=FALSE), times = n)
always repeats the same vector, e.g. (FALSE, TRUE, FALSE, FALSE)
However, I want to have n different random samples of the vector choice in a new vector (replace must be FALSE, because only 1 in 4 elements should be TRUE).
Which function should I choose? I'm not allowed to use for-loops.
You can use replicate. It returns a matrix, which you can then turn into a vector.
choice <- c(TRUE, FALSE, FALSE, FALSE)
n <- 3
set.seed(42) # for reproducibility
as.vector(replicate(n, sample(choice, size = 4, replace=FALSE)))
#[1] FALSE FALSE TRUE FALSE FALSE FALSE FALSE TRUE FALSE FALSE TRUE FALSE
I have a 3D array of this form
n_rep<-1000
n_box<-9
pert<-array(,dim=c(9,4,n_rep), dimnames=list(box=LETTERS[1:n_box],perturbation=c('p1','p2','p3','p4'),replicate=1:n_rep))
set.seed(1235)
pert[,1,]<-round(runif(n_rep*n_box,-1,1),0)
pert[,2,]<-round(runif(n_rep*n_box,-2,2),0)
pert[,3,]<-round(runif(n_rep*n_box,-3,3),0)
pert[,4,]<-round(runif(n_rep*n_box,-4,4),0)
and I want to apply a function (e.g. MyFun) to each column of each "layer" of the array.
MyFun takes an argument that is a vector of 9 numbers (i.e. here the rows of the array) on which it does some operation. The function could be something like:
MyFun<- function(vect=NULL){
res<-sum(10+vect)
return(res)
}
So basically, I want to apply MyFun cycling through both the dimensions 'perturbation' and 'replicate' (i.e. the columns and the 3rd dimension respectively). Such as:
MyFun(vect=pert[,1,1])
MyFun(vect=pert[,2,1])
MyFun(vect=pert[,3,1])
MyFun(vect=pert[,4,1])
MyFun(vect=pert[,1,2])
MyFun(vect=pert[,2,2])
and so fort.
Is there a way to use apply to do this in a single call or should I nest 2 apply function (i.e. one that cicle through the columns and the other over the 3rd dimension)?
We can use apply with MARGIN specified as 2 and 3
out <- apply(pert, c(2, 3), FUN = MyFun)
which can also done with nested loops
out1 <- t(sapply(seq_len(dim(pert)[2]), function(j)
sapply(seq_len(dim(pert)[3]), function(k) MyFun(pert[, j, k]))))
all.equal(out, out1, check.attributes = FALSE)
#[1] TRUE
-checking
identical(out[1,1], MyFun(vect=pert[,1,1]))
#[1] TRUE
identical(out[4,1], MyFun(vect=pert[,4,1]))
#[1] TRUE
identical(out[2,2], MyFun(vect=pert[,2,2]))
#[1] TRUE
Am I missing a better way of doing this - or at least a way that allows to vary the window size?
Say I have a vector, v.
v <- c(T,T,F,F,F,F,F,T,T,T,T,F,F,F,F,T,F,F,F,F,F,F,T,F)
I wish to convert this vector such that FALSEs are turned to TRUEs if a TRUE appeared within the previous 3 elements. e.g. the F's at positions 3,4,5 would also switch to T's as there is a T at position 2. The F at position 6 would not.
Solution if only interested in a window of 3:
vlag1 <- lag(v)
vlag2 <- lag(vlag1)
vlag3 <- lag(vlag2)
ifelse(v==T|vlag1==T|vlag2==T|vlag3==T,T,F)
Gives the desired result:
TRUE TRUE TRUE TRUE TRUE FALSE FALSE TRUE TRUE TRUE TRUE TRUE TRUE TRUE FALSE TRUE TRUE TRUE TRUE FALSE FALSE FALSE TRUE TRUE
But what if we wanted to vary the window to e.g. 4 or 5 - is there a better way?
You could do this with rollapply from the zoo package:
library(zoo)
rollapply(v,
width = 4, align = "right", partial = TRUE,
FUN = function(x) ifelse(TRUE %in% x, TRUE, FALSE))
Note that I have set width = 4 here, not 3. In your question, you said you wanted to check the previous 3 elements. Width includes the ith element. So, if you want to base the result on the previous 3, you have to set width to 4. You also need to include align = "right" to look back from the ith element (the default centers on the ith element, and you can also look ahead with align = "left").
This is a more manual solution:
# Input vector
v <- c(T,T,F,F,F,F,F,T,T,T,T,F,F,F,F,T,F,F,F,F,F,F,T,F)
# Size of the window
k <- 3
# Output vector
outp <- rep(F,length(v))
for(i in seq(length(v))){
# Checking values on variable window
aux <- v[seq(pmax(1,i-k),i)]
# Writing on output vector
outp[i] <- any(aux==T)
}
outp
Here is one option with data.table
library(data.table)
n <- 3
r1 <- Reduce(`|`, shift(v, seq_len(n), fill = FALSE))
identical(r1, r2)
#[1] TRUE
where 'r2' is the OP's output from ifelse
I'm new to R and I've got a question:
choice <- c(TRUE, FALSE, FALSE, FALSE)
rep(sample(choice, size = 4, replace=FALSE), times = n)
always repeats the same vector, e.g. (FALSE, TRUE, FALSE, FALSE)
However, I want to have n different random samples of the vector choice in a new vector (replace must be FALSE, because only 1 in 4 elements should be TRUE).
Which function should I choose? I'm not allowed to use for-loops.
You can use replicate. It returns a matrix, which you can then turn into a vector.
choice <- c(TRUE, FALSE, FALSE, FALSE)
n <- 3
set.seed(42) # for reproducibility
as.vector(replicate(n, sample(choice, size = 4, replace=FALSE)))
#[1] FALSE FALSE TRUE FALSE FALSE FALSE FALSE TRUE FALSE FALSE TRUE FALSE
I have a matrix and a vector with values:
mat<-matrix(c(1,1,6,
3,5,2,
1,6,5,
2,2,7,
8,6,1),nrow=5,ncol=3,byrow=T)
vec<-c(1,6)
This is a small subset of a N by N matrix and 1 by N vector. Is there a way so that I can subset the rows with values in vec?
The most straight forward way of doing this that I know of would be to use the subset function:
subset(mat,vec[,1] == 1 & vec[,2] == 6) #etc etc
The problem with subset is you have to specify in advance the column to look for and the specific combination to do for. The problem I am facing is structured in a way such that I want to find all rows containing the numbers in "vec" in any possible way. So in the above example, I want to get a return matrix of:
1,1,6
1,6,5
8,6,1
Any ideas?
You can do
apply(mat, 1, function(x) all(vec %in% x))
# [1] TRUE FALSE TRUE FALSE TRUE
but this may give you unexpected results if vec contains repeated values:
vec <- c(1, 1)
apply(mat, 1, function(x) all(vec %in% x))
# [1] TRUE FALSE TRUE FALSE TRUE
so you would have to use something more complicated using table to account for repetitions:
vec <- c(1, 1)
is.sub.table <- function(table1, table2) {
all(names(table1) %in% names(table2)) &&
all(table1 <= table2[names(table1)])
}
apply(mat, 1, function(x)is.sub.table(table(vec), table(x)))
# [1] TRUE FALSE FALSE FALSE FALSE
However, if the vector length is equal to the number of columns in your matrix as you seem to indicate but is not the case in your example, you should just do:
vec <- c(1, 6, 1)
apply(mat, 1, function(x) all(sort(vec) == sort(x)))
# [1] TRUE FALSE FALSE FALSE FALSE