NumCpp  2.12.1
A Templatized Header Only C++ Implementation of the Python NumPy Library
percentile.hpp
Go to the documentation of this file.
1
28#pragma once
29
30#include <algorithm>
31#include <cmath>
32#include <complex>
33#include <string>
34
35#include "NumCpp/Core/Enums.hpp"
39#include "NumCpp/Core/Shape.hpp"
40#include "NumCpp/Core/Types.hpp"
43#include "NumCpp/NdArray.hpp"
45
46namespace nc
47{
48 //============================================================================
49 // Method Description:
65 template<typename dtype>
67 double inPercentile,
68 Axis inAxis = Axis::NONE,
70 {
72
73 if (inPercentile < 0. || inPercentile > 100.)
74 {
75 THROW_INVALID_ARGUMENT_ERROR("input percentile value must be of the range [0, 100].");
76 }
77
78 if (inArray.isempty())
79 {
80 return {};
81 }
82 else if (inArray.isscalar())
83 {
84 NdArray<double> returnArray = { static_cast<double>(inArray.front()) };
85 return returnArray;
86 }
87
88 switch (inAxis)
89 {
90 case Axis::NONE:
91 {
92 NdArray<double> arrayCopy = inArray.template astype<double>();
93 stl_algorithms::sort(arrayCopy.begin(), arrayCopy.end());
94
95 if (utils::essentiallyEqual(inPercentile, 0.))
96 {
97 NdArray<double> returnArray = { arrayCopy.front() };
98 return returnArray;
99 }
100 if (utils::essentiallyEqual(inPercentile, 100.))
101 {
102 NdArray<double> returnArray = { arrayCopy.back() };
103 return returnArray;
104 }
105
106 const auto i =
107 static_cast<uint32>(std::floor(static_cast<double>(inArray.size() - 1) * inPercentile / 100.));
108 const auto indexLower = clip<uint32>(i, 0, inArray.size() - 2);
109
110 switch (inInterpMethod)
111 {
113 {
114 const double percentI =
115 static_cast<double>(indexLower) / static_cast<double>(inArray.size() - 1);
116 const double fraction =
117 (inPercentile / 100. - percentI) /
118 (static_cast<double>(indexLower + 1) / static_cast<double>(inArray.size() - 1) - percentI);
119
120 NdArray<double> returnArray = {
121 arrayCopy[indexLower] + (arrayCopy[indexLower + 1] - arrayCopy[indexLower]) * fraction
122 };
123 return returnArray;
124 }
126 {
127 NdArray<double> returnArray = { arrayCopy[indexLower] };
128 return returnArray;
129 }
131 {
132 NdArray<double> returnArray = { arrayCopy[indexLower + 1] };
133 return returnArray;
134 }
136 {
137 const double percent = inPercentile / 100.;
138 const double percent1 =
139 static_cast<double>(indexLower) / static_cast<double>(inArray.size() - 1);
140 const double percent2 =
141 static_cast<double>(indexLower + 1) / static_cast<double>(inArray.size() - 1);
142 const double diff1 = percent - percent1;
143 const double diff2 = percent2 - percent;
144
145 switch (argmin<double>({ diff1, diff2 }).item())
146 {
147 case 0:
148 {
149 NdArray<double> returnArray = { arrayCopy[indexLower] };
150 return returnArray;
151 }
152 case 1:
153 {
154 NdArray<double> returnArray = { arrayCopy[indexLower + 1] };
155 return returnArray;
156 }
157 }
158
159 return {}; // get rid of compiler warning
160 }
162 {
163 NdArray<double> returnArray = { (arrayCopy[indexLower] + arrayCopy[indexLower + 1]) / 2. };
164 return returnArray;
165 }
166 default:
167 {
168 THROW_INVALID_ARGUMENT_ERROR("Unimplemented Interpolation method.");
169 return {}; // get rid of compiler warning
170 }
171 }
172 }
173 case Axis::COL:
174 {
175 const Shape inShape = inArray.shape();
176
177 NdArray<double> returnArray(1, inShape.rows);
178 for (uint32 row = 0; row < inShape.rows; ++row)
179 {
180 returnArray[row] =
181 percentile(NdArray<dtype>(const_cast<typename NdArray<dtype>::pointer>(&inArray.front(row)),
182 inShape.cols,
184 inPercentile,
186 inInterpMethod)
187 .item();
188 }
189
190 return returnArray;
191 }
192 case Axis::ROW:
193 {
194 return percentile(inArray.transpose(), inPercentile, Axis::COL, inInterpMethod);
195 }
196 default:
197 {
198 THROW_INVALID_ARGUMENT_ERROR("Unimplemented axis type.");
199 return {}; // get rid of compiler warning
200 }
201 }
202
203 return {}; // get rid of compiler warning
204 }
205} // namespace nc
#define THROW_INVALID_ARGUMENT_ERROR(msg)
Definition: Error.hpp:37
#define STATIC_ASSERT_ARITHMETIC(dtype)
Definition: StaticAsserts.hpp:39
size_type size() const noexcept
Definition: NdArrayCore.hpp:4524
iterator end() noexcept
Definition: NdArrayCore.hpp:1623
typename AllocTraits::pointer pointer
Definition: NdArrayCore.hpp:152
self_type transpose() const
Definition: NdArrayCore.hpp:4882
bool isempty() const noexcept
Definition: NdArrayCore.hpp:2932
const Shape & shape() const noexcept
Definition: NdArrayCore.hpp:4511
const_reference back() const noexcept
Definition: NdArrayCore.hpp:2287
const_reference front() const noexcept
Definition: NdArrayCore.hpp:2860
iterator begin() noexcept
Definition: NdArrayCore.hpp:1315
bool isscalar() const noexcept
Definition: NdArrayCore.hpp:2956
value_type item() const
Definition: NdArrayCore.hpp:3022
A Shape Class for NdArrays.
Definition: Core/Shape.hpp:41
uint32 rows
Definition: Core/Shape.hpp:44
uint32 cols
Definition: Core/Shape.hpp:45
void sort(RandomIt first, RandomIt last) noexcept
Definition: StlAlgorithms.hpp:696
bool essentiallyEqual(dtype inValue1, dtype inValue2) noexcept
Definition: essentiallyEqual.hpp:49
Definition: Cartesian.hpp:40
InterpolationMethod
Definition: Enums.hpp:139
Axis
Enum To describe an axis.
Definition: Enums.hpp:36
dtype floor(dtype inValue) noexcept
Definition: floor.hpp:48
NdArray< double > percentile(const NdArray< dtype > &inArray, double inPercentile, Axis inAxis=Axis::NONE, InterpolationMethod inInterpMethod=InterpolationMethod::LINEAR)
Definition: percentile.hpp:66
std::uint32_t uint32
Definition: Types.hpp:40