14#ifndef XTENSOR_HISTOGRAM_HPP
15#define XTENSOR_HISTOGRAM_HPP
17#include "../containers/xtensor.hpp"
18#include "../misc/xset_operation.hpp"
19#include "../misc/xsort.hpp"
20#include "../views/xview.hpp"
22using namespace xt::placeholders;
40 template <
class E1,
class E2>
41 inline auto digitize(E1&& data, E2&& bin_edges,
bool right =
false)
43 XTENSOR_ASSERT(bin_edges.dimension() == 1);
44 XTENSOR_ASSERT(bin_edges.size() >= 2);
45 XTENSOR_ASSERT(std::is_sorted(bin_edges.cbegin(), bin_edges.cend()));
46 XTENSOR_ASSERT(
xt::amin(data)[0] >= bin_edges[0]);
47 XTENSOR_ASSERT(
xt::amax(data)[0] <= bin_edges[bin_edges.size() - 1]);
49 return xt::searchsorted(std::forward<E2>(bin_edges), std::forward<E1>(data), right);
54 template <
class R =
double,
class E1,
class E2,
class E3>
55 inline auto histogram_imp(E1&& data, E2&& bin_edges, E3&& weights,
bool density,
bool equal_bins)
57 using size_type = common_size_type_t<std::decay_t<E1>, std::decay_t<E2>, std::decay_t<E3>>;
58 using value_type =
typename std::decay_t<E3>::value_type;
60 XTENSOR_ASSERT(data.dimension() == 1);
61 XTENSOR_ASSERT(weights.dimension() == 1);
62 XTENSOR_ASSERT(bin_edges.dimension() == 1);
63 XTENSOR_ASSERT(weights.size() == data.size());
64 XTENSOR_ASSERT(bin_edges.size() >= 2);
65 XTENSOR_ASSERT(std::is_sorted(bin_edges.cbegin(), bin_edges.cend()));
67 size_t n_bins = bin_edges.size() - 1;
72 std::array<typename std::decay_t<E2>::value_type, 2> bounds =
xt::minmax(bin_edges)();
73 auto left =
static_cast<double>(bounds[0]);
74 auto right =
static_cast<double>(bounds[1]);
75 double norm = 1. / (right - left);
76 for (
size_t i = 0; i < data.size(); ++i)
78 auto v =
static_cast<double>(data(i));
80 if (v >= left && v < right)
82 auto i_bin =
static_cast<size_t>(
static_cast<double>(n_bins) * (v - left) *
norm);
83 count(i_bin) += weights(i);
87 count(n_bins - 1) += weights(i);
93 auto sorter = xt::argsort(data);
97 for (
auto& idx : sorter)
99 auto item = data[idx];
101 if (item < bin_edges[0])
106 if (item > bin_edges[n_bins])
111 while (item >= bin_edges[ibin + 1] && ibin < n_bins - 1)
116 count[ibin] += weights[idx];
124 R n =
static_cast<R
>(data.size());
125 for (size_type i = 0; i < bin_edges.size() - 1; ++i)
127 prob[i] /= (
static_cast<R
>(bin_edges[i + 1] - bin_edges[i]) * n);
151 template <
class R =
double,
class E1,
class E2,
class E3>
152 inline auto histogram(E1&& data, E2&& bin_edges, E3&& weights,
bool density =
false)
154 return detail::histogram_imp<R>(
155 std::forward<E1>(data),
156 std::forward<E2>(bin_edges),
157 std::forward<E3>(weights),
172 template <
class R =
double,
class E1,
class E2>
173 inline auto histogram(E1&& data, E2&& bin_edges,
bool density =
false)
175 using value_type =
typename std::decay_t<E1>::value_type;
177 auto n = data.size();
179 return detail::histogram_imp<R>(
180 std::forward<E1>(data),
181 std::forward<E2>(bin_edges),
197 template <
class R =
double,
class E1>
198 inline auto histogram(E1&& data, std::size_t bins = 10,
bool density =
false)
200 using value_type =
typename std::decay_t<E1>::value_type;
202 auto n = data.size();
204 return detail::histogram_imp<R>(
205 std::forward<E1>(data),
224 template <
class R =
double,
class E1,
class E2>
225 inline auto histogram(E1&& data, std::size_t bins, E2 left, E2 right,
bool density =
false)
227 using value_type =
typename std::decay_t<E1>::value_type;
229 auto n = data.size();
231 return detail::histogram_imp<R>(
232 std::forward<E1>(data),
250 template <
class R =
double,
class E1,
class E2>
251 inline auto histogram(E1&& data, std::size_t bins, E2&& weights,
bool density =
false)
253 return detail::histogram_imp<R>(
254 std::forward<E1>(data),
256 std::forward<E2>(weights),
274 template <
class R =
double,
class E1,
class E2,
class E3>
275 inline auto histogram(E1&& data, std::size_t bins, E2&& weights, E3 left, E3 right,
bool density =
false)
277 return detail::histogram_imp<R>(
278 std::forward<E1>(data),
280 std::forward<E2>(weights),
310 template <
class E1,
class E2,
class E3>
316 std::size_t bins = 10,
321 using size_type = common_size_type_t<std::decay_t<E1>, std::decay_t<E2>>;
322 using value_type =
typename std::decay_t<E1>::value_type;
323 using weights_type =
typename std::decay_t<E2>::value_type;
327 XTENSOR_ASSERT(data.dimension() == 1);
328 XTENSOR_ASSERT(weights.dimension() == 1);
330 XTENSOR_ASSERT(weights.size() == data.size());
332 XTENSOR_ASSERT(left <= right);
334 XTENSOR_ASSERT(bins > std::size_t(0));
340 case histogram_algorithm::automatic:
347 case histogram_algorithm::linspace:
354 case histogram_algorithm::logspace:
356 using rhs_value_type = std::conditional_t<xtl::is_integral<value_type>::value, double, value_type>;
370 case histogram_algorithm::uniform:
373 auto sorter = xt::argsort(data);
386 std::vector<size_t> shape = {bins + 1};
390 bin_edges[bins] = right;
392 weights_type cum_weight =
static_cast<weights_type
>(0);
396 for (size_type i = 0; i < weights.size(); ++i)
398 if (cum_weight >= count[ibin])
400 bin_edges[ibin + 1] = data[sorter[i]];
403 cum_weight += weights[sorter[i]];
427 template <
class E1,
class E2>
431 std::size_t bins = 10,
435 using value_type =
typename std::decay_t<E1>::value_type;
436 std::array<value_type, 2> left_right;
440 std::forward<E1>(data),
441 std::forward<E2>(weights),
462 using value_type =
typename std::decay_t<E1>::value_type;
464 auto n = data.size();
465 std::array<value_type, 2> left_right;
469 std::forward<E1>(data),
489 template <
class E1,
class E2>
494 std::size_t bins = 10,
498 using value_type =
typename std::decay_t<E1>::value_type;
500 auto n = data.size();
522 template <
class E1,
class E2, XTL_REQUIRES(is_xexpression<std::decay_t<E2>>)>
523 inline auto bincount(E1&& data, E2&& weights, std::size_t minlength = 0)
525 using result_value_type =
typename std::decay_t<E2>::value_type;
526 using input_value_type =
typename std::decay_t<E1>::value_type;
527 using size_type =
typename std::decay_t<E1>::size_type;
530 xtl::is_integral<typename std::decay_t<E1>::value_type>::value,
531 "Bincount data has to be integral type."
533 XTENSOR_ASSERT(data.dimension() == 1);
534 XTENSOR_ASSERT(weights.dimension() == 1);
536 std::array<input_value_type, 2> left_right;
539 if (left_right[0] < input_value_type(0))
541 XTENSOR_THROW(std::runtime_error,
"Data argument for bincount can only contain positive integers!");
545 {(std::max)(minlength, std::size_t(left_right[1] + 1))}
548 for (size_type i = 0; i < data.size(); ++i)
550 res(data(i)) += weights(i);
557 inline auto bincount(E1&& data, std::size_t minlength = 0)
560 std::forward<E1>(data),
561 xt::ones<
typename std::decay_t<E1>::value_type>(data.shape()),
578 if (weights.size() <= std::size_t(1))
584#ifdef XTENSOR_ENABLE_ASSERT
585 using value_type =
typename std::decay_t<E>::value_type;
587 XTENSOR_ASSERT(
xt::all(weights >=
static_cast<value_type
>(0)));
588 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 digitize(E1 &&data, E2 &&bin_edges, bool right=false)
Return the indices of the bins to which each value in input array belongs.
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 histogram(E1 &&data, E2 &&bin_edges, E3 &&weights, bool density=false)
Compute the histogram of a set of data.
histogram_algorithm
Defines different algorithms to be used in "histogram_bin_edges".
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 searchsorted(E1 &&a, E2 &&v, bool right=true)
Find indices where elements should be inserted to maintain order.
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 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 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 keep(T &&indices)
Create a non-contigous slice from a container of indices to keep.
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.