---
title: "10 - Statistical Functions with Missing Values"
output:
  litedown::html_format:
    options:
      toc: true
      number_sections: true
vignette: >
  %\VignetteIndexEntry{10 - Statistical Functions with Missing Values}
  %\VignetteEngine{litedown::vignette}
  %\VignetteEncoding{UTF-8}
editor:
  markdown:
    wrap: sentence
bibliography: ["references.bib"]
---

## Notes

* These functions ignore `NA` values for now. Adjustments for handling `NA` values are covered in a separate vignette.
* R already provides efficient versions of the functions covered here. This is just to illustrate how to use C++ code.

## Sum

The following function expands the previous `sum_cpp()` function to handle missing values.

```cpp
[[cpp4r::register]]
double sum2_cpp(doubles x, bool na_rm = false) {
  int n = x.size();
  double total = 0;
  for (int i = 0; i < n; ++i) {
    if (na_rm && ISNAN(x[i])) {
      continue;
    } else {
      total += x[i];
    }
  }
  return total;
}
```

Benchmark the functions as in the "Logical Functions" and "Rolling Functions" vignettes.

## Arithmetic mean

The following function expands the previous `mean_cpp()` function to handle missing values.

```cpp
[[cpp4r::register]]
double mean2_cpp(doubles x, bool na_rm = false) {
  int n = x.size();
  int m = 0;
  
  for (int i = 0; i < n; ++i) {
    if (na_rm && ISNAN(x[i])) {
      continue;
    } else {
      ++m;
    }
  }

  if (m == 0) {
    return NA_REAL;
  }

  double total = 0;
  for (int i = 0; i < n; ++i) {
    if (na_rm && ISNAN(x[i])) {
      continue;
    } else {
      total += x[i];
    }
  }

  return total / m;
}
```

Benchmark the functions as in the "Logical Functions" and "Rolling Functions" vignettes.

## Variance

The following function expands the previous `var_cpp()` function to handle missing values.

```cpp
[[cpp4r::register]]
double var2_cpp(doubles x, bool na_rm = false) {
  int n = x.size();
  int m = 0;
  double total = 0, sq_total = 0;

  for (int i = 0; i < n; ++i) {
    if (na_rm && ISNAN(x[i])) {
      continue;
    } else {
      ++m;
      total += x[i];
      sq_total += pow(x[i], 2);
    }
  }

  if (m <= 1) {
    return NA_REAL;
  }

  return (sq_total - total * total / m) / (m - 1);
}
```

Benchmark the functions as in the "Logical Functions" and "Rolling Functions" vignettes.

## Root Mean Square Error (RMSE)

The following function expands the previous `rmse_cpp()` function to handle missing values.

```cpp
[[cpp4r::register]]
double rmse2_cpp(doubles x, double x0, bool na_rm = false) {
  int n = x.size();
  int m = 0;
  double total = 0;

  for (int i = 0; i < n; ++i) {
    if (na_rm && ISNAN(x[i])) {
      continue;
    } else {
      ++m;
      total += pow(x[i] - x0, 2);
    }
  }

  if (m == 0) {
    return NA_REAL;
  }

  return sqrt(total / m);
}
```

Benchmark the functions as in the "Logical Functions" and "Rolling Functions" vignettes.
