浅析Numpy.genfromtxt及File I/O讲解
Python 并沒有提供數(shù)組功能,雖然列表 (list) 可以完成基本的數(shù)組功能,但它并不是真正的數(shù)組,而且在數(shù)據(jù)量較大時(shí),使用列表的速度就會(huì)慢的讓人難受。為此,Numpy 提供了真正的數(shù)組功能,以及對數(shù)據(jù)快速處理的函數(shù)。Numpy 還是很多更高級的擴(kuò)展庫的依賴庫,例如: Scipy,Matplotlib,Pandas等。此外,值得一提的是:Numpy 內(nèi)置函數(shù)處理數(shù)據(jù)的速度是 C 語言級別的,因此編寫程序時(shí),應(yīng)盡量使用內(nèi)置函數(shù),避免出現(xiàn)效率瓶頸的現(xiàn)象。一切計(jì)算源于數(shù)據(jù),那么我們就來看一看Numpy.genfromtxt 如何優(yōu)雅的處理數(shù)據(jù)。
官方文檔
Enthought offical tutorial: numpy.genfromtxt
A very common file format for data file is comma-separated values (CSV), or related formats such as TSV (tab-separated values). To read data from such files into Numpy arrays we can use the numpy.genfromtxt function.
案例說明
我們以數(shù)字示波器采集的實(shí)驗(yàn)產(chǎn)生的三角波 (triangular waveform) 為例,它是包含數(shù)據(jù)信息的表頭,以 .txt 格式存儲(chǔ)的文本文件。
Type: raw Points: 16200 Count: 1 ... X Units: second Y Units: Volt XY Data: 2.4000000E-008, 1.4349E-002 2.4000123E-008, 1.6005E-002 2.4000247E-008, 1.5455E-002 2.4000370E-008, 1.5702E-002 2.4000494E-008, 1.5147E-002 ...Python 獲取數(shù)據(jù)的方式有很多:(1) 如果在命令行運(yùn)行 Python 腳本,你可以用 sys.stdin 和 sys.stdout 以管道 (pipe) 方式傳遞數(shù)據(jù);(2) 可以顯式地用代碼來讀寫文件獲取數(shù)據(jù);(3) 從網(wǎng)頁獲取數(shù)據(jù),也就是所謂的爬蟲 (web spider);(4) 使用 API (Application Programming Interface) 獲取結(jié)構(gòu)化格式的數(shù)據(jù)。 而在科學(xué)計(jì)算領(lǐng)域,更多的是處理實(shí)驗(yàn)中所獲得的數(shù)據(jù),比如:傳感器,采集卡,示波器,光譜儀等儀器采集的數(shù)據(jù)。
案例一:溫度傳感器 (temperature sensor) 數(shù)據(jù)
本案例所采用的數(shù)據(jù)是熱敏電阻 (thermistor) 采集的被加熱物體的溫度信息數(shù)據(jù),其以如下格式存儲(chǔ)在txt文件中:
2018-02-15 21:31:08.781 49.9492 2018-02-15 21:31:09.296 49.9589 2018-02-15 21:31:09.811 49.964 2018-02-15 21:31:10.326 49.9741 2018-02-15 21:31:10.841 49.983 ...處理文本文件的第一步是通過 open 命令來獲取一個(gè)文件對象:
file_for_reading = open('thermistor.txt', 'r') # 'r' 意味著只讀 file_for_writing = open('thermistor.txt', 'w') # 'w' 是寫入 file_for_appending = open('thermistor.txt', 'a') # 'a' 是添加 file_for_xxx.close() # 完成操作后要關(guān)閉文件因?yàn)榉浅H菀淄涥P(guān)閉文件,所以應(yīng)該在 with 程序塊里操作文件,這樣結(jié)尾處文件會(huì)被自動(dòng)關(guān)閉:
with open('thermistor.txt', 'r') as f:data = function_that_gets_data_form(f) # 獲取數(shù)據(jù)函數(shù)此時(shí),f 已經(jīng)關(guān)閉了,就不能試圖使用它啦,然后對數(shù)據(jù)執(zhí)行相應(yīng)的操作即可。
process(data) # 處理數(shù)據(jù)函數(shù) 處理文本文件第二步是觀察數(shù)據(jù)特征,選擇合適的讀取命令:通過觀察,可以發(fā)現(xiàn),文件沒有頭部,每一行包括三種數(shù)據(jù) (編號,時(shí)間,溫度) 他們之間以空格鍵分開,每一列是同一類數(shù)據(jù),這樣我們就可以用 Python 中的 csv 模塊中的 csv.reader 對其進(jìn)行迭代處理,每一行都會(huì)被處理成恰當(dāng)劃分的列表。 1 import csv 2 with open(r"thermistor.txt","rb") as f: 3 reader = csv.reader(f,delimiter='\t') 4 number=[] 5 time = [] 6 data=[] 7 for row in reader: 8 number.append(row[0]) 9 time.append(row[1]) 10 data.append(float(row[2]))處理文本文件的第三步是檢測數(shù)據(jù)讀取格式是否正確,我們可以用如下的方式檢測:
>>> print number[0], time[0], data[0] >>> 2018-02-15 21:31:08.781 49.9492從輸出的首個(gè)元素來看,以上的讀取數(shù)據(jù)的方式是沒有問題的,但是到這里我們并不能完全放心我們的數(shù)據(jù)格式:
>>> print number[0:3], time[0:3], data[0:3] >>> ['\xef\xbb\xbf1', '2', '3'] ['2018-02-15 21:31:08.781', '2018-02-15 21:31:09.296', '2018-02-15 21:31:09.811'] [49.9492, 49.9589, 49.964] 當(dāng)我們以列表的形式輸出時(shí),number 中的首個(gè)元素出現(xiàn)了我們沒有預(yù)料到的“亂碼”,這其實(shí)是 BOM (byte order mark), 它是為 UTF-16 和 UTF-32 準(zhǔn)備的,用以標(biāo)記字節(jié)序。微軟在 UTF-8 中使用 BOM 是因?yàn)檫@樣可以把 UTF-8 和 ASCII 等編碼區(qū)別開,但這樣的文件會(huì)給我們的數(shù)據(jù)讀取帶來問題。還好,我們可以用 Python 中的 codecs 模塊解決這個(gè)問題。 1 import csv 2 import codecs 3 with codecs.open(r"thermistor.txt","rb","utf-8-sig") as f: 4 reader = csv.reader(f,delimiter='\t') 5 number=[] time=[] data=[] 6 for row in reader: 7 number.append(row[0]) 8 time.append(row[1]) 9 data.append(float(row[2])此時(shí),我們再以列表形式輸出時(shí),就會(huì)得到正確的結(jié)果:
>>> ['1', '2', '3'] ['2018-02-15 21:31:08.781', '2018-02-15 21:31:09.296', '2018-02-15 21:31:09.811'] [49.9492, 49.9589, 49.964]然后就可以用得到的數(shù)據(jù)進(jìn)行處理分析啦~
案例二:示波器 (oscilloscope) 數(shù)據(jù)
有了上面的經(jīng)驗(yàn),我們直接從處理文本文件第二步開始,示波器數(shù)據(jù)相對上面的數(shù)據(jù),復(fù)雜的地方在于它包含了表頭信息,而這些信息大部分時(shí)間是處理數(shù)據(jù)中不太需要的,它的數(shù)據(jù)格式如下:
Type: raw Points: 16200 Count: 1 XInc: 1.23457E-013 XOrg: 2.4000000000E-008 YData range: 1.48000E-001 YData center: 5.00000E-004 Coupling: 50 Ohms XRange: 2.00000E-009 XOffset: 2.4000000000E-008 YRange: 1.44000E-001 YOffset: 5.00000E-004 Date: 15 APR 2018 Time: 16:00:54:74 Frame: 86100C:MY46520443 X Units: second Y Units: Volt XY Data: 2.4000000E-008, 1.4349E-002 2.4000123E-008, 1.6005E-002 2.4000247E-008, 1.5455E-002 2.4000370E-008, 1.5702E-002 2.4000494E-008, 1.5147E-002 ...可以看出,“表頭”是一些參數(shù)信息,真正有用的數(shù)據(jù)是從 “XY Data:” 下一行開始的,對于這樣的數(shù)據(jù)有兩種方法進(jìn)行讀取:(1) 直接跳過“表頭”讀取數(shù)據(jù);(2) 利用正則表達(dá)式尋找“表頭” 和數(shù)據(jù)的不同特征進(jìn)行識別讀取。
1 with open(r"waveform.txt","rb") as f: 2 lines = f.readlines() x=[] y=[] 3 for line in lines[18:]: 4 x.append(float(line.replace("\r\n","").split(",")[0])) 5 y.append(float(line.replace("\r\n","").split(",")[1]))通過觀察我們發(fā)現(xiàn)有效數(shù)據(jù)是從第19行開始的,于是我們直接從19行開始讀取數(shù)據(jù),跳過“表頭”,以列表形式輸出 x 和 y 前3個(gè)元素如下:
>>> [2.4e-08, 2.4000123e-08, 2.4000247e-08] [0.014349, 0.016005, 0.015455] # 數(shù)據(jù)讀取正確運(yùn)用正則表達(dá)式讀取數(shù)據(jù)的關(guān)鍵在于找到有效數(shù)據(jù)行的獨(dú)有特征,這里以 “E-002” 作為有效數(shù)據(jù)行區(qū)別于“表頭”的特征,對數(shù)據(jù)的讀取方式如下:
1 import re 2 with open(r"waveform.txt","rb") as f: 3 lines = f.readlines() 4 x=[] 5 y=[] 6 for line in lines: 7 if re.search('E-002',line): 8 x.append(float(line.replace("\r\n","").split(",")[0])) 9 y.append(float(line.replace("\r\n","").split(",")[1]))同樣,以列表形式輸出 x 和 y 前3個(gè)元素用于檢驗(yàn):
>>> [2.4e-08, 2.4000123e-08, 2.4000247e-08] [0.014349, 0.016005, 0.015455] # 數(shù)據(jù)讀取正確注:具體的數(shù)據(jù)讀取方式要根據(jù)具體文本文件的特征決定,運(yùn)用合適的方法才能得到更好的結(jié)果。
案例三:二維數(shù)據(jù)寫入
很多時(shí)候,經(jīng)過 process( ) 后的數(shù)據(jù),需要備份留用或者供其他程序調(diào)用,因此,將處理后的數(shù)據(jù)寫入文本文件也將是關(guān)鍵的一步。根據(jù)數(shù)據(jù)讀入的經(jīng)驗(yàn),被讀入的數(shù)據(jù)經(jīng)常存儲(chǔ)在 list 中,那么處理后數(shù)據(jù)也通常存儲(chǔ)在 list 中,因此,以 list 的寫入作為例子:
x = [1, 2, 3, 4] y = [2.0, 4.0, 6.0, 8.0] # 參考數(shù)據(jù)接下來就要考慮的是要以什么樣的格式保存數(shù)據(jù),為了更加直觀的表現(xiàn)數(shù)據(jù)的關(guān)系,我們將 x,y 分別保存為一列,中間以空格鍵隔開,那么 csv.writer( ) 將是很好的工具:
1 xy = {} 2 for i in range(len(x)): 3 xy[x[i]] = y[i] 4 with open(r"15.txt", 'wb') as f: 5 writer = csv.writer(f,delimiter='\t') 6 for x, y in xy.items(): 7 writer.writerow([x, y])為了同時(shí)保存 x 和 y 的對應(yīng)值,這里把 x 和 y 寫入字典,x 為鍵 (key), y 為 值 (value) ,xy 就是 x 和 y 構(gòu)成的字典。保存后的數(shù)據(jù)格式如下所示:
1 2.0 2 4.0 3 6.0 4 8.0案例四:多維數(shù)據(jù)寫入
由于字典的鍵 (key) 和值 (value) 對應(yīng)的特殊數(shù)據(jù)結(jié)構(gòu),寫入二維數(shù)據(jù)較為方便,對于多維數(shù)據(jù),我們就需要構(gòu)建多維矩陣,或者列表與元組結(jié)合的方式錄入:
x = [1, 2, 3, 4] y = [2.0, 4.0, 6.0, 8.0] z = [3.0, 6.0, 9.0, 12.0]這里以三維數(shù)據(jù)為例子。同樣,需要將 x,y,z 各一列寫入到txt中:
1 xyz = [] 2 for i in range(len(x)): 3 xyz.append([x[i],y[i],z[i]]) 4 with open(r"15.txt", 'wb') as f: 5 writer = csv.writer(f,delimiter='\t') 6 for x, y, z in xyz: 7 writer.writerow([x, y, z])這樣,就可以很容易地得到需要的數(shù)據(jù)格式的文本文件:
1 2.0 3.0 2 4.0 6.0 3 6.0 9.0 4 8.0 12.0我們已經(jīng)提到了兩種方法讀取上述的數(shù)據(jù),它們共同點(diǎn)是將數(shù)據(jù)存儲(chǔ)在列表中,正如開頭所說,列表在處理大量數(shù)據(jù)時(shí)是非常緩慢的。那么,我們就來看一看 numpy.genfromtxt 如何大顯身手。
代碼示例
為了得到我們需要的有用數(shù)據(jù),我們有兩個(gè)硬的要求: (1) 跳過表頭信息;(2) 區(qū)分橫縱坐標(biāo)。
import numpy as np data = np.genfromtxt('waveform.txt',delimiter=',',skip_header=18) **delimiter: the str used to separate data. 橫縱坐標(biāo)以 ',' 分割,因此給 delimiter 傳入 ','。skip_header: ** the number of lines to skip at the beginning of the file. 有用數(shù)據(jù)是從19行開始的,因此給 skip_header 傳入 18。 print data[0:3,0], data[0:3,1]因?yàn)樽x入的是二維數(shù)據(jù),因此利用 numpy 二維數(shù)據(jù)的切片方式 (Index slicing) 輸出各自的前三個(gè)數(shù)據(jù)驗(yàn)證是否讀取正確:
[ 2.40000000e-08 2.40001230e-08 2.40002470e-08] [ 0.014349 0.016005 0.015455]對數(shù)據(jù)進(jìn)行歸一化處理后,調(diào)用 Matplotlib 畫圖命令,就可得到圖像如下:
1 import matplotlib.pyplot as plt 2 fig, axes = plt.subplots(figsize=(8,6)) 3 axes.plot(x, y, 'r', linewidth=3) 4 axes.set_xlabel('Time(ps)') 5 axes.set_ylabel('Amplitude[a.u.]') 6 fig.savefig("triangular.png", dpi=600) triangular waveform補(bǔ)充
numpy.genformtxt( ) 函數(shù)提供了眾多的入?yún)?#xff0c;實(shí)現(xiàn)不同格式數(shù)據(jù)的讀取,詳情可參考:numpy.genfromtxt
此外,numpy 中還提供了將數(shù)據(jù)存儲(chǔ)為 CSV 格式的函數(shù) numpy.savetxt( ),詳情可參考:numpy.savetxt
轉(zhuǎn)載于:https://www.cnblogs.com/ECJTUACM-873284962/p/8449346.html
總結(jié)
以上是生活随笔為你收集整理的浅析Numpy.genfromtxt及File I/O讲解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【总结】升级Xcode8遇到的问题及解决
- 下一篇: 关于监听UITextField的问题