7

问题:如何在小长度的 NaN 上进行局部插值?

我有一个包含 NaN 块的时间序列(“x”数据在“t”时间均匀采样)。例如:

x = [ 1   2   4    2 3 15 10 NaN NaN NaN NaN 2 4 NaN 19 25]
t = [0.1 0.2 0.3 ...etc..]

我想对 NaN 执行插值。

最基本的方法是从最左边的数据点线性插值到最右边的数据点。例如。从 x = 10 到 x = 2 的线和 4 NaN 值将从该线分配值。

时间序列的长度约为 150 万和 10000 NaN,因此我不想合并远离 NaN 位置的数据(在插值中)。一些 NaN 的长度为 1000-2000。

X(isnan(X)) = interp1(find(~isnan(X)), X(~isnan(X)), find(isnan(X)), 'linear'); 

将使用整个时间序列对 NaN 进行线性插值。

我将如何在本地进行插值?线性应该足够了。也许线性插值在 NaN 块的左侧和右侧合并了几个点(可能是 100-200 点)。自然邻居或样条(?)算法可能更合适;我必须小心不要向时间序列添加异常行为(例如,将虚构的“功率”添加到频率的插值)。

更新:时间序列是在一年内的分钟采样温度记录。线性插值就足够了;我只需要填写大约 6-7 小时的 NaN 间隔(在 NaN 间隔之前和 NaN 间隔之后向我提供了数据)。

4

2 回答 2

5

我认为这是(至少部分)你所寻求的:

% example data
x = [ 1   2   4    2 3 15 10 NaN NaN NaN NaN 2 4 NaN 19 25];
t = linspace(0.1, 10, numel(x));

% indices to NaN values in x 
% (assumes there are no NaNs in t)
nans = isnan(x);

% replace all NaNs in x with linearly interpolated values
x(nans) = interp1(t(~nans), x(~nans), t(nans));

请注意,您可以在此处轻松切换插值方法:

% cubic splines
x(nans) = interp1(t(~nans), x(~nans), t(nans), 'spline');

% nearest neighbor
x(nans) = interp1(t(~nans), x(~nans), t(nans), 'nearest');
于 2012-11-19T06:56:33.553 回答
3

考虑使用inpaint_nans,这是一个非常好的工具,旨在使用非 NaN 元素在 1-d 或 2-d 数组中插入 NaN 元素。它也可以推断,因为它不使用数据的三角剖分。它还允许不同的插值方法。

于 2012-11-19T03:45:15.187 回答