xtensor实现滚动均值时无法将xt::mean结果赋值给double类型元素
问题描述
我正在尝试通过xtensor库实现类似pandas的rolling mean(滚动均值)功能,但无法将表达式xt::mean(x_window)的结果赋值给double类型的result[i]元素。
复现代码
#include <iostream> #include <xtensor/xarray.hpp> #include <xtensor/xio.hpp> #include <xtensor/xview.hpp> #include <xtensor/xadapt.hpp> #include <vector> // 实现滚动均值 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); // <-- 出错位置 } 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] }
编译报错
代码编译失败,抛出的类型不匹配错误如下:
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>>'
问题原因
xtensor的所有运算、归约操作(包括xt::mean、xt::sum等)默认采用惰性求值逻辑:调用xt::mean(x_window)时不会立刻计算出数值结果,而是返回一个xfunction类型的表达式模板对象,用于延后计算优化性能。这个表达式对象无法隐式转换为double类型的标量值,直接赋值给result的元素就会触发类型不匹配的编译错误。
修复方案
赋值前手动触发惰性表达式的求值,拿到具体标量结果即可,常用写法有两种:
- 用
xt::eval()包裹xt::mean调用,强制即时求值,返回的0维xarray可自动转换为对应类型的标量 - 直接对惰性表达式执行
()运算符调用,显式取出计算完成的标量值
修复后代码
将出错行替换为以下任意一种写法即可:
// 写法1:通过eval触发求值 result[i + window - 1] = xt::eval(xt::mean(x_window)); // 写法2:直接取标量结果 result[i + window - 1] = xt::mean(x_window)();
完整可运行的修复版函数示例:
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::eval(xt::mean(x_window)); } return result; }
编译运行后即可得到预期输出:{ nan, 1.5, 2.5, 3.5, 4.5 }
内容的提问来源于stack exchange,提问作者marital_weeping
相关产品推荐
相关产品推荐

