0

I wrote this function to return the string before a certain character, which goes like so:

strBefore <- function(find, x, last = FALSE, occurence) {

  # Checking.
  if (class(x)[1] != "character") { stop("The strBefore function only supports objects of character class.") }

  # Getting the place of the find, and handling both caes of last.
  fullPlace <- gregexpr(find, x)[[1]] # Gets the location of the occurences of find in x.

  # Handling the case where last is TRUE.
  if (last == TRUE) { place <- max(fullPlace) # Grabbing the latest character index if last is TRUE.
  } else { place <- min(fullPlace) } # Otherwise, getting the first space.

  # Handles the occurrenceargument if given.
  if (!missing(occurrence)) { place <- fullPlace[occurrence] }

  # Subsetting the string.
  xlen <- nchar(x) # Getting the total number of characters in the string.
  x <- substr(x, 1, place - 1) # Minus 1 because we don't want to include the first hit for find.
  return(x)

}

Where find is the character you want the string before, x is the character, last asks if you to get before the last occurrence of find, and occurrence designates which occurrence of find to get before (overrides last if given).

If I use it on a single character object, it works fine like so:

> test <- "Hello World"
> test2 <- strBefore(" ", test)
> test2
[1] "Hello"

However, if I use it on a character vector, it cuts each item in the vector at the same place as the first item:

> test <- c("Hello World", "Hi There", "Why Hello")
> test2 <- strBefore(" ", test)
> test2
[1] "Hello" "Hi Th" "Why H"

Now, this link here does provide me with a method for doing what I want:

Using gsub to extract character string before white space in R

However, I do like having the functionality of the "occurrence" argument, which returns the string before the 2nd, 3rd, etc... occurrence of the find argument.

Just as a note, I can vectorize my function with sapply like so:

> test <- c("Hello World", "Hi There", "Why Hello")
> test2 <- sapply(test, function(x) strBefore(" ", x))
> test2
Hello World    Hi There   Why Hello 
    "Hello"        "Hi"       "Why" 

Which somewhat solves my problem...but is there a way to do this more cleanly without having to use an apply function? I'm not looking for a solution to what strBefore does, but more a solution to how to vectorize custom functions. Thanks for your time.

Community
  • 1
  • 1
giraffehere
  • 1,118
  • 7
  • 18
  • 2
    You can vectorize the function like this `Vectorize(strBefore, "x")(" ", test)`. – lukeA Mar 10 '16 at 15:33
  • Walk through your function with example input that doesn't do what you want and figure out where it breaks. – Dason Mar 10 '16 at 15:34
  • `char <- ' '; gsub(paste0(char, '.*'), '', test)` ? – rawr Mar 10 '16 at 15:36
  • You might want to look at `regmatches()`, which - in tandem with a regular expression - might give you what you want without having to write as much of a custom function. – Thomas Mar 10 '16 at 16:59
  • @lukeA Thanks for you reply, I think you're the only one that followed I was looking more for a way to vectorize my function instead of how to do what it does. Do you know if there's a way to make my function automatically vectorize without having to wrap it? Or is that what sapply and Vectorize are for? I could just make a wrapper function that would satisfy this. – giraffehere Mar 10 '16 at 19:32
  • 1
    `Vectorize(strBefore, "x")` returns a function, which vectorizes the argument `x`. So you could do sth like `vStrBefore <- Vectorize(strBefore, "x")` and just use `vStrBefore(...)`. Or you vectorize it beforehand by iterating over the `x`s and aggregating the results; e.g. by using `sapply` or a `for` loop. – lukeA Mar 10 '16 at 20:12
  • Okay, that sounds like my best bet. Thank you. :) – giraffehere Mar 14 '16 at 15:31

0 Answers0