14#ifndef XTENSOR_HISTOGRAM_HPP
15#define XTENSOR_HISTOGRAM_HPP
17#include "xset_operation.hpp"
22using namespace xt::placeholders;
35 template <
class E1,
class E2>
36 inline auto digitize(E1&& data, E2&& bin_edges,
bool right =
false)
38 XTENSOR_ASSERT(bin_edges.dimension() == 1);
39 XTENSOR_ASSERT(bin_edges.size() >= 2);
40 XTENSOR_ASSERT(std::is_sorted(bin_edges.cbegin(), bin_edges.cend()));
41 XTENSOR_ASSERT(
xt::amin(data)[0] >= bin_edges[0]);
42 XTENSOR_ASSERT(
xt::amax(data)[0] <= bin_edges[bin_edges.size() - 1]);
44 return xt::searchsorted(std::forward<E2>(bin_edges), std::forward<E1>(data), right);
49 template <
class R =
double,
class E1,
class E2,
class E3>
50 inline auto histogram_imp(E1&& data, E2&& bin_edges, E3&& weights,
bool density,
bool equal_bins)
52 using size_type = common_size_type_t<std::decay_t<E1>, std::decay_t<E2>, std::decay_t<E3>>;
53 using value_type =
typename std::decay_t<E3>::value_type;
55 XTENSOR_ASSERT(data.dimension() == 1);
56 XTENSOR_ASSERT(weights.dimension() == 1);
57 XTENSOR_ASSERT(bin_edges.dimension() == 1);
58 XTENSOR_ASSERT(weights.size() == data.size());
59 XTENSOR_ASSERT(bin_edges.size() >= 2);
60 XTENSOR_ASSERT(std::is_sorted(bin_edges.cbegin(), bin_edges.cend()));
62 size_t n_bins = bin_edges.size() - 1;
67 std::array<typename std::decay_t<E2>::value_type, 2> bounds =
xt::minmax(bin_edges)();
68 auto left =
static_cast<double>(bounds[0]);
69 auto right =
static_cast<double>(bounds[1]);
70 double norm = 1. / (right - left);
71 for (
size_t i = 0; i < data.size(); ++i)
73 auto v =
static_cast<double>(data(i));
75 if (v >= left && v < right)
77 auto i_bin =
static_cast<size_t>(
static_cast<double>(n_bins) * (v - left) *
norm);
78 count(i_bin) += weights(i);
82 count(n_bins - 1) += weights(i);
88 auto sorter = xt::argsort(data);
92 for (
auto& idx : sorter)
94 auto item = data[idx];
96 if (item < bin_edges[0])
101 if (item > bin_edges[n_bins])
106 while (item >= bin_edges[ibin + 1] && ibin < n_bins - 1)
111 count[ibin] += weights[idx];
119 R n =
static_cast<R
>(data.size());
120 for (size_type i = 0; i < bin_edges.size() - 1; ++i)
122 prob[i] /= (
static_cast<R
>(bin_edges[i + 1] - bin_edges[i]) * n);
141 template <
class R =
double,
class E1,
class E2,
class E3>
142 inline auto histogram(E1&& data, E2&& bin_edges, E3&& weights,
bool density =
false)
144 return detail::histogram_imp<R>(
145 std::forward<E1>(data),
146 std::forward<E2>(bin_edges),
147 std::forward<E3>(weights),
162 template <
class R =
double,
class E1,
class E2>
163 inline auto histogram(E1&& data, E2&& bin_edges,
bool density =
false)
165 using value_type =
typename std::decay_t<E1>::value_type;
167 auto n = data.size();
169 return detail::histogram_imp<R>(
170 std::forward<E1>(data),
171 std::forward<E2>(bin_edges),
187 template <
class R =
double,
class E1>
188 inline auto histogram(E1&& data, std::size_t bins = 10,
bool density =
false)
190 using value_type =
typename std::decay_t<E1>::value_type;
192 auto n = data.size();
194 return detail::histogram_imp<R>(
195 std::forward<E1>(data),
214 template <
class R =
double,
class E1,
class E2>
215 inline auto histogram(E1&& data, std::size_t bins, E2 left, E2 right,
bool density =
false)
217 using value_type =
typename std::decay_t<E1>::value_type;
219 auto n = data.size();
221 return detail::histogram_imp<R>(
222 std::forward<E1>(data),
240 template <
class R =
double,
class E1,
class E2>
241 inline auto histogram(E1&& data, std::size_t bins, E2&& weights,
bool density =
false)
243 return detail::histogram_imp<R>(
244 std::forward<E1>(data),
246 std::forward<E2>(weights),
264 template <
class R =
double,
class E1,
class E2,
class E3>
265 inline auto histogram(E1&& data, std::size_t bins, E2&& weights, E3 left, E3 right,
bool density =
false)
267 return detail::histogram_imp<R>(
268 std::forward<E1>(data),
270 std::forward<E2>(weights),
300 template <
class E1,
class E2,
class E3>
306 std::size_t bins = 10,
311 using size_type = common_size_type_t<std::decay_t<E1>, std::decay_t<E2>>;
312 using value_type =
typename std::decay_t<E1>::value_type;
313 using weights_type =
typename std::decay_t<E2>::value_type;
317 XTENSOR_ASSERT(data.dimension() == 1);
318 XTENSOR_ASSERT(weights.dimension() == 1);
320 XTENSOR_ASSERT(weights.size() == data.size());
322 XTENSOR_ASSERT(left <= right);
324 XTENSOR_ASSERT(bins > std::size_t(0));
330 case histogram_algorithm::automatic:
337 case histogram_algorithm::linspace:
344 case histogram_algorithm::logspace:
346 using rhs_value_type = std::conditional_t<xtl::is_integral<value_type>::value, double, value_type>;
360 case histogram_algorithm::uniform:
363 auto sorter = xt::argsort(data);
376 std::vector<size_t> shape = {bins + 1};
380 bin_edges[bins] = right;
382 weights_type cum_weight =
static_cast<weights_type
>(0);
386 for (size_type i = 0; i < weights.size(); ++i)
388 if (cum_weight >= count[ibin])
390 bin_edges[ibin + 1] = data[sorter[i]];
393 cum_weight += weights[sorter[i]];
417 template <
class E1,
class E2>
421 std::size_t bins = 10,
425 using value_type =
typename std::decay_t<E1>::value_type;
426 std::array<value_type, 2> left_right;
430 std::forward<E1>(data),
431 std::forward<E2>(weights),
452 using value_type =
typename std::decay_t<E1>::value_type;
454 auto n = data.size();
455 std::array<value_type, 2> left_right;
459 std::forward<E1>(data),
479 template <
class E1,
class E2>
484 std::size_t bins = 10,
488 using value_type =
typename std::decay_t<E1>::value_type;
490 auto n = data.size();
512 template <
class E1,
class E2, XTL_REQUIRES(is_xexpression<std::decay_t<E2>>)>
513 inline auto bincount(E1&& data, E2&& weights, std::size_t minlength = 0)
515 using result_value_type =
typename std::decay_t<E2>::value_type;
516 using input_value_type =
typename std::decay_t<E1>::value_type;
517 using size_type =
typename std::decay_t<E1>::size_type;
520 xtl::is_integral<typename std::decay_t<E1>::value_type>::value,
521 "Bincount data has to be integral type."
523 XTENSOR_ASSERT(data.dimension() == 1);
524 XTENSOR_ASSERT(weights.dimension() == 1);
526 std::array<input_value_type, 2> left_right;
529 if (left_right[0] < input_value_type(0))
531 XTENSOR_THROW(std::runtime_error,
"Data argument for bincount can only contain positive integers!");
535 {(std::max)(minlength, std::size_t(left_right[1] + 1))}
538 for (size_type i = 0; i < data.size(); ++i)
540 res(data(i)) += weights(i);
547 inline auto bincount(E1&& data, std::size_t minlength = 0)
550 std::forward<E1>(data),
551 xt::ones<
typename std::decay_t<E1>::value_type>(data.shape()),
568 if (weights.size() <= std::size_t(1))
574#ifdef XTENSOR_ENABLE_ASSERT
575 using value_type =
typename std::decay_t<E>::value_type;
577 XTENSOR_ASSERT(
xt::all(weights >=
static_cast<value_type
>(0)));
578 XTENSOR_ASSERT(
xt::sum(weights)() >
static_cast<value_type
>(0));
size_type size() const noexcept
Returns the number of element in the container.
constexpr const inner_shape_type & shape() const noexcept
Returns the shape of the container.
auto cumsum(E &&e, std::ptrdiff_t axis)
Cumulative sum.
auto amax(E &&e, X &&axes, EVS es=EVS())
Maximum element along given axis.
auto amin(E &&e, X &&axes, EVS es=EVS())
Minimum element along given axis.
auto cast(E &&e) noexcept -> detail::xfunction_type_t< typename detail::cast< R >::functor, E >
Element-wise static_cast.
auto ceil(E &&e) noexcept -> detail::xfunction_type_t< math::ceil_fun, E >
ceil function.
auto sum(E &&e, X &&axes, EVS es=EVS())
Sum of elements over given axes.
auto minmax(E &&e, EVS es=EVS())
Minimum and maximum among the elements of an array or expression.
auto norm(E &&e) noexcept
Calculates the squared magnitude elementwise for the complex numbers in e.
standard mathematical functions for xexpressions
auto range(A start_val, B stop_val)
Select a range from start_val to stop_val (excluded).
auto ones(S shape) noexcept
Returns an xexpression containing ones of the specified shape.
auto histogram_bin_edges(E1 &&data, E2 &&weights, E3 left, E3 right, std::size_t bins=10, histogram_algorithm mode=histogram_algorithm::automatic)
Compute the bin-edges of a histogram of a set of data using different algorithms.
auto zeros(S shape) noexcept
Returns an xexpression containing zeros of the specified shape.
xt::xtensor< size_t, 1 > bin_items(size_t N, E &&weights)
Get the number of items in each bin, given the fraction of items per bin.
auto searchsorted(E1 &&a, E2 &&v, bool right=true)
Find indices where elements should be inserted to maintain order.
auto digitize(E1 &&data, E2 &&bin_edges, bool right=false)
Return the indices of the bins to which each value in input array belongs.
auto linspace(T start, T stop, std::size_t num_samples=50, bool endpoint=true) noexcept
Generates num_samples evenly spaced numbers over given interval.
xtensor_container< uvector< T, A >, N, L > xtensor
Alias template on xtensor_container with default parameters for data container type.
auto histogram(E1 &&data, E2 &&bin_edges, E3 &&weights, bool density=false)
Compute the histogram of a set of data.
detail::disable_integral_keep< T > keep(T &&indices)
Create a non-contigous slice from a container of indices to keep.
histogram_algorithm
Defines different algorithms to be used in "histogram_bin_edges".
auto logspace(T start, T stop, std::size_t num_samples, T base=10, bool endpoint=true) noexcept
Generates num_samples numbers evenly spaced on a log scale over given interval.
auto bincount(E1 &&data, E2 &&weights, std::size_t minlength=0)
Count number of occurrences of each value in array of non-negative ints.
auto view(E &&e, S &&... slices)
Constructs and returns a view on the specified xexpression.