Compare strings with logical operator in R

66,768

Instead of using sapply to loop through each individual day in x and check whether it's the weekday or weekend, you can do this in a single vectorized operation with ifelse and %in%:

ifelse(x %in% c("Sat", "Sun"), "Weekend", "Weekday")
# [1] "Weekday" "Weekday" "Weekday" "Weekday" "Weekday" "Weekend" "Weekend"

The motivation for using vectorized operations here is twofold -- it will save you typing and it will make your code more efficient.

Share:
66,768
Bridgbro
Author by

Bridgbro

Updated on August 12, 2020

Comments

  • Bridgbro
    Bridgbro over 3 years

    I'm getting an error trying to compare and set weekday string values as either a "weekend" or a "weekday" using R. Any suggestions on how to approach this problem in a better way would be great.

    x <- c("Mon","Tue","Wed","Thu","Fri","Sat","Sun")
    
    setDay <- function(day){
              if(day == "Sat" | "Sun"){
               return("Weekend")
              } else { 
                return("Weekday")
              }
            }
    
    sapply(x, setDay)
    

    This is the error I get back in RStudio:

    Error in day == "Sat" | "Sun" : 
      operations are possible only for numeric, logical or complex types
    
  • Frank
    Frank over 8 years
    And as a counter to the ifelse hate: c("Weekend", "Weekday")[1L+x %in% c("Sat", "Sun")]
  • josliber
    josliber over 8 years
    @Frank I understand the motivation for that sort of expression instead of ifelse, but I find it to be a lot less readable.
  • Señor O
    Señor O over 8 years
    ^^ especially the 1L - is that even necessary?
  • Frank
    Frank over 8 years
    I'm with you; just trying to guard against an unnecessary answer with that approach :)
  • josliber
    josliber over 8 years
    @SeñorO you add the 1 to convert FALSE and TRUE to indices 1 and 2, respectively.
  • Señor O
    Señor O over 8 years
    Yeah, but the L specifies that it's an integer, which is used sometimes in highly optimized code, which this doesn't need to be. I think [1 + x %in% c(...)] would be more readable?
  • josliber
    josliber over 8 years
    Ah gotcha, you're saying 1L versus 1. I also noticed in this particular case that it should be c("Weekday", "Weekend")[1L+x %in% c("Sat", "Sun")] instead (flip the first vector).
  • ExperimenteR
    ExperimenteR over 8 years
    ifelse("Sunday" %in% c("Sat", "Sun"), "Weekend", "Weekday")
  • josliber
    josliber over 8 years
    @ExperimenteR well, from the question it seems like it's going to be "Sun" instead of "Sunday" -- note that the OP's original code (with the bug fix) will also return "Weekday" in this case. Of course, you could defend against the fully spelled days by checking for inclusion in the set c("Sat", "Sun", "Saturday", "Sunday").
  • rbatt
    rbatt over 8 years
    also, if %in% syntax confuses you, you can use is.element() (although takes up more characters)
  • MichaelChirico
    MichaelChirico over 8 years
    Once we start allowing Sunday, Saturday, Sat, etc., it's time to regex: ifelse(grepl("sun|sat",tolower(x)),"Weekend","Weekday")
  • MichaelChirico
    MichaelChirico over 8 years
    For the uninitiated, "the motivation for that sort of expression" is here