目录
一.理论知识
所谓插值,顾名思义,插入数值。很多时候,我们仅有离散点上的数据,这时如果我们想要分析变量之间的函数关系,则无法实现。但如果通过插值处理,当精度足够高时,离散点便可以变成连续的曲线~这就是插值的实用意义。
如下是插值法的原理,大家看一下就好了
常见的插值法有4种:拉格朗日插值、分段线性插值、埃尔米特(Hermite)插值 、三次样条插值
二.一维插值实例
p = interp1 (x, y, new_x, 'spline');
如上的代码即可实现一维插值,不同插值方式只需要修改第4个参数即可。
已知人口数:
年份 人口(万) 2009 133126 2010 133770 2011 134413 2012 135069 2013 135738 2014 136427 2015 137122 2016 137866 2017 138639 2018 139538
x=2009:1:2018; y=[133126 133770 134413 135069 135738 136427 137122 137866 138639 139538 ]; new_x=2009:0.1:2018; p = interp1 (x, y, new_x, 'spline'); plot(new_x,p)
三.二维插值实例
首先分享一个沙盘制作问题:
实现代码:
z=[2000,2000,2001,1992,1954,1938,1972,1995,1999,1999;2000,2002,2006,1908,1533,1381,1728,1959,1998,2000;2000,2005,2043,1921,977,897,1310,1930,2003,2000;1997,1978,2009,2463,2374,1445,1931,2209,2050,2003;1992,1892,1566,1971,2768,2111,2653,2610,2121,2007;1991,1875,1511,1556,2221,1986,2660,2601,2119,2007;1996,1950,1797,2057,2849,2798,2608,2303,2052,2003;1999,1999,2079,2685,3390,3384,2781,2165,2016,2000;2000,2002,2043,2271,2668,2668,2277,2049,2003,2000;2000,2000,2004,2027,2067,2067,2027,2004,2000,2000]; x=0:200:1800; y=x' surf(x,y,z);
如上图,未经二维插值处理的图像表面很粗糙。
x1=0:100:1800; y1=x1'; z1=interp2(x,y,z,x1,y1,'spline'); surf(x1,y1,z1)
而经过插值处理后, 表面变得光滑。
如上图,进一步提高插值精度(为上一张的2倍精度),表面变得更加光滑。
再来看另一个例子,如下图是一个关于油耗数值的散点图:
经过插值处理,三维图变得光滑(数据找不到了唉~,大家只要会套用代码就行)
x1=10:1:120; n1=interp1(x,y1,x1,'spline'); n2=interp1(x,y2,x1,'spline'); n3=interp1(x,y3,x1,'spline'); figure(1) plot(x1,n1); hold on plot(x1,n2); hold on plot(x1,n3); hold off
拓展:n维数据的插值:
% n维数据的插值
x = -pi:pi; y = sin(x);
new_x = -pi:0.1:pi;
p = interpn (x, y, new_x, 'spline');
% 等价于 p = spline(x, y, new_x);
figure(3);
plot(x, y, 'o', new_x, p, 'r-')
四.基于父母的身高预测孩子身高的案例
通过双亲的身高及孩子的身高,采用插值法计算目标男孩的身高。
首先通过随机数法,产生100个双亲平均身高的数据
count =100;
%样本总数
parent1=unifrnd(160,185,100,1);
%随机产生100个,父母平均身高在160cm——185cm的样本
接下来根据高尔顿的模型方程计算对应男孩的身高:
y= 0.8567+0.516*parent1;
%高尔顿的影响方程
接下来进行目标计算:首先提高数据精度,将值扩展到10000个样本;其次,假设父亲183cm,母亲164cm(均值为173.5),作为目标输入,进行计算:
count1=160:0.01:185;
son1=interp1(parent,son,count1,'spline');
%完成插值
最终在插值结果寻找173.5对应的项即可。
附加:对如下的数据实现插值
1 | 3 | 5 | 7 | 9 | 11 | 13 | 15 |
1913 | 1945 | 1920 | 2205 | 2260 | 2302 | 2385 | 2420 |
5.12 | 3.2 | 6.72 | 3.36 | 2.4 | 4.14 | 6.43 | 4.6 |
21.9 | 20 | 26.8 | 27.73 | 23.4 | 22.75 | 25.36 | 26.03 |
24.8 | 25.7 | 26.8 | 28 | 30.4 | 30 | 27.6 | 30.8 |
9.31 | 9.14 | 9.14 | 9.29 | 9.22 | 9.33 | 9.16 | 9.26 |
1.8 | 2.3 | 1.9 | 2.1 | 2.1 | 1.1 | 1.5 | 1.5 |
28 | 24 | 26 | 22 | 22 | 20 | 19 | 23 |
425.11 | 457.99 | 492.48 | 492.08 | 501.93 | 598.48 | 604.44 | 623.89 |
628.1 | 639.2 | 648.87 | 640.33 | 616.43 | 614.72 | 507.14 | 580 |
28 | 24 | 26 | 22 | 22 | 20 | 19 | 23 |
30.58 | 36.19 | 49.75 | 60.58 | 56.58 | 60.06 | 67.99 | 67.74 |
load Z.mat
x=Z(1,:);
[n,m]=size(Z);
ylab={'周数','轮虫','溶氧','COD','水温','PH值','盐度','透明度','总碱度','氯离子','透明度','生物量'};
disp(['共有' num2str(n-1) '个指标要进行插值。'])
disp('正在对一号池三次埃尔米特插值,请等待')
P=zeros(11,15);
for i=2:n
y=Z(i,:);
new_x=1:15;
p1=pchip(x,y,new_x);
subplot(4,3,i-1);
plot(x,y,'ro',new_x,p1,'-');
axis([0 15,-inf,inf])
% xlabel('星期')
ylabel(ylab{i})
P(i-1,:)=p1;
end
legend('原始数据','三次埃尔米特插值数据','Location','SouthEast')%加上标注,注意要手动在图中拖动标注到图片右下角哦
P = [1:15; P]