6

So basically I am doing a physics experiment, and in my table I want to have my data rounded to the same accuracy as the error is, which is rounded to 1 sig fig.

So for example if I have the following:

angle <- c(4, 4.1, 4.2)
angle.error <- c(0.024, 0.3, 0.113)
data <- data.frame(angle,angle.error)

want I want to end up with is the angle error rounded to 1 sig fig, and the angle rounded to the corresponding number of decimal places as the angle error, to give

angle <- c(4.00, 4.1, 4.2)
angle.error <- c(0.02,0.3,0.1)
data <- data.frame(angle, angle.error)

Hope this makes sense!! This is the standard way we are taught to present data, and as such I am surprised how difficult I am finding it to find a proper way of doing this. Any contributions would be great!!

EDIT:

If I want to turn this into a UDR where say the data is in column 5 and the errors in column 6 of my data frame, I write:

Conv2 <- function(x) {
x[6] <- signif(x[6],1)
exp <- floor(log10(x[6]))
man <- x[6]/10^exp         
x[5] <- round(x[5], -exp)   # Error associated with this line I think
sapply(seq_along(x[5]), function(i) format(x[i,5], nsmall=-exp[i]))

return(x)
}

When I implement it I get the error 'Error in FUN(X[[i]], ...) : non-numeric argument to mathematical function'

Nick Siemons
  • 61
  • 1
  • 1
  • 3
  • 2
    I might need a little clarification. Are you using "1dp" to mean 1 significant figure or 1 decimal place. If you are not using 1dp interchangeably with 1 sig fig, then your output doesn't seem quite right. Also, you say you want `angle` rounded to the same number of sigfigs as `angle.error`, but your output uses two sigfigs for `angle` while `angle.error` only has one. – Benjamin Mar 22 '17 at 18:39
  • yes sorry I got this the wrong way around - I have now edited it to make sense – Nick Siemons Mar 24 '17 at 12:17

1 Answers1

16

This can be done with signif(). In contrast to round(), which rounds to a number of decimal places, signif() rounds to a specific number of significant places.

x <- c(1,1.0001,0.00001)
round(x,1) # rounds to the specified number of decimal places
signif(x,1) # rounds to the specified number of significant digits

Let's apply this to your case. Note that signif is vectorized over both arguments.

> signif(c(1.111,2.222,3.333),c(1,2,3))
[1] 1.00 2.20 3.33

This would mean the following for your case:

angle.error <- c(0.024, 0.3, 0.113)
cor <- signif(angle.error,1)

Rounding the angles is slightly more difficult. We need to round angle to the same number of decimal places as angle.error_corr. Therefore we will extract the mantissa and exponent of this number.

exp <- floor(log10(cor)) 
man <- cor/10^exp

Now it is possible to use the exponents to round your angles.

angle <- c(4, 4.1, 4.2)
angle_cor <- round(angle, -exp)

However, this does not give the intended result since R shows the number of digits of the most precise double and drops trailing zeros. We can solve this with the nsmall argument of format, which is unfortunately not vectorized.

sapply(seq_along(angle), function(i) format(angle[i], nsmall = -exp[i]))

Which should give you the answer you were looking for.

takje
  • 2,630
  • 28
  • 47