如何作出优美的曲线

0.引言

在一些理工科实验中,我们常需要根据实验数据作出相应的一些曲线,而我们在实验过程中难免会存在失误偏差,再加上很多人并不手巧,纸面上画曲线更是难上加难,因此用计算机作图便成了变成了一种较为科学便捷的方法,本文将分别用三种程序(python、matlab、R)介绍一些简单的曲线作图保姆级教程。

(笔者建议:如果读者对编程操作不感兴趣,可直接跳转至2.1进行阅读)

本文使用的数据如下:(氨基酸的酸碱滴定实验)

1.Python

1.1安装库

如果您python开发环境是pycharm,那么装库操作较为简单,详细操作见如下链接:

PyCharm安装教程和第三方库安装方法_pycharm安装第三方库_python机器学习建模的博客-CSDN博客

如果您python为其他开放环境,那么装库操作较为复杂,尤其是对于一些第一次装库的朋友很不友好,详细操作见如下链接:

Python安装库的常用方法_python库怎么安装_沉默的松花的博客-CSDN博客

当然也可以通过调用一些库pip,os来回避终端的操作,如果你是对终端操作不熟的初学者,也可以采用以下方法:

Python3,选择Python自动安装第三方库,从此跟pip说拜拜!!_Carl_奕然的博客-CSDN博客

本文需要用到的库:numpy(配合matplotlib存储数据),matplotlib(绘图),scipy(样条插样的计算)

1.2报错处理(pycharm)

使用pycharm的朋友在调用matplotlib可能会出现类似如下报错

在Settings中Tools的Python Scientific中取消show plots in tool window勾选,应用即可。

1.3方法选择

作平滑曲线的方法有很多种,常见有插值法和拟合法,两者区别是:

  • 插值法会要求曲线经过所有的数据点;拟合法只要求近似曲线尽可能接近数据点,保证曲线的平滑性和一致性。

  • 插值法适用于数据点较少且分布均匀的情况,而拟合法适用于数据点较多且分布不均匀的情况。

  • 插值法可以保证函数在数据点处的精确性,而拟合法可能会损失一些细节信息。

本实验的pH值是用pH试纸测得,数据点数据并不精确,实验目的也是为了探求氨基酸的酸碱滴定曲线的一个趋势,因此采用拟合法更加合适,但为了让大家更加直观地感受两种方法的区别,在这里将用python将两种方法皆以实现,在后续部分将不在赘述。

1.4插值法实现

第一步输入数据

x = np.linspace(1, 15, 15)#创建一个包含15个元素的数组,从1到15均匀分布
y = np.array([1,2,2,2,3,4,5,7,8,9,9,9,9,10,11])

第二步使用样条插值法对数据点进行拟合

tck = splrep(x, y)
xnew = np.linspace(1, 15, 200)#插入200个点使曲线更加平滑
ynew = splev(xnew, tck)

第三步绘制原始数据点和平滑曲线

plt.scatter(x, y, c='red', label='data point')#绘制数据点
plt.plot(xnew, ynew, linestyle='-', linewidth=2, label='smooth curve')#绘制曲线
plt.legend()#设置图例
plt.xlabel('serial number')#设置x轴标签
plt.ylabel('pH')#设置y轴标签
plt.title('Acid-Base titration curve of amino acids')#设置标题
plt.show()

完整代码如下:

import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import splrep, splev

x = np.linspace(1, 15, 15)#创建一个包含15个元素的数组,从1到15均匀分布
y = np.array([1,2,2,2,3,4,5,7,8,9,9,9,9,10,11])

tck = splrep(x, y)
xnew = np.linspace(1, 15, 200)#插入200个点使曲线更加平滑
ynew = splev(xnew, tck)

plt.scatter(x, y, c='red', label='data point')#绘制数据点
plt.plot(xnew, ynew, linestyle='-', linewidth=2, label='smooth curve')#绘制曲线
plt.legend()#设置图例
plt.xlabel('serial number')#设置x轴标签
plt.ylabel('pH')#设置y轴标签
plt.title('Acid-Base titration curve of amino acids')#设置标题
plt.show()

效果如下图:

图像稍有些突兀

1.5拟合法实现

拟合法有多种实现方法,如果通过理论分析得知了函数关系,或者图像有某些经典函数的数学特征(例如上述数据笔者认为可以分为多段Sigmoid函数曲线拟合),则可以使用scipy.optimize.curve_fit()函数进行曲线拟合,得到最优参数值,这种方法可以有效减轻一些数据点存在偏差带来的影响。

当然如果不知道该曲线对应的具体函数形式也不要紧,可以直接使用多项式拟合使用numpy.polyfit()函数,它可以对给定的数据集进行多项式回归,通过调整多项式的阶数,我们可以得到较为满意的图像,本文以第二种方法为例。

coeffs = np.polyfit(x, y, 8)#将多项式系数设置为8
poly = np.poly1d(coeffs)#根据系数创建一个多项式函数

完整代码如下:

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(1, 15, 15)#创建一个包含15个元素的数组,从1到15均匀分布
y = np.array([1,2,2,2,3,4,5,7,8,9,9,9,9,10,11])

coeffs = np.polyfit(x, y, 8)#将多项式系数设置为8
poly = np.poly1d(coeffs)#根据系数创建一个多项式函数

plt.scatter(x, y, c='red', label='data point')#绘制数据点
plt.plot(x, poly(x), linestyle='-', linewidth=2, label='smooth curve')#绘制曲线
plt.legend()#设置图例
plt.xlabel('serial number')#设置x轴标签
plt.ylabel('pH')#设置y轴标签
plt.title('Acid-Base titration curve of amino acids')#设置标题
plt.show()

效果如下图

相较于插值法更加圆润

2.Matlab

笔者这里使用的matlab版本为2022b

2.1使用曲线拟合器(Curve Fitting Toolbox)

第一步在环境中输入数据集,运行

x=[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];
y=[1,2,2,2,3,4,5,7,8,9,9,9,9,10,11];

当我们看到工作区有如下显示时即可进行曲线拟合操作了

第二步在App中打开曲线拟合器

点击选择数据

将X数据选择为我们创建的表格x,Y数据选择为我们创建的表格y

第三步在拟合类型中选择合适的方法,如果不太熟悉这些方法,可以逐个去尝试。

第四步在右侧拟合选项调整参数直到自己满意为止(注:参数并不是越大越好,过大会出现过拟合现象,一些情况下如果数据量不够可能会报错)

还可以在右上角选择残差图来查看拟合效果

效果如下:

多项式拟合

傅里叶拟合

2.2细微调整

上述方法虽然简单快捷,但为了做出较为完美的图形,我们往往还是需要用代码进行细微调整,甚至可以把图形做得更美观。

在导出界面选择生成代码,我们则可以在源码上直接进行微调,同时我们也不要忘记在代码中加入参数的输入。

笔者自己对生成的代码进行了微调,完整代码如下,给各位提供一个参考:

function [fitresult, gof] = createFit(x, y)

x = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];
y = [1,2,2,2,3,4,5,7,8,9,9,9,9,10,11];
[xData, yData] = prepareCurveData(x, y);%将数据转化为适合拟合的形式


ft = fittype('fourier4');%定义拟合类型为四阶傅里叶级数模型
opts = fitoptions('Method', 'NonlinearLeastSquares');%设置拟合选项
opts.Display = 'Off';%设置拟合选项
opts.StartPoint = [0 0 0 0 0 0 0 0 0 0.149599650170943];%设置拟合选项


[fitresult, gof] = fit(xData, yData, ft, opts);%进行拟合,fitresult为拟合结果,gof为优度
figure('Name', 'Fitting curve');%设置图形
scatter(x,y,25,"black",'filled');% 绘制散点
hold on


h = plot(fitresult);% 绘制拟合曲线和图例
set(h, 'Color', 'b', 'LineStyle', '-','LineWidth',1); % 设置拟合曲线颜色和线型
axis([1 15 0 12]); % 设置坐标轴在指定的区间
legend('Data', 'Fitting curve', 'Location', 'northwest');% 添加图例
title('Acid-Base titration curve of amino acids');% 添加标题
xlabel('serial number');% 添加坐标轴标签
ylabel('pH');% 添加坐标轴标签
grid on

最后效果图如下

3.R

3.1安装包

相较于python安装库,R语言安装包更为便捷只要运行如下程序:

install.packages("ggplot2")
install.packages("ggalt")

对于初学者而言有一个很常见的错误,就是要注意,在使用install.packages()函数时包名要加双引号,而使用library()函数时,加载包不需要加双引号。本文使用的ggplot2和ggalt包都是用于R中的高级绘图操作。

3.2代码实现

#输入数据
x <- c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 ,15)
y <- c(1, 2, 2, 2, 3, 4, 5, 7, 8, 9, 9, 9, 9, 10, 11)

#绘图
library(ggplot2)
library(ggalt)
ggplot(data.frame(x = x,y = y), aes(x = x,y = y)) +#创建映射关系
  geom_point(size = 2.5,aes(color = "datapoint")) +#显示数据点并添加图例
  geom_xspline(spline_shape = 1,aes(color = "Fitting curve"))+#绘制曲线并添加图例
  theme_bw() + #设置白色背景
  labs(title = "Acid-base titration curve of amino acids", x = "serial number", y = "pH") + # 设置标题和标签
  scale_x_continuous(breaks=seq(1,15,by=3)) + # 设置x轴刻度范围和间隔
  scale_y_continuous(limits=c(1,11)) + # 设置y轴刻度范围
  scale_color_manual(values=c("red","blue"),labels=c("datapoint","Fitting curve"))+ # 设置图例的颜色和名称
  theme(axis.title.x=element_text(size=16), axis.title.y=element_text(size=16))#改变x轴y轴字体大小#改变x轴y轴字体大小

这里要注意一下geom_xspline()函数,当spline_shape>0时曲线趋于拟合数据点;当spline_shape=0 时,曲线直接连接数据点;当 spline_shape<0 时,样条曲线趋于平滑数据点(类似1.4插值法),同样spline_shape值不能设的过大,否则会出现过拟合现象。

效果如下图

4.三种软件对比分析

拟合采取方法的效果比较:R>matlab>python

图形的美观方面比较:matlab>R>python

实现难度比较(由易到难):matlab(曲线拟合器)>R>matlab(代码)=python

软件的拓展范围比较:python>matlab>R

(个人观点,可能会存在笔者对某些软件操作还不熟悉以及方法不正确从而没有真正地发挥软件作用的情况,还请多多包容)

以上仅为笔者作为初学者的一些不成熟看法,也是笔者第一次写博客,如有不当之处,还请各位多多指教!

  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值