日期:2019/8/8
假設某人儲存資料時不是用csv檔,而是使用數量不一致的空格分格資料,我們將前一篇文章〈最接近直線〉的數據排列成底下這樣再儲存為文字檔data.txt。
index x errx y erry
0 1.0 0.1 4.9 0.5
1 2.0 0.1 6.9 0.5
2 3.0 0.1 9.0 0.5
3 4.0 0.1 11.1 0.6
4 5.0 0.1 13.2 0.6
5 6.0 0.2 15.2 0.8
6 7.0 0.2 16.9 0.8
7 8.0 0.2 18.9 0.8
8 9.0 0.2 20.9 0.8
9 10.0 0.2 22.8 0.8
我絕對不會用這樣的格式儲存資料,但如果真的遇到這種狀況還是有辦法解決,只要使用numpy.genfromtxt即可,語法為
np.genfromtxt([資料檔名稱], dtype=[資料格式], unpack=[True 或 False],
skip_header=[列數], usecols=[欄位索引值])
其中資料格式預設值為float、unpack預設值為False、skip_header預設值為0、usecols預設值為None,詳細的用法請參考官方說明書。
為了方便比較讀取資料的效果,我們使用前一篇文章〈最接近直線〉的數據及程式碼,但是將讀取資料的方法從numpy.loadtxt改成numpy.genfromtxt,程式碼如下
import numpy as np
from scipy.optimize import curve_fit
import matplotlib.pyplot as plt
# 從 data.csv 讀取資料
x, errx, y, erry = np.genfromtxt('data.txt', dtype=float, unpack=True, skip_header=1, usecols=(1, 2, 3, 4))
# 計算最接近直線的斜率、截距及不準量
popt, pcov = curve_fit(lambda x, a, b: a*x+b, x, y, sigma=erry, absolute_sigma=True)
print("slope: %.12f +/- %.12f" % (popt[0], np.sqrt(pcov[0, 0])))
print("intercept: %.12f +/- %.12f" % (popt[1], np.sqrt(pcov[1, 1])))
# 計算最接近直線的R平方值
cor = np.corrcoef(x, y)[0, 1]
print("r-squared: %.12f" % cor**2)
# 建立繪圖物件
plt.figure(figsize=(6, 4.5), dpi=72)
plt.xlabel('x', fontsize=14)
plt.ylabel('y', fontsize=14)
plt.grid(color='grey', linestyle='--', linewidth=1)
plt.plot(x, y, color='blue', marker='o', markersize=10, linestyle='')
# 加上 error bar
plt.errorbar(x, y, xerr=errx, yerr=erry, color='black', fmt='o', capsize=4, markersize=0, linewidth=1)
# 加上最接近直線
line = popt[0]*x + popt[1]
plt.plot(x, line, color='red', marker='', linestyle='-', linewidth=2)
# 儲存、顯示圖片
plt.savefig('genfromtxt.svg')
plt.savefig('genfromtxt.png')
plt.show()
其實只改了第6行
x, errx, y, erry = np.genfromtxt('data.txt', dtype=float, unpack=True, skip_header=1, usecols=(1, 2, 3, 4))
從文字檔data.txt中讀取資料,資料格式為float,將資料依照欄位拆開,忽略第1行的文字,將第1、2、3、4欄的資料分別存入陣列x、errx、y、erry。
2021/7/15 補充
第6行也可以改成以下的寫法,效果一樣。
data = np.genfromtxt('data.txt', names=True)
x, errx, y, erry = data['x'], data['errx'], data['y'], data['erry']
線性擬合計算結果以及最後繪製的XY散佈圖與前一篇文章一模一樣,應該成功地解決了一個奇怪的要求。
$$ a = 1.997966995944 \pm 0.071531035658 $$
$$ b = 2.991771672485 \pm 0.371842522314 $$
$$ R^2 = 0.999497575579 $$
用 matplotlib 繪製的XY散佈圖
HackMD 版本連結:https://hackmd.io/@yizhewang/HyFxPWKXB
沒有留言:
張貼留言