I'm trying to implement a rolling mean ala pandas
via the xtensor
library. However I'm unable to assign the expression xt::mean(x_window)
to the double result[i]
.
#include <iostream>
#include <xtensor/xarray.hpp>
#include <xtensor/xio.hpp>
#include <xtensor/xview.hpp>
#include <xtensor/xadapt.hpp>
#include <vector>
// implement rolling mean
template<typename T>
xt::xarray<T> rolling_mean(const xt::xarray<T> &x, const int window) {
const auto nan = std::numeric_limits<T>::quiet_NaN();
xt::xarray<T> result = xt::full_like(x, nan);
for (int i = 0; i < x.shape()[0] - window + 1; i++) {
auto x_window = xt::view(x, xt::range(i, i + window));
result[i + window - 1] = xt::mean(x_window); // <-- problematic step
}
return result;
}
int main(int argc, char *argv[]) {
using T = double;
std::vector<T> v = {1, 2, 3, 4, 5};
xt::xarray<T> a = xt::adapt(v);
std::cout << rolling_mean(a,2) << std::endl; // [nan, 1.5, 2.5, 3.5, 4.5] expected
}
How do I fix this?
The compilation fails with the error message
error: assigning to 'double' from incompatible type 'xt::xfunction<xt::detail::divides, xt::xreducer<xt::xreducer_functors<xt::detail::plus, xt::const_value<double>>, const xt::xview<xt::xarray_container<xt::uvector<double, xsimd::aligned_allocator<double, 16>>, xt::layout_type::row_major, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true>> &, xt::xrange<long>> &, xt::svector<unsigned long, 4, std::allocator<unsigned long>, true>, xt::reducer_options<double, std::tuple<xt::evaluation_strategy::lazy_type>>>, xt::xscalar<double>>'
The problem is that you're not actually calling the callable resulting from xt::mean
but instead trying to assign the result of xt::mean
to a double
.
To solve this just call it by adding the parenthesis ()
and then assign that to the double
as shown below:
//----------------------------vv---->added this parenthesis
result[i] = xt::mean(x_window)();