I want to compare two vectors but it is not working, kindly tell me how two vectors can be compared:
x <- c(1,2,3,4)
y <- c(5,6,7,8)
if (x==y) print("same") else print("different")
Use all can work here.
> all(x==y)
[1] FALSE
> y1=c(5,6,7,8)
> all(y==y1)
[1] TRUE
EDIT
best is to use isTRUE(all.equal(x,y)) to avoid recycling
recycling
> x=c(5,6,5,6)
> y=c(5,6)
> all(x==y)
[1] TRUE
better way
> isTRUE(all.equal(x,y))
[1] FALSE
> isTRUE(all.equal(y,y1))
[1] TRUE
> x=c(5,6,5,6)
> y=c(5,6)
>isTRUE(all.equal(x,y))
[1] FALSE
When it comes to array comparison, all and any are your friends. If you do not really mean geometric vector but array of values, sort should also be necessary:
> all(sort(x)==sort(y))
Try:
x <- c(1,2,3,4)
y <- c(5,6,7,8)
if(identical(x,y)) print("identical") else print("not identical")
Related
Let's say I have this list:
List_example <- list('short'= 10,'medium'= 20,'long'=200)
How do I check can I check if short, medium and long are integers in one go?
Try the code below
> all(sapply(List_example, `%%`, 1) == 0)
[1] TRUE
With sapply :
List_example <- list('short'= 10,'medium'= 20,'long'=200)
all(sapply(List_example, is.numeric))
#[1] TRUE
To check for integers specifically use is.integer.
If an object has an R integer type then clearly it is a whole number or if it has a double type then we can check if it equals itself rounded.
is_int <- function(x) is.integer(x) || (is.numeric(x) && identical(round(x), x))
all(sapply(List_example, is_int))
## [1] TRUE
L <- list(3, 5L, "xyz")
all(sapply(L, is_int))
## [1] FALSE
If what you mean is that you want to find out if they all have R integer type then we have the following since the numbers in the example are all doubles.
all(sapply(List_example, is.integer))
## [1] FALSE
Is there an easy, straightforward way (possibly a builtin function) that could match one vector as a whole in another vector?
Example:
target <- c(1,2,3)
A <- c(4,5,6,1,2,3)
B <- c(4,5,6,3,2,1)
my_match(target, A) # TRUE
my_match(target, B) # FALSE
I tried %in%, match and pmatch but these won't give the desired result. For example, both target %in% A and target %in% B will give the result [1] TRUE TRUE TRUE, which is not what I want.
Here another version
multi_match=function(target,A) {
lA=length(A)
lt=length(target)
if (lt>lA) return(FALSE)
any(colSums(sapply(1:(lA-lt+1),function(i) A[i:(i+lt-1)])==target)==lt)
}
Let's try it with some data
target <- c(1,2,3)
A <- c(4,5,6,1,2,3,1,2,3,1,3)
B <- c(4,5,6,3,2,1)
multi_match(target,A)
#TRUE
multi_match(target,B)
#FALSE
#"wrong" input order - trivially no match
multi_match(A,target)
#FALSE
And an extension of the multi_match function above to multi_which.
multi_which=function(target,A) {
lA=length(A)
lt=length(target)
if (lt>lA) return(integer(0))
which(colSums(sapply(1:(lA-lt+1),function(i) A[i:(i+lt-1)])==target)==lt)
}
multi_which(target,A)
#[1] 4 7
multi_which(target,B)
#integer(0)
#"wrong" input order - trivially no match
multi_which(A,target)
#integer(0)
Try:
grepl(paste(target,collapse=","),paste(A,collapse=","))
grepl(paste(target,collapse=","),paste(B,collapse=","))
This concatenates the vectors into strings and looks for a substring in the second argument that matches the first.
You could put this into a function that returns true or false:
my_match <- function(x,y,dlm=",") grepl(paste(x,collapse=dlm),paste(y,collapse=dlm))
my_match(target,A)
[1] TRUE
my_match(target,B)
[1] FALSE
One possible way is to use match and check if resulting sequence is rising
all(diff(match(target, A)) == 1) && length(match(target, A)) == length(target)
Or as a function
> exact_match <- function(p, x) all(diff(match(p, x)) == 1) && length(match(p, x)) == length(p)
> exact_match(target,A)
[1] TRUE
> exact_match(target,B)
[1] FALSE
Can someone help me modify the function below to check if a number is numeric?
# handy function that checks if something is numeric
check.numeric <- function(N){
!length(grep("[^[:digit:]]", as.character(N)))
}
check.numeric(3243)
#TRUE
check.numeric("sdds")
#FALSE
check.numeric(3.14)
#FALSE
I want check.numeric() to return TRUE when it's a decimal like 3.14.
You could use is.finite to test whether the value is numeric and non-NA. This will work for numeric, integer, and complex values (if both real/imaginary parts are finite).
> is.finite(NA)
[1] FALSE
> is.finite(NaN)
[1] FALSE
> is.finite(Inf)
[1] FALSE
> is.finite(1L)
[1] TRUE
> is.finite(1.0)
[1] TRUE
> is.finite("A")
[1] FALSE
> is.finite(pi)
[1] TRUE
> is.finite(1+0i)
[1] TRUE
Sounds like you want a function like this:
f <- function(x) is.numeric(x) & !is.na(x)
Let's say we have a statement that produces integer(0), e.g.
a <- which(1:3 == 5)
What is the safest way of catching this?
That is R's way of printing a zero length vector (an integer one), so you could test for a being of length 0:
R> length(a)
[1] 0
It might be worth rethinking the strategy you are using to identify which elements you want, but without further specific details it is difficult to suggest an alternative strategy.
If it's specifically zero length integers, then you want something like
is.integer0 <- function(x)
{
is.integer(x) && length(x) == 0L
}
Check it with:
is.integer0(integer(0)) #TRUE
is.integer0(0L) #FALSE
is.integer0(numeric(0)) #FALSE
You can also use assertive for this.
library(assertive)
x <- integer(0)
assert_is_integer(x)
assert_is_empty(x)
x <- 0L
assert_is_integer(x)
assert_is_empty(x)
## Error: is_empty : x has length 1, not 0.
x <- numeric(0)
assert_is_integer(x)
assert_is_empty(x)
## Error: is_integer : x is not of class 'integer'; it has class 'numeric'.
Maybe off-topic, but R features two nice, fast and empty-aware functions for reducing logical vectors -- any and all:
if(any(x=='dolphin')) stop("Told you, no mammals!")
Inspired by Andrie's answer, you could use identical and avoid any attribute problems by using the fact that it is the empty set of that class of object and combine it with an element of that class:
attr(a, "foo") <- "bar"
identical(1L, c(a, 1L))
#> [1] TRUE
Or more generally:
is.empty <- function(x, mode = NULL){
if (is.null(mode)) mode <- class(x)
identical(vector(mode, 1), c(x, vector(class(x), 1)))
}
b <- numeric(0)
is.empty(a)
#> [1] TRUE
is.empty(a,"numeric")
#> [1] FALSE
is.empty(b)
#> [1] TRUE
is.empty(b,"integer")
#> [1] FALSE
if ( length(a <- which(1:3 == 5) ) ) print(a) else print("nothing returned for 'a'")
#[1] "nothing returned for 'a'"
On second thought I think any is more beautiful than length(.):
if ( any(a <- which(1:3 == 5) ) ) print(a) else print("nothing returned for 'a'")
if ( any(a <- 1:3 == 5 ) ) print(a) else print("nothing returned for 'a'")
You can easily catch integer(0) with function identical(x,y)
x = integer(0)
identical(x, integer(0))
[1] TRUE
foo = function(x){identical(x, integer(0))}
foo(x)
[1] TRUE
foo(0)
[1] FALSE
another option is rlang::is_empty (useful if you're working in the tidyverse)
The rlang namespace does not seem to be attached when attaching the tidyverse via library(tidyverse) - in this case you use purrr::is_empty, which is just imported from the rlang package.
By the way, rlang::is_empty uses user Gavin's approach.
rlang::is_empty(which(1:3 == 5))
#> [1] TRUE
isEmpty() is included in the S4Vectors base package. No need to load any other packages.
a <- which(1:3 == 5)
isEmpty(a)
# [1] TRUE
I manage to do the following:
stuff <- c("banana_fruit","apple_fruit","coin","key","crap")
fruits <- stuff[stuff %in% grep("fruit",stuff,value=TRUE)]
but I can't get select the-not-so-healthy stuff with the usual thoughts and ideas like
no_fruit <- stuff[stuff %not in% grep("fruit",stuff,value=TRUE)]
#or
no_fruit <- stuff[-c(stuff %in% grep("fruit",stuff,value=TRUE))]
don't work. The latter just ignores the "-"
> stuff[grep("fruit",stuff)]
[1] "banana_fruit" "apple_fruit"
> stuff[-grep("fruit",stuff)]
[1] "coin" "key" "crap"
You can only use negative subscripts with numeric/integer vectors, not logical because:
> -TRUE
[1] -1
If you want to negate a logical vector, use !:
> !TRUE
[1] FALSE
As Joshua mentioned: you can't use - to negate your logical index; use ! instead.
stuff[!(stuff %in% grep("fruit",stuff,value=TRUE))]
See also the stringr package for this kind of thing.
stuff[!str_detect(stuff, "fruit")]
There is also a parameter called 'invert' in grep that does essentially what you're looking for:
> stuff <- c("banana_fruit","apple_fruit","coin","key","crap")
> fruits <- stuff[stuff %in% grep("fruit",stuff,value=TRUE)]
> fruits
[1] "banana_fruit" "apple_fruit"
> grep("fruit", stuff, value = T)
[1] "banana_fruit" "apple_fruit"
> grep("fruit", stuff, value = T, invert = T)
[1] "coin" "key" "crap"