。根據此思路,用我們駕輕就熟的線性擬合方法進行操作: # 線性擬合求mc x_c = x[-8:] # t y_c = y[-8:] # m x_cc = 1000/x_c P_linear, R2 = linear(x_cc, y_c) xx_c = np.linspace(np.min(x_cc), np.max(x_cc), 50) yy_c = np.polyval(P_linear, xx_c) mc = P_linear[1] #最大沉降質量,g print(f'mc:{mc}') # 線性擬合圖作圖 # 作圖 plt.figure(1) plt.rcParams['font.family'] = 'SimHei' plt.rcParams['font.size'] = 16 # 調整matplotlib內部設置使之支持中文,這種方法改變全局設置 plt.plot(xx_c, yy_c, 'r-.', label='擬合曲線', linewidth=4) plt.plot(x_cc, y_c, 'bo', label='實驗數據點', markersize=10) plt.xlabel(u'$1000/t (s^{-1})$', fontsize=24) plt.ylabel(u'沉降重量 $m/g$', fontsize=24) plt.title('線性擬合外推法求取沉降總量曲線圖', fontsize=28) plt.grid() plt.legend() # 擬合線描述圖例 txt_point = (np.mean(xx_c[xx_c >= np.mean(xx_c)]), np.mean(yy_c)) # 相對點法 msg = '擬合方程: y={:.4g}x+{:.4g}\n R2 = {:.4f}'.format( P_linear[0], P_linear[1], R2) plt.annotate(msg, xy=txt_point, xytext=txt_point)即可以通過線性擬合的方法求得 ,並且給出一張線性擬合曲線圖,用於實驗報告書寫和線性擬合結果可信度檢驗
由於之前的Arial Unicode MS在書寫"沉"字的時候看起來很醜,因此將字體換成黑體SimHei
線性擬合曲線圖接下來是重頭戲,基於已知曲線進行曲線擬合
# 曲線擬合函數定義 def func(t,a,b,c): global mc return mc * (1-np.exp(-a * t**(b + c*np.log(t)))) # curve_fit環節 popt,pcov = curve_fit(func,x,y) a,b,c = popt[0],popt[1],popt[2] yy = func(x,a,b,c) print(a,b,c) # 作圖 plt.figure(2) plt.rcParams['font.family'] = 'SimHei' plt.rcParams['font.size'] = 16 # 調整matplotlib內部設置使之支持中文,這種方法改變全局設置 plt.plot(x, yy, 'r-', label='擬合曲線', linewidth=2.2) plt.plot(x, y, 'bo', label='實驗數據點', markersize=5) plt.xlabel('時間 $t/s$', fontsize=24) plt.ylabel('沉降重量 $m/g$', fontsize=24) plt.title('多級分散體系沉降曲線圖', fontsize=28) # 擬合線描述圖例 txt_point = (np.mean(x), np.mean(yy)) # 相對點法 msg = '擬合方程:\n $m_t = mc * [1-exp(- (a) * t ^{(b + c \ln (t)) } ) ]$' msg = msg.replace('mc', f'{mc:.4g}') msg = msg.replace('a', f'{a:.4g}') msg = msg.replace('b', f'{b:.4g}') msg = msg.replace('c', f'{c:.4g}') plt.annotate(msg, xy=txt_point, xytext=txt_point) plt.grid() plt.legend()得到曲線擬合結果和沉降曲線圖:
沉降曲線圖2.2.2 基於擬合結果的進一步數據處理在使用scipy.optimize.curve_fit的時候,將函數單獨使用def定義出來用,這樣看起來代碼多了,實際上是將函數定義和函數使用分離,算是一種模塊化的思想。接下來我們也打算用這種思路進行數據處理:
# 導函數 # 導函數形式是固定的 直接內置 def dfunc(t,a,b,c): global mc return a*mc*t**(b + c*np.log(t))*( (b + 2*c*np.log(t))/t)*np.exp(-a*t**(b + c*np.log(t))) # 由半徑求取對應的完全沉降時間的函數 def func_tr(r, eta=eta, rho=rho, rho_0=rho_0, h=h, g=g): t = (9*eta*h)/(2*g*(rho-rho_0)*r**2) return t # 利用切線斜率求截距 def func_St(t, mt, dmdt): S = mt - t*dmdt return S # 數據處理求分布函數折線圖 r = np.arange(1,14) # um dr = 1 # um t_r = func_tr(r*1E-6) m_tr = func(t_r,a,b,c) dmdt_r = dfunc(t_r,a,b,c) S_r = func_St(t_r, m_tr, dmdt_r) dS_r = [] for i in range(1,len(S_r)): dS_r.append(S_r[i-dr]-S_r[i]) dS_r = np.array(dS_r) f_Sr = dS_r / (mc * dr * 1E-6)可以得到一系列的輸出數據,這些輸出數據可以在spyder裡面直接可視化,我在代碼末尾設計了一段輸出,用來輸出這些數據處理的所得結果。這裡的數據處理過程可以參照沉降物化的實驗講義
# 出數據 result_data = pd.DataFrame( [r,t_r,m_tr,dmdt_r,S_r,dS_r,f_Sr], index=['r','t','m_t','dm/dt','S','∆S','f']) result_data.to_csv('result_cjwh.csv') # 出圖 plt.show() 2.2.3 粒度分布圖輸出# 作圖 plt.figure(3) plt.rcParams['font.family'] = 'SimHei' plt.rcParams['font.size'] = 16 # 調整matplotlib內部設置使之支持中文,這種方法改變全局設置 plt.bar(r[1:], f_Sr, width=1,edgecolor='red', color='white',linewidth=4) plt.xlabel('半徑 $r / um$', fontsize=24) plt.ylabel('分布函數 f', fontsize=24) plt.title('多級沉降體系粒度分布圖', fontsize=28)基本的柱形圖做法即可,關於plt.bar可以在CSDN上進一步了解
粒度分布圖3. 全部原始碼# JamesBourbon in 20201116 # 沉降物化實驗的數據處理 # 曲線擬合scipy.optimize.curve_fit初應用 import numpy as np import matplotlib.pyplot as plt import pandas as pd import statsmodels.api as sm from statistic_model import linear # 引入線性擬合 from scipy.optimize import curve_fit # 數據導入 data = pd.read_csv('10183791.csv') y = np.array(data['m']) x = np.array(data['t']) # 實驗參數 eta = 0.0009111 # 黏度,Pa·S rho = 2700 # 滑石粉密度,kg/m3 rho_0 = 997.2995 # 介質密度,kg/m3 h = 0.13 # 沉降高度,m g = 9.81 # 線性擬合求mc x_c = x[-8:] # t y_c = y[-8:] # m x_cc = 1000/x_c P_linear, R2 = linear(x_cc, y_c) xx_c = np.linspace(np.min(x_cc), np.max(x_cc), 50) yy_c = np.polyval(P_linear, xx_c) mc = P_linear[1] #最大沉降質量,g print(f'mc:{mc}') # 線性擬合圖作圖 # 作圖 plt.figure(1) plt.rcParams['font.family'] = 'SimHei' plt.rcParams['font.size'] = 16 # 調整matplotlib內部設置使之支持中文,這種方法改變全局設置 plt.plot(xx_c, yy_c, 'r-.', label='擬合曲線', linewidth=4) plt.plot(x_cc, y_c, 'bo', label='實驗數據點', markersize=10) plt.xlabel(u'$1000/t (s^{-1})$', fontsize=24) plt.ylabel(u'沉降重量 $m/g$', fontsize=24) plt.title('線性擬合外推法求取沉降總量曲線圖', fontsize=28) plt.grid() plt.legend() # 擬合線描述圖例 txt_point = (np.mean(xx_c[xx_c >= np.mean(xx_c)]), np.mean(yy_c)) # 相對點法 msg = '擬合方程: y={:.4g}x+{:.4g}\n R2 = {:.4f}'.format( P_linear[0], P_linear[1], R2) plt.annotate(msg, xy=txt_point, xytext=txt_point) # 曲線擬合函數定義 def func(t,a,b,c): global mc return mc * (1-np.exp(-a * t**(b + c*np.log(t)))) # curve_fit環節 popt,pcov = curve_fit(func,x,y) a,b,c = popt[0],popt[1],popt[2] yy = func(x,a,b,c) print(a,b,c) # 作圖 plt.figure(2) plt.rcParams['font.family'] = 'SimHei' plt.rcParams['font.size'] = 16 # 調整matplotlib內部設置使之支持中文,這種方法改變全局設置 plt.plot(x, yy, 'r-', label='擬合曲線', linewidth=2.2) plt.plot(x, y, 'bo', label='實驗數據點', markersize=5) plt.xlabel('時間 $t/s$', fontsize=24) plt.ylabel('沉降重量 $m/g$', fontsize=24) plt.title('多級分散體系沉降曲線圖', fontsize=28) # 擬合線描述圖例 txt_point = (np.mean(x), np.mean(yy)) # 相對點法 msg = '擬合方程:\n $m_t = mc * [1-exp(- (a) * t ^{(b + c \ln (t)) } ) ]$' msg = msg.replace('mc', f'{mc:.4g}') msg = msg.replace('a', f'{a:.4g}') msg = msg.replace('b', f'{b:.4g}') msg = msg.replace('c', f'{c:.4g}') plt.annotate(msg, xy=txt_point, xytext=txt_point) plt.grid() plt.legend() # 導函數 # 導函數形式是固定的 直接內置 def dfunc(t,a,b,c): global mc return a*mc*t**(b + c*np.log(t))*( (b + 2*c*np.log(t))/t)*np.exp(-a*t**(b + c*np.log(t))) # 由半徑求取對應的完全沉降時間的函數 def func_tr(r, eta=eta, rho=rho, rho_0=rho_0, h=h, g=g): t = (9*eta*h)/(2*g*(rho-rho_0)*r**2) return t # 利用切線斜率求截距 def func_St(t, mt, dmdt): S = mt - t*dmdt return S # 數據處理求分布函數折線圖 r = np.arange(1,14) # um dr = 1 # um t_r = func_tr(r*1E-6) m_tr = func(t_r,a,b,c) dmdt_r = dfunc(t_r,a,b,c) S_r = func_St(t_r, m_tr, dmdt_r) dS_r = [] for i in range(1,len(S_r)): dS_r.append(S_r[i-dr]-S_r[i]) dS_r = np.array(dS_r) f_Sr = dS_r / (mc * dr * 1E-6) # 作圖 plt.figure(3) plt.rcParams['font.family'] = 'SimHei' plt.rcParams['font.size'] = 16 # 調整matplotlib內部設置使之支持中文,這種方法改變全局設置 plt.bar(r[1:], f_Sr, width=1,edgecolor='red', color='white',linewidth=4) plt.xlabel('半徑 $r / um$', fontsize=24) plt.ylabel('分布函數 f', fontsize=24) plt.title('多級沉降體系粒度分布圖', fontsize=28) # 出數據 result_data = pd.DataFrame( [r,t_r,m_tr,dmdt_r,S_r,dS_r,f_Sr], index=['r','t','m_t','dm/dt','S','∆S','f']) result_data.to_csv('result_cjwh.csv') # 出圖 plt.show() 4. 總結這個實驗的實驗結果數據文件少則幾十行,多的可以上千行,但都可以囊括在這套代碼裡面,出圖的時候調一下樣品點和曲線的大小就行。這套代碼幾乎把實驗級別的數據分析可視化做到極致了,再往上就要大數據和資料庫人工智慧級別了。
在這邊講解的時候沒有涉及到具體的各個庫各個方法各各個函數的使用細節,只是說了需要解決的問題和解決問題的方法,如果大家有這方面的需求歡迎後臺留言,考慮一下2333
事情好多,昨天才忙完成思危名譽校長獎學金答辯和創新實驗大賽論文,今天又要寫實驗報告忙論文改代碼跑計算,總歸事情是做不完的,還在更公眾號真的是熱情了,B站和雲峰聯的事情都只能寒假再說的樣子😂
不過我會繼續努力的吧
希望真的能如自己在成獎答辯的時候說的一樣,這一年能做到
鯤鵬展翅,直上九天。
歡迎點讚收藏在看三連呀,多多指教~