简体   繁体   中英

Weird bug in R code: Sample Moments

CalculateSampleMomentAroundZero <- function(x) {
  # Computes the sample moments (up to fourth order) around zero
  #
  # Args:
  #   x: A vector of numbers whose sample moments around zero
  #      will be calculated
  #
  # Returns:
  #   A list that contains the sample moments (up to fourth order)
  #   of the numbers in vector x.

  n <- length(x)
  moment.zero <- lapply(1:4, function(i) (1/n) * sum(x^i))
  names(moment.zero) <- c("first", "second", "third", "fourth")

  moment.zero
}

CalculateSampleMomentAroundMean <- function(x) {
  # Computes the sample moment (up to fourth order) around the mean
  #
  # Args:
  #   x: A vector of numbers whose sample moments around the mean 
  #      will be computed
  #
  # Returns:
  #   A list that contains the sample moments (up to fourth order) 
  #   of the numbers in vector x.

  #
  # Uses the function to calculate sample moments around zero to
  #  obtain the mean (sample moment around zero of first order) of 
  #  the numbers in vector x.
  #
  moments.around.zero <- CalculateSampleMomentAroundZero(x)
  xbar <- moments.around.zero$first

  n <- length(x)
  moment.mean <- lapply(1:4, function(i) (1/n) * sum((x - xbar)^i))
  names(moment.mean) <- c("first", "second", "third", "fourth")

  moment.mean
} 

skewnesskurtosis <- function(x) {
  # Computes the skewness and kurtosis of a vector of numbers
  #
  # Args:
  #   x: A vector of numbers whose skewness and kurtosis will be 
  #      computed.
  #
  # Returns:
  #   A list that contains the skewness and kurtosis of the numbers 
  #   in vector x.

  #
  # Uses the function to compute sample moments around the mean to 
  #  obtain the second, third, and fourth orders of the sample    
  #  moments around the mean.
  #
  moments.around.mean <- CalculateSampleMomentAroundMean(x)
  mu2 <- moments.around.mean$second
  mu3 <- moments.around.mean$third
  mu4 <- moments.around.mean$fourth

  skew <- mu3 / (mu2)^(3/2)
  kurt <- (mu4 / (mu2)^(2)) - 3
  sk <- list(skewness = skew, kurtosis = kurt)

  sk
}

I checked my output by using the functions in the moments library, and I get the same results for my first function. The second function, however, is a little odd. The second, third, and fourth moments match up, but not the first. This is weird, because how could the first moment be incorrect, while the rest are right? I looked over my code many times, and I still can't find the error. Could someone please help?

Edit: here's my input and output

x <- rnorm(5)

CalculateSampleMomentAroundMean(x)
$first
[1] -2.220446e-17

$second
[1] 0.2923308

$third
[1] -0.02291481

$fourth
[1] 0.1172637

> moment(x, order = 1, central = TRUE)
[1] -8.326673e-18

> moment(x, order = 2, central = TRUE)
[1] 0.2923308

> moment(x, order = 3, central = TRUE)
[1] -0.02291481

> moment(x, order = 4, central = TRUE)
[1] 0.1172637

You function is calculating things correctly. Because the calculation was performed differently in the moments function, the errors from the floating point representation of the numbers added up differently.

Essentially what is happening is because the machine cannot represent any given floating point number exactly, when you try to do math on a number like sqrt(2) , small errors are introduced. These errors add up differently depending on what you are doing. For example, if you multiply and then add, the floating point error may be different than if you added and then multiplied. In any event, the error is less than a value called machine precision which is about 1e-16. Since the differences between moments and your function are within that value, the difference is not meaningful.

I would suggest that if the moment is 1, you automatically return 0. That would avoid this problem.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM