在上关于matlab的课时,老师留了一道题目,题目内容如下:
根据所给的数据文件input.mat,以变量x为自变量,y为因变量,分别使用四种插值方式求出自变量为X时因变量的值Y,把图形窗口分割为四个区域,在每个区域分别画出四种不同插值方式时,插值前后的数据曲线。
这一道题目全班没有几个人做出来,但是我做出来了~ 于是我来分享一下我的经验~
一、怎么求插值?
先学习一下插值函数interp1
,interp1的函数的语法如下:
vq = interp1(x , y , xq , method)
其中的x
是原数据的X值(可以理解为横坐标的位置);y
是原数据的Y值(也是纵坐标的位置);xq
是你要插值的数据的X值;method
是插值方式,可以省略。插值方式有很多,比如linear,nearest,next,previous,pchip,cubic,v5cubic,makima,spline等,如果省略就是默认值linear(线性插值)
举个例子,我这里有一个从0到6的向量x,这个数字沿着y=sin(x)
路径走……
>> x = 0:1:6
x =
0 1 2 3 4 5 6
>> y = sin(x)
y =
0 0.8415 0.9093 0.1411 -0.7568 -0.9589 -0.2794
>>
在图上显示是这样的……
如果我想知道当使用线性插值时,x为0.5、2.5、4.5对应Y值。于是我可以这么的使用函数Y=interp(x,y,X)
……
>> X = [0.5,2.5,4.5]
X =
0.5000 2.5000 4.5000
>> Y = interp1(x,y,X);
>> Y
Y =
0.4207 0.5252 -0.8579
>>
于是我就可以知道了当X为0.5、2.5、4.5时,线性插值Y就是0.4207、0.5252、-0.8579
二、然后知道怎么排序
首先我们先学习一个函数sort,这个函数是一个排序函数,可以按照要求将数字、文本进行升序或者降序排序~ sort的语法如下:
[ B , I ] = sort( A )
其中,A中填入的可以是矩阵,也可以是向量,因为我们做的题目是和插值相关的,所以用向量就足够了;B是将矩阵/向量A排序以后返回的结果;I是返回排序后的值在原来向量中的索引。
我们举个例子,我先准备了一串向量A
,向量A
的值如下:
A = [9,8,7,6,5,4,3,2,1,0];
然后我们将向量A
里面的数据升序排序,我可以这么使用函数:
[B,I]=sort(A);
之后我们使用matlab分别查看B
和I
的值……
>> [B,I]=sort(A);
>> B
B =
0 1 2 3 4 5 6 7 8 9
>> I
I =
10 9 8 7 6 5 4 3 2 1
>>
我们可以发现,B
里面的值就是向量A升序排序以后的结果;我们再看I
,I
里面第一个数字10是什么呢?我们看看B
里面的第一个数字0
在向量A
里面的索引……正好就是数字10!
我们再看其他数字,排序过的数字的索引在原来的向量A里面都可以找到那个数字唉~ 于是我们就知道了,这个向量I里面的记的数字,正好就是对于原来的向量中数字的索引的位置!
三、融合在一起
我们先用我们第一部分的数据做个例子,我们目前有四个变量,分别是x,y,X,Y四个变量。
>> x
x =
0 1 2 3 4 5 6
>> y
y =
0 0.8415 0.9093 0.1411 -0.7568 -0.9589 -0.2794
>> X
X =
0.5000 2.5000 4.5000
>> Y
Y =
0.4207 0.5252 -0.8579
>>
我们再看一看我们之前展示的一张图片……观察图片,我们发现X轴的数字从左往右看是从小到大排列的,我们正好就可以使用之前的sort函数来将原数据和插值数据重新从小到大排序~
我们先要将原数据和插值数据放在一个向量里面,这个简单,我们可以这样……
>> xlist = [x,X]
xlist =
0 1.0000 2.0000 3.0000 4.0000 5.0000 6.0000 0.5000 2.5000 4.5000
>>
然后将这个向量进行排序……这样的话,我们X轴就排列好了~
>> [xsort,I] = sort(xlist);
>> xsort
xsort =
0 0.5000 1.0000 2.0000 2.5000 3.0000 4.0000 4.5000 5.0000 6.0000
>>
然后我们再把原始数据y和插值数据Y合并创建一个向量ylist,我们可以这样:
>> ylist = [y,Y];
>> ylist
ylist =
0 0.8415 0.9093 0.1411 -0.7568 -0.9589 -0.2794 0.4207 0.5252 -0.8579
>>
我们可以对X轴采用升序排列,但是我们不能对Y轴同样按照这种方式排列啊!这样的话,重新排列以后就是一条递增的数了……但是我们不要忘了一个数列I,它可以保存排序过的数字在原来向量的索引
,我们可以利用向量I来找到对应位置的数字在原向量中的位置,我们可以这样:
>> I
I =
1 8 2 3 9 4 5 10 6 7
>> ysort = ylist(I)
ysort =
0 0.4207 0.8415 0.9093 0.5252 0.1411 -0.7568 -0.8579 -0.9589 -0.2794
>>
于是,我们的X和Y就成功的排列完成啦~ 鼓掌!!我们看一下使用插值以后的效果,蓝线是插值以前的数据,圆圈是插值以后的数据。因为线性插值的方式是取该点左右最近的点,取左右中间的点,所以圆圈在线上面……
四、实践上手
根据所给的数据文件input.mat,以变量x为自变量,y为因变量,分别使用四种插值方式求出自变量为X时因变量的值Y,把图形窗口分割为四个区域,在每个区域分别画出四种不同插值方式时,插值前后的数据曲线。
我们先导入数据……假设我们把数据文件和matlab原文件放在一起,因为在一个文件夹里面,所以我们可以直接load
进数据……
load input.mat
然后,我们把插值Y
求出来
Y = interp1(x,y,X,'linear');
之后,将原始值和插值合并在一起……
xlist = [x,X];
ylist = [y,Y];
我们将X轴排序,将排序以后的值放入xsort
[xsort,I]=sort(xlist);
之后,将I用于Y的排序……
ysort = ylist(I);
到此,重点讲完了,我们就可以选择画图位置来画图了,我喜欢将排序前的数据打红虚线,排序后的数据变成蓝色的带有X
符号的线……
subplot(2,2,1)
plot(xsort,ysort,'-bx',x,y,'-.r')
title("使用linear模式绘图")
legend("使用后","使用前");
将上述内容总结在一起,我们就可以画出其中一种插值了……
load input.mat
%% 使用linear模式绘图
Y = interp1(x,y,X,'linear');
xlist = [x,X];
ylist = [y,Y];
[xsort,I]=sort(xlist);
ysort = ylist(I);
subplot(2,2,1)
plot(xsort,ysort,'-bx',x,y,'-.r')
title("使用linear模式绘图")
legend("使用后","使用前");
我们可以将插值到绘图的部分复制粘贴为四份,把interp1中间的变量'linear'
改一下。我们就可以用四种模式来绘图了。
load input.mat
%% 使用linear模式绘图
Y = interp1(x,y,X,'linear');
xlist = [x,X];
ylist = [y,Y];
[xsort,I]=sort(xlist);
ysort = ylist(I);
subplot(2,2,1)
plot(xsort,ysort,'-bx',x,y,'-.r')
title("使用linear模式绘图")
legend("使用后","使用前");
%% 使用next模式绘图
Y = interp1(x,y,X,'next');
xlist = [x,X];
ylist = [y,Y];
[xsort,I]=sort(xlist);
ysort = ylist(I);
subplot(2,2,2)
plot(xsort,ysort,'-bx',x,y,'-.r')
title("使用next模式绘图")
legend("使用后","使用前");
%% 使用spline模式绘图
Y = interp1(x,y,X,'spline');
xlist = [x,X];
ylist = [y,Y];
[xsort,I]=sort(xlist);
ysort = ylist(I);
subplot(2,2,3)
plot(xsort,ysort,'-bx',x,y,'-.r')
title("使用spline模式绘图")
legend("使用后","使用前");
%% 使用pchip模式绘图
Y = interp1(x,y,X,'pchip');
xlist = [x,X];
ylist = [y,Y];
[xsort,I]=sort(xlist);
ysort = ylist(I);
subplot(2,2,4)
plot(xsort,ysort,'-bx',x,y,'-.r')
title("使用pchip模式绘图")
legend("使用后","使用前");
结果如下: