Is there a way to grab either the min or max value from a string interval value in R?

Viewed 147

I am given a vector x which contain these string price intervals

x <- c("$100-$150","$90-$120","$30-$50")

how would I write a function that would return a vector containing the min of each interval in numeric form?

x <- c(100,90,30)

In addition, how would I write a function that did the same thing but returned the max?

4 Answers

You can use strcapture from base R to get a data.frame with the min and max for the intervals:

strcapture("\\$([[:digit:]]+)-\\$([[:digit:]]+)", x, 
           data.frame(min = integer(), max = integer()))
##   min max
## 1 100 150
## 2  90 120
## 3  30  50
  • The pattern ("\\$([[:digit:]]+)-\\$([[:digit:]]+)") sets up the two capture groups of digits.
  • x is the object we're reading from
  • The proto form is being defined as a data.frame with two columns, named "min" and "max", each containing integer values.

We can use parse_number

library(readr)
parse_number(x)
#[1] 100  90  30

Or with sub from base R

as.numeric(sub("\\$(\\d+)-.*", "\\1", x))
#[1] 100  90  30

Or to grab the max value

as.numeric(sub(".*-\\$(\\d+)", "\\1", x))
#[1] 150 120  50

Or this can be done using read.table from base R to create two column

read.table(text = gsub("$", "", x, fixed = TRUE), header = FALSE, sep="-")
#   V1  V2
#1 100 150
#2  90 120
#3  30  50

data

x <- c("$100-$150","$90-$120","$30-$50")

Another base R option using regmatches + sapply

> sapply(regmatches(x,gregexpr("\\d+",x)),function(x) min(as.numeric(x)))
[1] 100  90  30

If you want to have both min and max values, we can try

type.convert(
  setNames(
    data.frame(
      do.call(
        rbind,
        regmatches(x,gregexpr("\\d+",x)))),
    c("min","max")), 
  as.is = TRUE
  )

which gives

  min max
1 100 150
2  90 120
3  30  50

Using stringr, you can remove the $ and then split the string. The first row is the min, the second the max.

library(stringr)

y <- sapply(str_split(str_remove_all(x, "[$]"), "-", 2), as.numeric)
y
#      [,1] [,2] [,3]
# [1,]  100   90   30
# [2,]  150  120   50

y_min <- y[1,]
y_max <- y[2,]

To break it down...

  • str_remove_all is used to remove the '$' symbols
  • str_split is used to split each element on the '-'
  • sapply is used to convert each new character vector to numeric

If you want to go the dplyr route, you can separate().

library(dplyr)
library(tidyr)
library(stringr)

tibble(price = x) %>%
  mutate(price = str_remove_all(price, "[$]")) %>% 
  separate(price, c("min", "max"), sep = "-", convert = TRUE)

# # A tibble: 3 x 2
#       min   max
#      <int> <int>
#   1   100   150
#   2    90   120
#   3    30    50
Related