# 使用 numpy.genfromtxt 從文字檔中讀取資料 > 作者:王一哲 > 日期:2019/8/8 <br /> 假設某人儲存資料時不是用csv檔,而是使用數量不一致的空格分格資料,我們將前一篇文章〈[最接近直線](https://hackmd.io/@yizhewang/Sy6OHP2GS)〉的數據排列成底下這樣再儲存為文字檔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**即可,語法為 ```python np.genfromtxt([資料檔名稱], dtype=[資料格式], unpack=[True 或 False], skip_header=[列數], usecols=[欄位索引值]) ``` 其中資料格式預設值為float、unpack預設值為False、skip_header預設值為0、usecols預設值為None,詳細的用法請參考[官方說明書](https://docs.scipy.org/doc/numpy/reference/generated/numpy.genfromtxt.html)。 <br /> 為了方便比較讀取資料的效果,我們使用前一篇文章〈[最接近直線](https://hackmd.io/@yizhewang/Sy6OHP2GS)〉的數據及程式碼,但是將讀取資料的方法從**numpy.loadtxt**改成**numpy.genfromtxt**,程式碼如下 ```python= 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() ``` <br /> 其實只改了第6行 ```python 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行也可以改成以下的寫法,效果一樣。 ```python 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 $$ <img height="60%" width="60%" src="https://imgur.com/GFKi0qz.png" style="display: block; margin-left: auto; margin-right: auto;"/> <div style="text-align:center">用 matplotlib 繪製的XY散佈圖</div><br /> --- ###### tags:`Python`