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)
Related
I want to create a list based on some of the elements, even if the elements are not available.
> group_vars <- list(hhrace,hhethn,hhsize,hhinc,hhage,hhcnty,hhkids,hhgeo)
here hhrace and hhcnty do not exist, but I want to create a list without those elements.
> group_vars <- list(hhrace,hhethn,hhsize,hhinc,hhage,hhcnty,hhkids,hhgeo)
Error: object 'hhrace' not found
Desired Output-
> group_vars
hhethn,hhsize,hhinc,hhage,hhkids,hhgeo
without the hhrace and the hhcnty.
You can store them in a list of expressions with rlang::exprs and only keep the ones which exist:
library(purrr)
# define variables in global environment
hhethn <- hhsize <- hhinc <- hhage <- hhkids <- hhgeo <- TRUE
group_vars <- rlang::exprs(hhrace, hhethn, hhsize, hhinc, hhage, hhcnty, hhkids, hhgeo) %>%
keep(~exists(as.character(.x))) %>%
set_names(as.character(.)) %>%
map(eval)
group_vars
#$hhethn
#[1] TRUE
#
#$hhsize
#[1] TRUE
#
#$hhinc
#[1] TRUE
#
#$hhage
#[1] TRUE
#
#$hhkids
#[1] TRUE
#
#$hhgeo
#[1] TRUE
For a more general case you can create a function:
safe_list <- function(...){
rlang::enexprs(...) %>%
keep(~exists(as.character(.x))) %>%
set_names(as.character(.)) %>%
map(eval)
}
group_vars <- safe_list(hhrace, hhethn, hhsize, hhinc, hhage, hhcnty, hhkids, hhgeo)
I just want to pick up a solution suggested in the comments, which I believe is more useful than appreciated.
To set the stage, let's create the objects as DiceboyT has done:
hhethn <- hhsize <- hhinc <- hhage <- hhkids <- hhgeo <- TRUE
I am also creating a vector with the names of the existing objects:
objects <- c("hhrace","hhethn","hhsize","hhinc","hhage","hhcnty","hhkids","hhgeo")
Now, I may be wrong, but I have a hunch that all you need is the vector of objects that actually exist. The following would help with that:
objects[objects %in% ls()]
[1] "hhethn" "hhsize" "hhinc" "hhage" "hhkids" "hhgeo"
However, if you truly want to list, the following would help as well, setting all missing elements to FALSE:
mget(objects, ifnotfound = FALSE)
$hhrace
[1] FALSE
$hhethn
[1] TRUE
$hhsize
[1] TRUE
$hhinc
[1] TRUE
$hhage
[1] TRUE
$hhcnty
[1] FALSE
$hhkids
[1] TRUE
$hhgeo
[1] TRUE
Now, to get a list of these except for the missing ones, we could also do the following:
tmpfun <- function(lst, nme) {
tryCatch(
lst[[nme]] <- get(nme)
, error = function(e) {return(lst)}
)
return(lst)
}
Reduce(tmpfun, objects, init = list())
$hhethn
[1] TRUE
$hhsize
[1] TRUE
$hhinc
[1] TRUE
$hhage
[1] TRUE
$hhkids
[1] TRUE
$hhgeo
[1] TRUE
which gives you the above results except for the cases where the object does not exist.
You can do something like this-
INPUT-
> objects <- c("hhrace","hhethn","hhsize","hhinc","hhage","hhcnty","hhkids","hhgeo")
> hhsize=list(a=2)
> hhinc=list(a=5)
> hhethn=list(a=50)
> sapply(objects,function(x) if(exists(x)) TRUE else FALSE)
OUTPUT-
hhrace hhethn hhsize hhinc hhage hhcnty hhkids hhgeo
FALSE TRUE TRUE TRUE FALSE FALSE FALSE FALSE
Note- To get available lists in your env you can use below code-
To just get list names which are available in env you can use-
> names(which(sapply(objects,function(x) if(exists(x)) TRUE else FALSE)))
[1] "hhethn" "hhsize" "hhinc"
To get complete list elements you can use below code
> mget(names(which(sapply(objects,function(x) if(exists(x)) TRUE else FALSE))))
$hhethn
$hhethn$a
[1] 50
$hhsize
$hhsize$a
[1] 2
$hhinc
$hhinc$a
[1] 5
I want to filter out the rows of a table which contain '*' in the string value of the column. Checking just that column.
string_name = c("aaaaa", "bbbbb", "ccccc", "dddd*", "eee*eee")
zz <- sapply(tx$variant_full_name, function(x) {substrRight(x, -1) =="*"})
Error in FUN(c("Agno I30N", "VP2 E17Q", "VP2 I204*", "VP3 I85F", "VP1 K73R", :
could not find function "substrRight"
The 4th value of zz should be TRUE by this.
in python there is endswith function for strings [ string_s.endswith('*') ]
Is there something similar to that in R ?
Also, is it problem because of '*' as a character as it means any character ? grepl also not working.
> grepl("*^",'dddd*')
[1] TRUE
> grepl("*^",'dddd')
[1] TRUE
Base now contains startsWith and endsWith. Thus the OP's question can be answered with endsWith:
> string_name = c("aaaaa", "bbbbb", "ccccc", "dddd*", "eee*eee")
> endsWith(string_name, '*')
[1] FALSE FALSE FALSE TRUE FALSE
This is much faster than substring(string_name, nchar(string_name)) == '*'.
* is a quantifier in regular expressions. It tells the regular expression engine to attempt to match the preceding token "zero or more times". To match a literal, you need to precede it with two backslashes or place inside of a character class [*]. To check if the string ends with a specific pattern, use the end of string $ anchor.
> grepl('\\*$', c('aaaaa', 'bbbbb', 'ccccc', 'dddd*', 'eee*eee'))
# [1] FALSE FALSE FALSE TRUE FALSE
You can simply do this without implementing a regular expression in base R:
> x <- c('aaaaa', 'bbbbb', 'ccccc', 'dddd*', 'eee*eee')
> substr(x, nchar(x)-1+1, nchar(x)) == '*'
# [1] FALSE FALSE FALSE TRUE FALSE
This is simple enough that you don't need regular expressions.
> string_name = c("aaaaa", "bbbbb", "ccccc", "dddd*", "eee*eee")
> substring(string_name, nchar(string_name)) == "*"
[1] FALSE FALSE FALSE TRUE FALSE
I use something like this:
strEndsWith <- function(haystack, needle)
{
hl <- nchar(haystack)
nl <- nchar(needle)
if(nl>hl)
{
return(F)
} else
{
return(substr(haystack, hl-nl+1, hl) == needle)
}
}
here is a tidyverse solution:
string_name = c("aaaaa", "bbbbb", "ccccc", "dddd*", "eee*eee")
str_sub(string_name, -1) == "*"
[1] FALSE FALSE FALSE TRUE FALSE
It has the benefits of being much more readable and can also be changed easily if a different location needs to be checked.
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")
I would like to determine if a vector is either always increasing or always decreasing in R.
Ideally, if I had these three vectors:
asc=c(1,2,3,4,5)
des=c(5,4,3,2,1)
non=c(1,3,5,4,2)
I would hope that the first two would return TRUE, and the last would return FALSE.
I tried a few approaches. First, I tried:
> is.ordered(asc)
[1] FALSE
> is.ordered(des)
[1] FALSE
> is.ordered(non)
[1] FALSE
And I also tried:
> order(non)
[1] 1 5 2 4 3
And hoped that I could simply compare this vector with 1,2,3,4,5 and 5,4,3,2,1, but even that returns a string of logicals, rather than a single true or false:
> order(non)==c(1,2,3,4,5)
[1] TRUE FALSE FALSE TRUE FALSE
Maybe is.unsorted is the function your looking for
> is.unsorted(asc)
[1] FALSE
> is.unsorted(rev(des)) # here you need 'rev'
[1] FALSE
> is.unsorted(non)
[1] TRUE
From the Description of is.unsorted you can find:
Test if an object is not sorted (in increasing order), without the cost of sorting it.
Here's one way using ?is.unsorted:
is.sorted <- function(x, ...) {
!is.unsorted(x, ...) | !is.unsorted(rev(x), ...)
}
Have a look at the additional arguments to is.unsorted, which can be passed here as well.
Here is one way without is.unsorted() to check if to vectors are sorted. This function will return true, if all elements in the vector given are sorted in an ascending manner or false if not:
is.sorted <- function(x) {
if(all(sort(x, decreasing = FALSE) == x)) {
return(TRUE)
} else {
return(FALSE)
}
}
i have a dataframe named as newdata. it has two columns named as BONUS and GENDER.
When i write the following code in r:
> newdata <- within(newdata,{
PROMOTION=ifelse(BONUS>=1500,1,0)})
it works though i haven't used loop here but the following codes don't work without loop. Why?
> add <- with(newdata,
if(GENDER==F)sum(PROMOTION))
Warning message:
In if (GENDER == F) sum(PROMOTION) :
the condition has length > 1 and only the first element will be used
My question is why in the first code all elements have been used?
ifelse is vectorized, but if is not. For example:
> x <- rbinom(20,1,.5)
> ifelse(x,TRUE,FALSE)
[1] TRUE TRUE FALSE TRUE FALSE TRUE FALSE TRUE TRUE TRUE TRUE FALSE
[13] FALSE TRUE TRUE FALSE TRUE TRUE TRUE TRUE
> if(x) {TRUE} else {FALSE}
[1] TRUE
Warning message:
In if (x) { :
the condition has length > 1 and only the first element will be used