Try   HackMD

使用 numpy.genfromtxt 從文字檔中讀取資料

作者:王一哲
日期: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=[TrueFalse], 
              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±0.071531035658
b=2.991771672485±0.371842522314

R2=0.999497575579

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
用 matplotlib 繪製的XY散佈圖


tags:Python