How can I predefine mutually exclusive comparisons?

The human eye can see that not a single x value satisfies the condition

x<1 & x>2

but how can I make R see this. I want to use this in a function that receives passed comparisons (e.g. strings), and not necessarily data. Let me say that I want to write a function that checks if a combination of comparisons can ever be executed, for example

areTherePossibleValues <- function(someString){
    someCode
}

areTherePossibleValues("x<1 & x>2")
[1] FALSE

I mean, this can be done by interpreting substrings, which are signs of comparison, etc., but I feel that there should be a better way. Comparison functions R ('<', '>', '=', etc.) Can actually be the answer to this, right?

+4
source share
1

, < >, >=, <= = ( ==).

areTherePossibleValues = function(condition = "x<1 & x>2", tolerance = 1e-10){

    #Attach all comparison into one
    condition = paste(condition, collapse = "&")

    #PARSE
    condition = tolower(condition) #make everything lowercase just in case    
    condition = gsub("[ ,x]","",condition) #Remove whitespace and 'x'    
    condition = gsub(">=","g",condition) # >= to g(reater than or equal to)
    condition = gsub("<=","s",condition) # <= to s(maller than or equal to) 
    condition = gsub("[==,=]","e",condition) # == or = to e(qual)

    #Separate conditions into a list
    condition = unlist(strsplit(condition,"&"))

    #Initiate vector of upper and lower bounds with NA
    Upper = rep(x = NA, times = length(condition))
    Lower = rep(x = NA, times = length(condition))

    #Fill the vector of upper and lower bounds based on comparators and numbers
    for (i in 1:length(condition)){
        number = as.numeric(gsub(pattern = "[<,>,e,g,s]", replacement = "", condition[i]))    
        comparator = substr(condition[i], start = 1, stop = 1)
        if (comparator == ">"){
            Lower[i] = number + tolerance   #just to the right of the number so as to exclude it
        } else if (comparator == "<"){
            Upper[i] = number - tolerance   #just to the left of the number so as to exclude it
        } else if (comparator == "g"){
            Lower[i] = number           #Include the number
        } else if (comparator == "s"){
            Upper[i] = number           #Include the number
        } else if (comparator == "e"){
            Upper[i] = number           #For =, make upper and lower bounds same
            Lower[i] = number
        }
    }

    Upper = as.numeric(Upper[which(is.na(Upper) == FALSE)]) #Remove NAs
    Lower = as.numeric(Lower[which(is.na(Lower) == FALSE)]) #Remove NAs

    if (length(Upper) == 0 & length(Lower) > 0){
        #1. If Upper has 0 length and Lower has more than 0, it means
        # x is constrained only by lower bounds. x will always be fulfilled
        ans = TRUE
    } else if (length(Lower) == 0 & length(Upper) > 0){
        #2. If Lower has 0 length and Upper has more than 0, it means
        # x is constrained only by upper bounds. x will always be fulfilled
        ans = TRUE
    } else {
        # If the smallest upper bound is bigger than the largest lower bound,
        #x will be fulfilled.
        ans = (min(Upper) - max(Lower)) >= 0
    }

    if (ans == FALSE){
    return(ans)
    } else {
    return(paste(ans," for (",max(Lower)," < x < ",min(Upper),")",sep = ""))
    }
}

areTherePossibleValues(">=5 & <50 & >30 & >45")
#[1] "TRUE for (45.0000000001 < x < 49.9999999999)"

areTherePossibleValues("x>5 & x<3")
#[1] FALSE

areTherePossibleValues(c("<5",">=2 & =4"))
#[1] "TRUE for (4 < x < 4)"
0

Source: https://habr.com/ru/post/1667856/


All Articles