2
0
mirror of https://github.com/boostorg/math.git synced 2026-01-19 04:22:09 +00:00

First pass at interquartile range.

This commit is contained in:
Nick Thompson
2019-12-29 15:34:22 -05:00
parent b3e1f4d8a1
commit f943649e68
2 changed files with 49 additions and 1 deletions

View File

@@ -465,5 +465,25 @@ inline auto median_absolute_deviation(RandomAccessContainer & v, typename Random
return median_absolute_deviation(v.begin(), v.end(), center);
}
template<class ForwardIterator>
auto interquartile_range(ForwardIterator first, ForwardIterator last)
{
using Real = typename std::iterator_traits<ForwardIterator>::value_type;
BOOST_ASSERT_MSG(std::distance(first, last) >= 4, "At least 4 samples are required to compute the interquartile range.");
std::nth_element(first, first + (last-first)/4, last);
Real Q1 = *(first + (last-first)/4);
auto q1 = first + (last-first)/4;
std::nth_element(q1, q1 + (last-q1)/2, last);
Real Q3 = *(first + 3*(last-first)/4);
return Q3 - Q1;
}
template<class RandomAccessContainer>
inline auto interquartile_range(RandomAccessContainer & v)
{
return interquartile_range(v.begin(), v.end());
}
}
#endif

View File

@@ -381,7 +381,7 @@ void test_kurtosis()
v = {1,2,3,4,5};
// mu =1, sigma^2 = 2, kurtosis = 17/10
kurt = boost::math::statistics::kurtosis(v);
BOOST_TEST(abs(kurt - Real(17)/Real(10)) < tol);
BOOST_TEST(abs(kurt - Real(17)/Real(10)) < 10*tol);
v = {0,0,0,0,5};
// mu = 1, sigma^2 = 4, sigma = 2, skew = 3/2, kurtosis = 13/4
@@ -723,6 +723,33 @@ void test_integer_gini_coefficient()
BOOST_TEST(abs(gini) < tol);
}
template<typename Real>
void test_interquartile_range()
{
// Taken from Wikipedia's example:
std::vector<Real> v{7, 7, 31, 31, 47, 75, 87, 115, 116, 119, 119, 155, 177};
// Q1 = 31, Q3 = 119, Q3 - Q1 = 88.
Real iqr = boost::math::statistics::interquartile_range(v);
BOOST_TEST_EQ(iqr, 88);
std::mt19937 gen(486);
std::shuffle(v.begin(), v.end(), gen);
iqr = boost::math::statistics::interquartile_range(v);
BOOST_TEST_EQ(iqr, 88);
std::shuffle(v.begin(), v.end(), gen);
iqr = boost::math::statistics::interquartile_range(v);
BOOST_TEST_EQ(iqr, 88);
std::fill(v.begin(), v.end(), 1);
iqr = boost::math::statistics::interquartile_range(v);
BOOST_TEST_EQ(iqr, 0);
}
int main()
{
test_mean<float>();
@@ -790,5 +817,6 @@ int main()
test_sample_gini_coefficient<long double>();
test_sample_gini_coefficient<cpp_bin_float_50>();
test_interquartile_range<double>();
return boost::report_errors();
}