combine two vectors using cbind and either or argument - r

I have a simple question but don't know how to do it myself. I have two vectors where each contains '0' and '1' numeric values. My aim is to combine two vectors as one, and have something like this:
A <- c(1,1,0,0,0,1)
B <- c(0,1,1,0,0,1)
after combining two:
C <- c(1,1,1,0,0,1)
Basically, if either of them has 1, then it should be combined as 1, if both of them have 1, then it should be 1 too, if none of them have 1, then it should be 0.
Hope you can answer
Thank you much!
-G

We can use pmax to get the output
pmax(A, B)
Or with | to coerce the binary vectors to a logical vector and then change it to binary with + or (as.integer)
+(A|B)
#[1] 1 1 1 0 0 1

Related

R condtional replace in a 3d array

I want to conditionally replace values in a specific vector in a 3d array, the replacement value being a value from a probability calculation. For some reason the replacement value is the same for all values of the vector, rather than being calculated on an individual vector element basis. I must have something simple incorrect in my syntax
library (abind)
pop <- array(c (1,0,1,1,1,0,0,0,0,0,2,0,2,3,5), dim = c(1,5,3))
pop <- abind(pop,pop, along = 1)
so the particular vector I want to work on is
pop[dim(pop)[1], ,1]
[1] 1 0 1 1 1
what I want to achieve is to leave the zero value alone, and if the value is one, then run a random binomial test, to see if it changes to zero, and if it does change, do the insertion. I'm told that the ifelse is vectorized but with this syntax it is not operating individually on each element of the vector. When I try to produce a new vector as such
ifelse (pop[dim(pop)[1], ,1] == 1, rbinom(1,1,0.5), 0)
I get either no change
> ifelse (pop[dim(pop)[1], ,1] == 1, rbinom(1,1,0.5), 0)
[1] 1 0 1 1 1
or alternatively it changes all values.
> ifelse (pop[dim(pop)[1], ,1] == 1, rbinom(1,1,0.5), 0)
[1] 0 0 0 0 0
I'm expecting some of the values in the array to be changed, but not "all or nothing". What am I doing wrong? Also if there is a simple elegant way to do the substitution back into the original 3d array I'd be grateful. Thx. J
I think I did find a solution using the "modify_if" function of the dplyr package.
pop[dim(pop)[1], ,1] %<>% modify_if(~ .x == 1, ~ rbinom(1,1,pliv1))
HTH, J

How to find if two or more continuously elements of a vector are equal in R

I want to find a way to determine if two or more continuously elements of a vector are equal.
For example, in vector x=c(1,1,1,2,3,1,3), the first, the second and the third element are equal.
With the following command, I can determine if a vector, say y, contains two or more continuously elements that are equal to 2 or 3
all(rle(y)$lengths[which( rle(y)$values==2 | rle(y)$values==3 )]==1)
Is there any other faster way?
EDIT
Let say we have the vector z=c(1,1,2,1,2,2,3,2,3,3).
I want a vector with three elements as output. The first element will refer to value 1, the second to 2 and the third one to 3. The values of the elements of the output vector will be equal to 1 if two or more continuously elements of z are the same for one value of 1,2,3 and 0 otherwise. So, the output for the vector z will be (1,1,1).
For the vector w=c(1,1,2,3,2,3,1) the output will be 1,0,0, since only for the value 1 there are two continuously elements, that is in the first and in the second position of w.
I'm not entirely sure if I'm understanding your question as it could be worded better. The first part just asks how you find if continuous elements in a vector are equal. The answer is to use the diff() function combined with a check for a difference of zero:
z <- c(1,1,2,1,2,2,3,2,3,3)
sort(unique(z[which(diff(z) == 0)]))
# [1] 1 2 3
w <- c(1,1,2,3,2,3,1)
sort(unique(w[which(diff(w) == 0)]))
# [1] 1
But your edit example seems to imply you are looking to see if there are repeated units in a vector, of which will only be the integers 1, 2, or 3. Your output will always be X, Y, Z, where
X is 1 if there is at least one "1" repeated, else 0
Y is 2 if there is at least one "2" repeated, else 0
Z is 3 if there is at least one "3" repeated, else 0
Is this correct?
If so, see the following
continuously <- function(x){
s <- sort(unique(x[which(diff(x) == 0)]))
output <- c(0,0,0)
output[s] <- s
return(output)
}
continuously(z)
# [1] 1 2 3
continuously(w)
# [1] 1 0 0
Assuming your series name is z=c(1,1,2,1,2,2,3,2,3,3) then you can do:
(unique(z[c(FALSE, diff(z) == 0)]) >= 0)+0 which will output to 1, 1, 1,
When you run the above command on your other sequenc:
w=c(1,1,2,3,2,3,1)
then (unique(w[c(FALSE, diff(w) == 0)]) >= 0)+0 will return to 1
You may also try this for an exact output like 1,1,1 or 1,0,0
(unique(z[c(FALSE, diff(z) == 0)]) == unique(z))+0 #1,1,1 for z and 1,0,0 for w
Logic:
diff command will take difference between corresponding second and prior items, since total differences will always 1 less than the number of items, I have added first item as FALSE. Then subsetted with your original sequences and for boolean comparison whether the difference returned is zero or not. Finally we convert them to 1s by asking if they are greater than or equal to 0 (To get series of 1s, you may also check it with some other conditions to get 1s).
Assuming your sequence doesn't have negative numbers.

Changing values at specific indices - R

I have two vectors a & b.
a <- c(1,0,1,0,0,0,1)
b <- c(.2,.9,.3,.9,.8,.78,.3)
and I want to subtract 1 from all values in b that correspond to indices for 1 in a. I can extract the indices of all values that are 1 in a by doing which(a == 1). I tried doing something like b <- 1 - b[which(a == 1)] but this didn't work. Is there some way to do this without using a for loop?
We can convert the binary vector 'a' to logical by double negation (!! - converts 1 to TRUE and 0 to FALSE) or by just wrapping with as.logical or as in the OP's code (a==1). This will subset the values in 'b' that corresponds to TRUE/1 in 'a'. Subtract 1 from those values and assign the output back to those values in 'b'
b[a==1] <- 1 - b[a==1]
Or we can use ifelse
ifelse(a==1, 1-b, b)
In the OP's code, wrapping with which is not needed and also assigning to 'b' with a subset of elements of 'b' replaces the original vector 'b' with the subset 'b'
Your a vector is 0's and 1's. If you want to subtract 1 from b whenever a is 1, and do nothing (aka subtract 0) from b whenever a is 0, then this is just subtraction:
b - a
If your a vector has values other than 0 or 1, then you'll need a slightly more complicated, more general method as in #akrun's answer.
Another "more complex" variant would use the implicit meaning of TRUE as 1 and FALSE as 0 to do
b - (a == 1)
Upon re-reading, you might need to clarify what you want. Your text says subtract 1 from all values in b, which implies b - (1 or 0). However, you code attempt is 1 - b, subtracting b from 1 not 1 from b, in which case akrun's answer is perfect and mine would need some adjustments.

Number of overlapping elements

I've got two vectors:
vec1 <- c(1,0,1,1,1)
vec2 <- c(1,1,0,1,1)
The vectors have the same elements at position 1, 4 and 5.
How can I return the number of elements that overlap in 2 vectors taking the position into account? So, here I would like to return the number 3.
Test for equality, then sum, you might want to exclude NAs:
sum(vec1==vec2, na.rm=TRUE)
EDIT
Exclude 0==0 matches, by adding an exclusion like:
sum(vec1==vec2 & vec1!=0, na.rm=TRUE)
Thanks to #CarlWitthoft
Or, if you have only ones and zeros, then:
sum((vec1+vec2)==2, na.rm=TRUE)
If your entries are only 0 and 1 (or if you are only interested in 0 and anything that is not 0) you can use xor to determine where they differ and then sum its negation, otherwise you would have to test for equality as #zx8754 commented:
sum(!xor(vec1,vec2))
[1] 3

Select matrix column (resp. row) as Nx1 (resp. 1xD) matrix, as opposed to vector

Let X be an N by D matrix. Selecting a submatrix of size n by d returns a matrix of those dimensions unless at least one of n and d equals 1, in which case we get a vector instead. Interestingly, R still returns a matrix of the correct dimensions even if one of n and d are 0, and the other not 1.
Now, if we are certain that n!=1, then executing cbind(X[row.subset,col.subset]) will return a matrix of the correct dimensions regardless of whether d==1 or not (here n=length(row.subset) and d=length(col.subset)). If we are certain that d!=1, then we can use rbind(...). But if both n and d can be 1, neither approach will work since we could accidentally turn a row into a column or vice versa.
As far as I can tell, one way to always get a matrix of the right dimensions is to call matrix(X[row.subset,col.subset],nrow=n,ncol=d). However, it doesn't feel like that should be the right way to go about it, plus I'm not confident that there is no performance penalty. Is there a more "native" solution?
Here's a working example:
N <- 6
D <- 3
X <- matrix(rnorm(N*D),ncol=D)
dim(X[1:2,1:2]) #returns 2 2
dim(X[1:2,1]) #returns NULL, this is a vector
dim(cbind(X[1:2,1])) #returns 2 1
dim(cbind(X[1,1:2])) #returns 2 1, but we'd like it to be 1 2
dim(rbind(X[1,1:2])) #returns 1 2
dim(rbind(X[1:2,1])) #returns 1 2, but we'd like it to be 2 1
row.subset <- 1:4
col.subset <- 2
#I _think_ this is always correct, but it's verbose:
matrix(X[row.subset,col.subset],nrow=length(row.subset),ncol=length(col.subset))
Thanks in advance.
If you don't want to simplify matrix subsets to vectors just tell [ not to drop dimensions:
> dim(X[1:2,1, drop=FALSE])
[1] 2 1
> dim(X[1,1:2, drop=FALSE])
[1] 1 2
See ?"[" for details.

Resources