欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Python 做曲线拟合和求积分的方法

程序员文章站 2022-03-24 13:03:19
这是一个由加油站油罐传感器测量的油罐高度数据和出油体积,根据体积和高度的倒数,用截面积来描述油罐形状,求出拟合曲线,再用标准数据,求积分来验证拟合曲线效果和误差的一个小项目...

这是一个由加油站油罐传感器测量的油罐高度数据和出油体积,根据体积和高度的倒数,用截面积来描述油罐形状,求出拟合曲线,再用标准数据,求积分来验证拟合曲线效果和误差的一个小项目。 主要的就是首先要安装anaconda  python库,然后来运用这些数学工具。

###最小二乘法试验###
import numpy as np
import pymysql
from scipy.optimize import leastsq
from scipy import integrate
###绘图,看拟合效果###
import matplotlib.pyplot as plt
from sympy import *
 
 
path='e:\pythonprogram\oildata.txt'
 
lieh0 =[]   #初始第一列,油管高度
liev1 =[]   #初始第二列,油枪记录的体积
 
h_median =[]  # 高度相邻中位数
h_subtract =[]   #相邻高度作差
v_subtract =[]   #相邻体积作差
select_h_subtr =[]   #筛选的高度作差 ########
select_v_subtr =[]   #筛选的体积作差
 
vdth=[]      #筛选的v 和 t 的 倒数。
 
def loaddata(spath,lie0,lie1):
 with open(spath,'r') as f0:
   for i in f0:
    tmp=i.split()
    lie0.append(float(tmp[0]))
    lie1.append(float(tmp[2]))
 print ("source lie0",len(lie0))
 
 
def connectmysql():
 db = pymysql.connect(host='10.**.**.**', user='root', passwd='***', db="zabbix", charset="utf8") # 校罐
 cur = db.cursor()
 
 try:
  # 查询
  cur.execute("select * from station_snapshot limit 10 ")
  for row in cur.fetchall():
   # print(row)
   id = row[0]
   snapshot_id = row[1]
   datetime = row[13]
   attr1v = row[5]
   attr2h = row[6]
   print("id=%d ,snapshot_id=%s,datetime=%s,attr1v =%s, attr2h=%s ",
     (id, snapshot_id, datetime, attr1v, attr2h))
 except:
  print("error: unable to fecth data of station_stock")
 
 try:
  cur.execute("select * from can_stock limit 5");
  for row in cur.fetchall():
   # print(row)
   stockid = row[0]
   stationid = row[1]
   datetime = row[4]
   volume = row[5]
   height = row[8]
   print("stockid=%d ,stationid=%s,datetime=%s,volume =%f, height=%f ",
     (stockid, stationid, datetime, volume, height))
 except:
  print("error: unable to fecth data of can_snapshot")
 
 cur.close()
 db.close()
 
 
def formatdata(h_med,h_subtr,v_subtr):
 lh0 = lieh0[:]
 del lh0[0]
 print("lh0 size(): ",len(lh0))
 
 lh1 =lieh0[:]
 del lh1[len(lh1)-1]
 
 print("lh1 size() : ",len(lh1))
 
 lv0 =liev1[:]
 del lv0[0]
 #print (liev1)
 print ("souce liev1 size() : ",len(liev1))
 print ("lv1 size() :",len(lv0))
 """
 lv1 =liev1[:]
 del lv1[len(lv1)-1]
 print("lv1 size(): ",len(lv1))
 """
 h_med[:] =[(x+y)/2 for x,y in zip(lh0,lh1)]  ###采样点(xi,yi)###
 print("h_med size() : ", len(h_med))
 
 h_subtr[:] = [(y-x) for x,y in zip(lh0,lh1)]
 print("h_subtr size() : ", len(h_subtr))
 # v_subtr[:] = [(y-x) for x,y in zip(lv0,lv1)]
 v_subtr[:] = lv0
 print("v_subtr size() : ", len(v_subtr))
 
 
def removebadpoint(h_med,h_sub,v_sub):
 for val in h_sub:
  position=h_sub.index(val)
  if 0.01 > val > -0.01:
   del h_sub[position]
   del h_med[position]
   del v_sub[position]
 v_dt_h_ay = [(y/x) for x, y in zip(h_sub, v_sub)]
 return v_dt_h_ay
 
 
 
def selectrightpoint(h_med,h_subtr,v_dt_h_ay):
 for val in v_dt_h_ay:
  pos = v_dt_h_ay.index(val)
  if val > 20 :
   del v_dt_h_ay[pos]
   del h_med[pos]
   del h_subtr[pos]
 for val in v_dt_h_ay:
  ptr = v_dt_h_ay.index(val)
  if val < 14:
   del v_dt_h_ay[ptr]
   del h_med[ptr]
   del h_subtr[ptr]
 
 
def writefile(h_mp, v_dt_h):
 s='\n'.join(str(num)[1:-1] for num in h_mp)
 v='\n'.join(str(vdt)[1:-1] for vdt in v_dt_h)
 open(r'h_2.txt','w').write(s)
 open(r'v_dt_h.txt','w').write(v)
 print("write h_median: ",len(h_mp))
 # print("v_dt also is (y-x) : ",v_dt_h,end="\n")
 print("write v_dt_h : ",len(v_dt_h))
# file=open('data.txt','w')
# file.write(str(h_mp));
# file.close
 
 
def integralcalculate(coeff,xspace):
 vcalcute =[]
 x = symbol('x')
 a, b, c, d = coeff[0]
 y = a * x ** 3 + b * x ** 2 + c * x + d
 i=0
 while (i< len(xspace)-1) :
  m = integrate(y, (x, xspace[i], xspace[i+1]))
  vcalcute.append(abs(m))
  i=i+1
 
 print("求导结果:",vcalcute)
 print("求导长度 len(vcalcute): ",len(vcalcute))
 return vcalcute
 
 ###需要拟合的函数func及误差error###
 
def func(p,x):
 a,b,c,d=p
 return a*x**3+b*x**2+c*x+d #指明待拟合的函数的形状,设定的拟合函数。
 
def error(p,x,y):
 return func(p,x)-y #x、y都是列表,故返回值也是个列表
 
def leastsquarefitting(h_mp,v_dt_hl):
 p0=[1,2,6,10]  #a,b,c 的假设初始值,随着迭代会越来越小
 #print(error(p0,h_mp,v_dt_h,"cishu")) #目标是让error 不断减小
 #s="test the number of iteration" #试验最小二乘法函数leastsq得调用几次error函数才能找到使得均方误差之和最小的a~c
 para=leastsq(error,p0,args=(h_mp,v_dt_hl)) #把error函数中除了p以外的参数打包到args中
 a,b,c,d=para[0]   #leastsq 返回的第一个值是a,b,c 的求解结果,leastsq返回类型相当于c++ 中的tuple
 print(" a=",a," b=",b," c=",c," d=",d)
 plt.figure(figsize=(8,6))
 plt.scatter(h_mp,v_dt_hl,color="red",label="sample point",linewidth=3) #画样本点
 x=np.linspace(200,2200,1000)
 y=a*x**3+b*x**2+c*x+d
 
 integralcalculate(para,h_subtract)
 plt.plot(x,y,color="orange",label="fitting curve",linewidth=2) #画拟合曲线
 # plt.plot(h_mp, v_dt_hl,color="blue", label='origin line',linewidth=1) #画连接线
 plt.legend()
 plt.show()
 
def freeparameterfitting(h_mp,v_dt_hl):
 z1 = np.polyfit(h_mp, v_dt_hl, 6) # 第一个拟合,*度为6
  # 生成多项式对象
 p1 = np.poly1d(z1)
 print("z1:")
 print(z1)
 print("p1:")
 print(p1)
 print("\n")
 x = np.linspace(400, 1700, 1000)
 plt.plot(h_mp, v_dt_hl, color="blue", label='origin line', linewidth=1) # 画连接线
 plt.plot(x, p1(x), 'gv--', color="black", label='poly fitting line(deg=6)', linewidth=1)
 plt.legend()
 plt.show()
 
def main():
 loaddata(path, lieh0, liev1)
 connectmysql() # 读取oildata数据库
 
 formatdata(h_median, h_subtract, v_subtract)
 
 # 去除被除数为0对应的点,并得到v 和 h 求导 值的列表
 vdth[:] = removebadpoint(h_median, h_subtract, v_subtract)
 print("h_median1:", len(h_median))
 
 print("vdth1 : ", len(vdth))
 
 # 赛选数据,去除异常点
 selectrightpoint(h_median, h_subtract, vdth)
 print("h_median2:", len(h_median))
 print("h_subtract: ", len(h_subtract))
 print("vdth2 : ", len(vdth))
 h_mp = np.array(h_median)
 v_dt_h = np.array(vdth)
 
 writefile(h_mp, v_dt_h)
 # 最小二乘法作图
 leastsquarefitting(h_mp, v_dt_h)
 # 多项式*参数法作图
 freeparameterfitting(h_mp, v_dt_h)
 
if __name__ == '__main__':
 main()
 

以上这篇python 做曲线拟合和求积分的方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持。