Comparing Vectors Values: 1 element with all other - r

I'm wondering how I can compare 1 element of a vector with all elements in the other vector. As an example: suppose
x <- c(1:10)
y <- c(10,11,12,13,14,1,7)
Now I can compare the elements parewise
x == y
[1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
But I want to compare all elements of y with a specific element of x, something like
x[7] == y
[1] FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
Is this possible?

Do you mean something like this?
x <- 1:10
y <- c(10,7,11,12,13,14,15,16,17,18)
res <- outer(x, y, `==`)
colnames(res) <- paste0("y=", y)
rownames(res) <- paste0("x=", x)
Which gives you the following matrix:
y=10 y=7 y=11 y=12 y=13 y=14 y=15 y=16 y=17 y=18
x=1 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
x=2 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
x=3 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
x=4 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
x=5 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
x=6 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
x=7 FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
x=8 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
x=9 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
x=10 TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
If you want the dimnames to be as y[1] use
colnames(res) <- paste0("y[", seq_along(y), "]")
rownames(res) <- paste0("x[", seq_along(x), "]")
which gives you:
y[1] y[2] y[3] y[4] y[5] y[6] y[7] y[8] y[9] y[10]
x[1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
x[2] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
x[3] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
x[4] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
x[5] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
x[6] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
x[7] FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
x[8] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
x[9] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
x[10] TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
To get the index use which as follows:
which(res)
[1] 10 17
As R saves matrices rowwise this results in 10 and 17.
If you want the index in x and y component use:
which(res, arr.ind = TRUE)
row col
x=10 10 1
x=7 7 2

If you want to compare each element of x to y, usually one of the 'apply' functions will help.
As follows:
x <- c(1:10)
y <- c(10,11,12,13,14,1,7)
sapply(x,function(z){z==y})
Column i in the output is result from x[i]==y.
Is this what you're looking for?

Related

Logical vector to see wether an element of a df is contained within a df inside a List

I tried:
mdf$CLAVE.EMISORA %in% BMV[[9]]$`CLAVE EMISORA`
But it only returns:
logical(0)
For some reason the reveres seems to work:
BMV[[9]]$`CLAVE EMISORA` %in% mdf$CLAVE.EMISORA
[1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[20] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[39] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[58] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[77] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
My data (mdf): I have it but I don't know how to embed
My list (BMV): .... I don't know how to copy a list to clipboard sorry...
logical(0) is a vector of base type logical with 0 length.
You're getting this because your trying to check if any element in a vector of length 0 is present in BMV[[9]]$'CLAVE EMISORA'
if you run
length(mdf$CLAVE.EMISORA)
You'll get 0 as output
Reverse works because you're checking if any element from a vector of a non-zero length is present in a vector of 0 length.

create numeric vector based on values in logic vector- R

I have a logic vector in R something like this:
[1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE
[19] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[37] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[55] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[73] FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
I want to construct another numeric vector that contains a 1 if the logic vector is true and a 0 if it is false. I have tried the following code
## create an empty vector
numericvec <- vector(mode="numeric", length=0)
## for loop
for (i in logicvec){
if(i == TRUE){
c(numericvec, 1)
} else {
c(numericvec, 0)
}
}
The for loop syntax seems ok because I don't get errors when I run it but it isn't currently adding any values to the numeric vector.
This should work:
numericvec <- as.numeric(logicvec)
No need for a for() loop. R typically operates on entire columns.

Splitting data based on time condition

I have rows of data that are seconds apart, however I found some anomalies. The difference between some rows is 30min or above, so I want to split my data to multiple other data frames at that condition which means loop through my data frame and split when the difference in time is above 30min. I’ve tried this already but it splits my data to one row data frame.
RBD < - function(x){
i <- 0
while(i < length(data$Time)){
if(data$Time[i+1]-data$Time[i] > 60*30){
rb <- 1
}
else{
rb<-0
}
i <- i+1
}
}
ListData <- Data %>%
group_by(Data$temp)%>%
transmute(ind=all((RBD = 1))%>%
.$ind
names(ListData) <- paste0(‘Data’, seq_along(ListData))
split(Data, ListData)
My Data looks like this
Data
There's a very helpful function in base R: diff, which can do the heavy lifting for you. If this doesn't work for you, try posting a reprex and I'll see if i can help you troubleshoot.
Lets simulate some data:
set.seed(123)
x <- sample(1200, 100)
x <- x + sample(c(0, 0, 0, 0, 2400), 100, replace = TRUE)
RBD <- function(x){
res <- lag(x) > 60*30
res[1] <- FALSE
res
}
RBD(x)
# [1] FALSE FALSE FALSE FALSE TRUE FALSE TRUE TRUE FALSE FALSE FALSE TRUE
# [13] FALSE FALSE TRUE FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE
# [25] FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE TRUE FALSE FALSE FALSE
# [37] FALSE TRUE FALSE TRUE FALSE FALSE FALSE FALSE FALSE TRUE FALSE FALSE
# [49] FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
# [61] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
# [73] FALSE TRUE FALSE FALSE FALSE FALSE FALSE TRUE FALSE TRUE FALSE FALSE
# [85] FALSE FALSE FALSE FALSE FALSE TRUE TRUE FALSE FALSE TRUE FALSE TRUE
# [97] FALSE FALSE FALSE FALSE

Create a logical or binary matrix/data.frame from a list of factors in R

I have a list of approximately 2 million elements. The list is made up of vectors of character strings. There are about 50 different character strings so can be considered factors. The vectors of character strings are different lengths varying between 1 and 50 (i.e the total number of character strings).
I want to convert the list to a logical or binary matrix/data.frame. Currently my method involves lapply and is incredibly slow, I would like to know if there is a vectorised approach.
require(dplyr); require(tidyr)
#create test data set
set.seed(123)
list1 <- list()
ListLength <-10
elementlength <- sample(1:5, ListLength, replace = TRUE )
for(i in 1:length(elementlength) ){
list1[[i]] <- sample(letters[1:15], elementlength[i])
}
#Create data frame from list using lapply
lapply(list1, function(n){
data.frame(type = n, value = TRUE) %>%
spread(., key = type, value )
}) %>% bind_rows()
I don't know if there is a way by preallocating the data frame then filling it in somehow.
Type <- unique(unlist(list1, use.names = FALSE))
#Create empty dataframe
TypeMat <- data.frame(matrix(NA,
ncol = length(Type),
nrow = ListLength)) %>%
setNames(Type)
We could use mtabulate from qdapTools
library(qdapTools)
mtabulate(list1)!=0
# a b c d e f g h i j k l m o
#[1,] FALSE FALSE FALSE FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE TRUE
#[2,] FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE TRUE FALSE TRUE FALSE FALSE TRUE
#[3,] TRUE FALSE FALSE TRUE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
#[4,] FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE FALSE TRUE TRUE FALSE TRUE TRUE
#[5,] FALSE FALSE FALSE TRUE FALSE FALSE FALSE TRUE FALSE TRUE FALSE FALSE TRUE TRUE
#[6,] FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
#[7,] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE FALSE FALSE FALSE TRUE TRUE
#[8,] TRUE FALSE TRUE FALSE FALSE FALSE TRUE FALSE FALSE TRUE FALSE TRUE FALSE FALSE
#[9,] FALSE TRUE FALSE TRUE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
#[10,]FALSE FALSE FALSE FALSE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE

Finding vector elements with a length longer than 1 in R

I have a vector like this
c(0,1,2,0,0,2,2,2,2,2,2,1,0,1,2,2,2,2,2,1)
I would like to find the position where a series of at least three consecutive 2's, c(2,2,2), starts and if it is interupted I would like to find the next first postion.
The return vector should look something like this:
FALSE FALSE FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE
I have tried match and several other functions but without success
Here is one way:
x <- c(0,1,2,0,0,2,2,2,2,2,2,1,0,1,2,2,2,2,2,1)
a <- rle(x)
z <- rep(FALSE, length(x))
z[sequence(a$lengths) == 1] <- a$lengths >= 2 & a$values == 2
z
# [1] FALSE FALSE FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE
# [11] FALSE FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE
r <- rle(x)
# Which entries are true in the result:
w <- (cumsum(r$length)[r$values==2] - (r$length[r$values==2]-1))[r$length[r$values==2]>2]
result <- logical(length(x))
result[w] <- T
result
## [1] FALSE FALSE FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE FALSE
## [17] FALSE FALSE FALSE FALSE
Here's my attempt as a function:
FUN <- function(x, n = 3) {
y <- rle(x)
z <- y[[1]] > (n - 1)
unlist(lapply(1:length(z), function(i) {
m <- rep(FALSE, each=y[[1]][i])
if(z[i]) {
m[1] <- TRUE
}
m
}))
}
FUN(x)
## [1] FALSE FALSE FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE
## [11] FALSE FALSE FALSE FALSE TRUE FALSE FALSE FALSE FALSE FALSE

Resources