展歌 2021-11-16 20:01 采纳率: 100%
浏览 289
已结题

MATLAB 怎样绘制拟合出的Smoothing spline曲线的导数曲线??

对大量实验测得的数据点用Smoothing spline曲线拟合,然后怎样得出拟合后的曲线的导数曲线?

  • 写回答

1条回答 默认 最新

  • 技术专家团-Joel 2021-11-16 22:21
    关注

    一个简单的办法是直接用三点差分求导,我给你一个函数

    function [dydx,x,y] = threePiontDerivative(x,y)
    x = x(:); y = y(:);
    n = length(x); m = length(y);
    if(n~=m)
        error('x和y长度不一致')
    end
    if(n<3)
        error('x和y长度不够,长度至少要有3')
    end
    dx = diff(x);
    h = mean(dx);
    if(max(abs(h-dx))>1e-12)
        warning('x不是等间距的')
        if(~all(dx>0))
           [x,idx] = sort(x); 
           y = y(idx);
        end
        [x,ia] = unique(x);
        y = y(ia);
        dydx =  nonUniformPoint(x,y);
    else
        dydx = zeros(size(y));
        dydx(2:end-1) = (y(3:end)-y(1:end-2))/(2*h);%首端点
        dydx(1) = (-3*y(1)+4*y(2)-y(3))/(2*h);%中间点
        dydx(n) = (y(n-2)-4*y(n-1)+3*y(n))/(2*h);%末端点
    end
    end
    function dy =  nonUniformPoint(x,y)
    dy = zeros(size(y));
    n = length(y);
    dx = diff(x);
    h1 = dx(1:end-1);
    h2 = dx(2:end);
    h11 = h1.*h1;
    h22 = h2.*h2;
    h12 = h1.*h2;
    a = -h2./(h11+h12);
    b = (h2-h1)./h12;
    c = h1./(h22+h12);
    dy(2:n-1) = a.*y(1:n-2)+b.*y(2:n-1)+c.*y(3:n); 
    dy(1) = -(2*h1(1)+h2(1))/(h11(1)+h12(1))*y(1) +...
        (h1(1)+h2(1))/h12(1)*y(2) +...
        -h1(1)/(h22(1)+h12(1))*y(3);
    dy(n) = (h2(end)/(h11(end)+h12(end)))*y(n-2) +...
        -(h1(end)+h2(end))/h12(end)*y(n-1) +...
        (h1(end)+2*h2(end))/(h22(end)+h12(end))*y(n);
    end
    
    

    然后调用:

    x = 0:pi/3:2*pi;
    y = sin(x);
    xp = 0:pi/10:2*pi;
    yp = spline(x,y,xp);
    figure(1);clf;
    plot(x,y,'ro',xp,yp,'b-'); 
    dy = threePiontDerivative(xp,yp);
    hold on 
    plot(xp,dy,'m--')
    legend('原数据','Spline后','Spline求导')
    

    效果:

    img

    当然我还想到了一种更简单的办法!!!, 一并实现了

    x = 0:pi/3:2*pi;
    y = sin(x);
    xp = 0:pi/10:2*pi;
    pp = spline(x,y);
    yp = ppval(pp, xp); % 分段得到的样条插值值
    p = pp.coefs; % 获取分段系数
    q = zeros(size(p,1),size(p,2)-1);
    for i = 1:size(p,1)
        q(i,:) = polyder(p(i,:)); %直接对分段多项式系数求导
    end
    pp.coefs = q;  pp.order = 3; % 把pp更改为求导后的系数和阶数
    dy = ppval(pp, xp); % 直接用ppval获取样条插值后的导数
    figure(1);clf; % 画图
    plot(x,y,'ro',xp,yp,'b-');hold on;
    plot(xp,dy,'m--')
    legend('原数据','Spline后','Spline求导')
    

    效果:

    img

    堪称完美!

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录

报告相同问题?

问题事件

  • 系统已结题 11月30日
  • 已采纳回答 11月22日
  • 创建了问题 11月16日

悬赏问题

  • ¥15 运筹学排序问题中的在线排序
  • ¥15 关于docker部署flink集成hadoop的yarn,请教个问题 flink启动yarn-session.sh连不上hadoop,这个整了好几天一直不行,求帮忙看一下怎么解决
  • ¥30 求一段fortran代码用IVF编译运行的结果
  • ¥15 深度学习根据CNN网络模型,搭建BP模型并训练MNIST数据集
  • ¥15 lammps拉伸应力应变曲线分析
  • ¥15 C++ 头文件/宏冲突问题解决
  • ¥15 用comsol模拟大气湍流通过底部加热(温度不同)的腔体
  • ¥50 安卓adb backup备份子用户应用数据失败
  • ¥20 有人能用聚类分析帮我分析一下文本内容嘛
  • ¥15 请问Lammps做复合材料拉伸模拟,应力应变曲线问题