Search code examples
rstringtextformattingnumbers

How to convert limits of detection (or linearity) with an inferior (or superior) sign to numbers with fixed decimals in R?


Let's consider a dataframe with a column "before" as character format.
How to convert the limits of detection like e.g. "<0.5" to a number with four decimals "0.4999"and the limits of linearity like e.g. ">15.0" to "15.0001" while keeping string texts intact, e.g. "Value > limit"?
Edit
Note that my dataframe contains thousands of lines, including several dozen different detection limits, linearity limits, and string texts; therefore, a global formatting would therefore be preferable, without having to search for and type the different limits/strings one by one in the script to be executed.

enter image description here

dat0 <-
structure(list(before = c("6.1", "<0.5", "4.7", ">15.0", "Value > limit", 
    "8.0", "Result < cutoff", "6.5", "<50", "92", ">500", "480", 
    "Value > linearity"), after = c("6.1", "0.4999", "4.7", "15.0001", 
    "Value > limit", "8.0", "Result < cutoff", "6.5", "49.9999", 
    "92", "500.0001", "480", "Value > linearity")), class = "data.frame", row.names = c(NA, 
    -13L)) 

Thanks for help


Solution

  • It looks like we could use a case_when applied to each column:

    1. when the data starts with "<", extract the "number" part of the text, subtract 0.0001, and show the result to 4 decimal places.
    2. when the data starts with ">", same deal but add 0.0001.
    3. otherwise, leave the data as is.

    library(tidyverse)
    dat0 |>
      mutate(across(before:after, ~case_when(
        str_starts(.x, "<") ~ sprintf(parse_number(.x) - 0.0001, fmt = "%#.4f"),
        str_starts(.x, ">") ~ sprintf(parse_number(.x) + 0.0001, fmt = "%#.4f"),
        .default = .x)))
    

    Result

                  before             after
    1                6.1               6.1
    2             0.4999            0.4999
    3                4.7               4.7
    4            15.0001           15.0001
    5      Value > limit     Value > limit
    6                8.0               8.0
    7    Result < cutoff   Result < cutoff
    8                6.5               6.5
    9            49.9999           49.9999
    10                92                92
    11          500.0001          500.0001
    12               480               480
    13 Value > linearity Value > linearity