nan_handling.hpp
1 // Copyright © 2020 Thomas Nagler
2 //
3 // This file is part of the wdm library and licensed under the terms of
4 // the MIT license. For a copy, see the LICENSE file in the root directory
5 // or https://github.com/tnagler/wdm/blob/master/LICENSE.
6 
7 #pragma once
8 
9 #include "methods.hpp"
10 
11 #include <cmath>
12 #include <limits>
13 #include <sstream>
14 #include <vector>
15 
16 namespace wdm {
17 
18 namespace utils {
19 
20 inline void
21 remove_incomplete(std::vector<double>& x,
22  std::vector<double>& y,
23  std::vector<double>& w)
24 {
25  size_t complete_count = 0;
26  for (size_t i = 0; i < x.size(); ++i) {
27  bool row_has_nan = (std::isnan(x[i]) || std::isnan(y[i]));
28  if (w.size() > 0)
29  row_has_nan = (row_has_nan || std::isnan(w[i]));
30  if (!row_has_nan) {
31  x[complete_count] = x[i];
32  y[complete_count] = y[i];
33  if (w.size() > 0)
34  w[complete_count] = w[i];
35  ++complete_count;
36  }
37  }
38 
39  x.resize(complete_count);
40  y.resize(complete_count);
41  if (w.size() > 0)
42  w.resize(complete_count);
43 }
44 
45 inline bool
46 any_nan(const std::vector<double>& x)
47 {
48  for (size_t i = 0; (i < x.size()); i++) {
49  if (std::isnan(x[i]))
50  return true;
51  }
52 
53  return false;
54 }
55 
56 inline void
57 validate_weights(const std::vector<double>& weights)
58 {
59  if (weights.empty())
60  return;
61  double weight_sum = 0.0;
62  for (const auto& weight : weights) {
63  if (!std::isfinite(weight) || weight < 0.0)
64  throw std::runtime_error("weights must be finite and nonnegative.");
65  weight_sum += weight;
66  }
67  if (!std::isfinite(weight_sum) || weight_sum <= 0.0)
68  throw std::runtime_error("weights must have a finite, positive sum.");
69 }
70 
71 inline std::string
72 preproc(std::vector<double>& x,
73  std::vector<double>& y,
74  std::vector<double>& weights,
75  std::string method,
76  bool remove_missing)
77 {
78  if (!methods::is_supported(method))
79  throw std::runtime_error("method not implemented.");
80 
81  if (remove_missing) {
82  utils::remove_incomplete(x, y, weights);
83  utils::validate_weights(weights);
84  if (x.size() < methods::get_min_nobs(method))
85  return "return_nan";
86  } else {
87  std::stringstream msg;
88  if (utils::any_nan(x) || utils::any_nan(y) || utils::any_nan(weights)) {
89  msg << "there are missing values in the data; "
90  << "try remove_missing = TRUE";
91  } else {
92  utils::validate_weights(weights);
93  if (x.size() < methods::get_min_nobs(method))
94  msg << "need at least " << methods::get_min_nobs(method)
95  << " observations.";
96  }
97  if (!msg.str().empty())
98  throw std::runtime_error(msg.str());
99  }
100 
101  return "continue";
102 }
103 
104 } // end utils
105 
106 } // end wdm
Weighted dependence measures.
Definition: wdm.hpp:19