I have numbers look like below (left column - results; right column - uncertainty). And I want to combine result and uncertainty like '0.20±1.52E-17'. Can I do this using R codes?
A tricky part will be how to automatically adjust the notations such as E-18 to E-17.
I know how to write scientific notations using R. But I can't find the way to combine result and uncertainty in scientific notations. I searched the internet but couldn't find the solution.
Thank you.
I have numbers look like below (left column - results; right column - uncertainty). And I want to combine result and uncertainty like '0.20±1.52E-17'. Can I do this using R codes?
A tricky part will be how to automatically adjust the notations such as E-18 to E-17.
I know how to write scientific notations using R. But I can't find the way to combine result and uncertainty in scientific notations. I searched the internet but couldn't find the solution.
Thank you.
Share Improve this question edited Feb 4 at 22:51 ThomasIsCoding 104k9 gold badges37 silver badges103 bronze badges asked Feb 4 at 18:12 TanukiTanuki 1 2 |2 Answers
Reset to default 1Perhaps there's a more efficient way to do this, but this should work. First, there is a function get_exp()
that finds the appropriate exponent for the scientific notation.
get_exp <- function(x){
e <- seq(-100,100)
out <- outer(x, e, function(x,e)x*10^e)
res <- -e[apply(out, 1, \(x)min(which(abs(x) > 1)))]
ifelse(res > 0, res+1, res)
}
Next, we can use that in the function I called combine_notation()
to find the appropriate exponent for both the result and uncertainty, pick the largest one and then put the results together as you described.
combine_notation <- function(result, uncertainty){
result_exp <- get_exp(d$result)
unc_exp <- get_exp(d$uncert)
use_exp <- apply(cbind(result_exp, unc_exp), 1, max)
sprintf("%.2f\U00B1%.2fE%s", d$result/10^use_exp, d$uncert/10^use_exp, as.character(use_exp))
}
Here's how it works on the first couple of rows of the data above.
d <- data.frame(result = c(2E-18, -7.84E-17), uncert = c(1.52E-17, 1.67E-16))
combine_notation(d$result, d$uncert)
#> [1] "0.20±1.52E-17" "-0.78±1.67E-16"
Created on 2025-02-04 with reprex v2.1.1
While this works, I might suggest that you would need to be very careful using this notation. I suspect most people will read this as (0.2 - 1.52E-17, 0.2 + 1.52E-17) - a very small range around 0.2. However, the actual data are more like (0.2+/-1.52)E-17 - a very small range around 0.2E-17. The onus will be on you to ensure that this information is conveyed appropriately if you choose to use this notation.
You could put sprintf
into Reduce
for this.
> Reduce(\(x, y) sprintf('%.2E\U00B1%.2E', x, y), as.data.frame(m))
[1] "1.37E-17±6.33E-18" "-5.65E-18±4.04E-18" "3.63E-18±-1.06E-18"
PS: Writing 3.63±-1.06E-18
instead of 3.63E-18±-1.06E-18
is invalid.
Data:
> dput(m)
structure(c(1.37095844714667e-17, -5.64698171396089e-18, 3.63128411337339e-18,
6.3286260496104e-18, 4.04268323140999e-18, -1.06124516091484e-18
), dim = 3:2)
(0.20±1.52)E-17
– Roland Commented Feb 5 at 5:36