前言
工作上遇到一个数据处理的问题:供应商提供了一个器件的S参数,其中S11和S21提供的测试频点不一样,需要将S11的曲线拟合出来,再用S21的频率求到对应的值。
一开始想着最愚蠢的办法,认为两点间是完全线性,把现有S11所有频率相邻两点间做线性拟合,然后再用S21的频率点去一段段的找,找到在哪段频率范围内,就用线性拟合出来的公式算这个点的值。这个方法显然是很不科学的。并且就算用Excel来弄,也是需要花一点功夫的。
想着无所不能的Python对这类数据分析处理不是很擅长嘛,一定有相关的模块可以直接搞定的。于是乎网上找了一通后,发现了这个scipy模块函数做曲线插值拟合。
正文
直接上代码吧:
一,首先是需要用到的模块部分
import pandas as pd
import matplotlib.pyplot as plt
from scipy import interpolate
import numpy as np
import xlwt
用pandas读取和写入Excel;用pyplot来画图;核心是scipy里的interpolate 来做插值拟合。
二,读取Excel里面的S11数据
io = r'S11.xlsx'
# 打开最新的xlsx文件,需要使用‘openpyxl’;加入keep_default_na=False 这样空值后面好处理
df = pd.read_excel(io, sheet_name=0, engine='openpyxl', keep_default_na=False)
S21freqData = df['Hz']
S11freqData = df['S11_Hz']
S11Data = df['S11']
‘Hz’列是S21的频率点,也就是我们需要用这些频率点去找到对应的S11参数;‘S11_Hz’列是S11原本测试频率点;'S11'列则是S11原本频率点的值。
我们需要通过S11freqData和S11Data将S11曲线完全拟合出来,再代入S21freqData的频率点,求得这些频率点对应的S11参数。
三,插值拟合
插值拟合这个说法不知道对不对,没有去细究,反正要实现上面说的目的就需要用到scipy里的interpolate模块。
因为拟合曲线用到的函数splrep只能处理list,pandas读取的数据是dataframe的格式,因此需要处理成list格式。
# interpolate.splrep 只能处理list,dataframe格式会报错,所以下面需要将dataframe导入到list里
newX = []
x = []
y = []
for data in S21freqData:
if data == '':
break
newX.append(data)
for data in S11freqData:
if data == '':
break
x.append(data)
for data in S11Data:
if data == '':
break
y.append(data)
然后使用interpolate.splrep函数,简单的一行代码,完成拟合。
# 拟合曲线
tck = interpolate.splrep(x, y)
再用interpolate.splev函数,得到S21频率点在拟合出来的S11上的值
# 用新的x轴值求得拟合曲线的y值
newY = interpolate.splev(newX, tck)
四,存储数据
用pandas将求得的值重新保存在Excel里面
df_newY = pd.DataFrame({
'S11vsS21Freq': newY
})
with pd.ExcelWriter('newS11.xls') as writer:
df_newY.to_excel(writer, sheet_name='newS11')
五,画图
直接上代码:
plt.scatter(x, y, 25, 'red')
plt.plot(newX, newY)
plt.show()
最终图片结果如下所示:
红点是原本的S11的数据值,蓝线则是拟合出来的曲线。可以看到,两者几乎是重叠的。
后记:
这个案例的代码本身是很简单的,这里只是做一个记录以备后续查看。
主要想说几点感悟:
1,Python真是无所不能,只要你想得到,Python就能做得到;
2,工作和学习相结合,一定是最高效的,工作高效了,学习也高效了。后续一定会持续通过学习Python来解决工作上的很多问题;
3,搜索能力也是非常的重要。这个案例中,由于数学基础薄弱,其实我自己都说不清楚到底是要实现一个什么样的数学处理。但还好给出的关键字还算靠谱,让我在百度上在无穷无尽的Python函数库里面找到了我想要的函数。其实整个完成的过程,耗时最长的就是找出这个函数库=_=!