在上关于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
>> 

在图上显示是这样的……

image-20221226200742037

如果我想知道当使用线性插值时,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分别查看BI的值……

>> [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升序排序以后的结果;我们再看II里面第一个数字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函数来将原数据和插值数据重新从小到大排序~

image-20221226200742037

我们先要将原数据和插值数据放在一个向量里面,这个简单,我们可以这样……

>> 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就成功的排列完成啦~ 鼓掌!!我们看一下使用插值以后的效果,蓝线是插值以前的数据,圆圈是插值以后的数据。因为线性插值的方式是取该点左右最近的点,取左右中间的点,所以圆圈在线上面……

image-20221226211121651

四、实践上手

根据所给的数据文件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("使用后","使用前");

结果如下:

image-20221226213613135