3

I have a character variable with ratios (proportions) expressed as strings:

x <- c("2/3", "5/6", "3/11").

I want to convert the character values in x into percentages. Thus, my desired output would be:

c(2/3, 5/6, 3/11) * 100
# [1] 66.66667 83.33333 27.27273 

When I try the as.numeric(x), a warning message is generated (NAs introduced by coercion) and all elements are converted into NA

What to do?

Henrik
  • 65,555
  • 14
  • 143
  • 159
suyash gautam
  • 169
  • 1
  • 2
  • 9

2 Answers2

9

Here are some alternatives:

1) read.table Read the text in as if it were a file and then divide:

with(read.table(text = x, sep = "/"), 100 * V1 / V2)
## [1] 66.66667 83.33333 27.27273

2) eval/parse eval/parse is generally frowned upon but here is how it would work:

100 * sapply(as.list(parse(text = x)), eval)
## [1] 66.66667 83.33333 27.27273

3) strsplit

sapply(strsplit(x, "/"), function(x) { x <- as.numeric(x); 100 * x[1] / x[2]})
## [1] 66.66667 83.33333 27.27273

4) gsubfn::strapply This picks out the two strings of digits using strapply and then converts each to numeric and divides:

library(gsubfn)

strapply(x, "(\\d+)/(\\d+)", ~ 100 * as.numeric(x) / as.numeric(y), simplify = TRUE)
## [1] 66.66667 83.33333 27.27273
G. Grothendieck
  • 254,981
  • 17
  • 203
  • 341
  • 1
    for people like me who should wonder why `eval(parse(` is frowned upon https://stackoverflow.com/questions/13649979/what-specifically-are-the-dangers-of-evalparse – tjebo Feb 06 '21 at 16:48
2

tidyerse

If you stumbled onto this post in search of a tidyverse answer here is a simple extension. Note this does use the aforementioned "frowned upon" eval( parse())

library(dplyr)
library(purrr)

# add into a tibble
df <- tibble(fractions = c("2/3", "5/6", "3/11"))
df %>% 
  mutate(numbers = map_dbl(fractions, ~eval(parse(text = .x))))
#> # A tibble: 3 x 2
#>   fractions numbers
#>   <chr>       <dbl>
#> 1 2/3         0.667
#> 2 5/6         0.833
#> 3 3/11        0.273
blakiseskream
  • 338
  • 4
  • 9