聲明:本文大量參考https://www.dataquest.io/mission/6/getting-started-with-numpy(建議閱讀原文)
讀取文件
有一個名為world_alcohol.csv的文件,文件格式如下
Year,WHO region,Country,Beverage Types,Display Value 1986,Western Pacific,Viet Nam,Wine,0 1986,Americas,Uruguay,Other,0.5 1985,Africa,Cte d'Ivoire,Wine,1.62 |
文件內容的含義:(這是一份全球的飲料消耗記錄表,第一列的意思是記錄的年份,第二列指的是飲料的出產地,第三列指的是飲料的消耗地,第四列指的是飲料的類型,第五列指的是飲料的每人平均消耗量)
現在使用numpy的genfromtxt()函數來讀取該文件,delimiter參數是用來指定每一行用來分隔數據的分隔符
import numpy world_alcohol = numpy.genfromtxt('world_alcohol.csv', delimiter=',') print(world_alcohol)
此時讀取到的內容如下:
[[ nan nan nan nan nan] [ 1.98600000e+03 nan nan nan 0.00000000e+00] [ 1.98600000e+03 nan nan nan 5.00000000e-01] ..., [ 1.98600000e+03 nan nan nan 2.54000000e+00] [ 1.98700000e+03 nan nan nan 0.00000000e+00] [ 1.98600000e+03 nan nan nan 5.15000000e+00]] |
這是因為numpy在讀取元素時,默認是按照float格式來讀取的,對於不能轉換為float類型的數據會讀取為nan(not a number),對於留空的數據則顯示為na(not available),為了正確的讀取數據,可以通過增加參數:
- dtype參數用來指定讀取數據的格式,這里的U75表示將每一個數據都讀取為75個byte的unicode數據格式
- skip_header參數用來跳過文件的第一行
- delimiter參數用來指定每行數據的分隔符
import numpy world_alcohol = numpy.genfromtxt('world_alcohol.csv', dtype='U75', skip_header=True, delimiter=',') print(world_alcohol)
數組
可以通過array()函數來創建一個數組,在這里向量指的是變量只有一個列表,矩陣指的是具有多個列表的列表
創建一個向量:vector = numpy.array([10, 20, 30])
創建一個矩陣:matrix = numpy.array([[5,10,15],[20,25,30],[35,40,45]])
數組的屬性:
- shape屬性描述了該數組的結構
- dtype屬性描述了元素的數據類型
print(vector.shape) 輸出結果: (3,) 這是一個元組,表示vector變量是一個只有一行的向量,具有3個元素 print(matrix.shape) 輸出結果: (3,3)表示matrix變量是一個3 × 3的矩陣,具有3行3列共9個元素 |
print(vector.shape) 輸出結果: int64 |
數據類型大致有以下幾種:
- bool -- 布爾類型,True或者False
- int -- 整型,分為int16, int32, int64,后面的數字表明數值的長度
- float -- 浮點型,分為float16, float32, float64,后面的數字表明數值的長度
- string -- 字符串類型,分為string或者unicode,它們的差異在於存儲字符的方式
索引和分片
謹記一點:數組的索引是從0開始的
matrix = numpy.array([ [5,10,15], [20,25,30], [35,40,45] ]) print(matrix[1][1]) # 兩種方式都可以索引數據,輸出結果都是25,注意這里索引的是第二行第二個 print(matrix[1,1])
可以類似於使用切片來操作數據(將切片操作符 : 理解為‘全部’)
print(matrix[:,0]) # 輸出全部行,第一列的數據 [ 5 20 35] print(matrix[0,:]) # 輸出第一行,全部列的數據 [ 5 10 15] print(matrix[:,0:2]) # 輸出全部行,前2列的數據[ [5, 10], [20, 25], [35, 40] ] print(matrix[1:3,:]) # 輸出第2和第3行的全部列的數據 [ [20, 25, 30], [35, 40, 45] ] print(matrix[1:3,1]) # 輸出第2,3行的第1列數據 [ [10], [25] ]
數組比較
將數組與一個值相比較的時候,實際上是把數組內的每個值都與該值比較,然后返回一個布爾值列表
vector = numpy.array([5, 10, 15, 20]) vector == 10 返回的是:[False, True, False, False]
對於矩陣也如此
matrix = numpy.array([ [5, 10, 15], [20, 25, 30], [35, 40, 45] ]) matrix == 25 結果如下:[ [False, False, False], [False, True, False], [False, False, False] ]
數組比較中還可以使用多條件
vector = numpy.array([5, 10, 15, 20]) equal_to_ten_and_five = (vector == 10) & (vector == 5) 輸出:[False, False, False, False] equal_to_ten_or_five = (vector == 10) | (vector == 5) 輸出:[True, True, False, False]
數組比較的最大用處是
一、用來選擇數組或矩陣中的元素
matrix = numpy.array([ [5, 10, 15], [20, 25, 30], [35, 40, 45] ]) second_column_25 = (matrix[:,1] == 25) print(matrix[second_column_25, :]) 作用:提取出matrix中第二列中等於25的所有行,結果為[20, 25, 30]
二、替換元素
vector = numpy.array([5, 10, 15, 20]) equal_to_ten_or_five = (vector == 10) | (vector == 5) vector[equal_to_ten_or_five] = 50 print(vector) 輸出:[50, 50, 15, 20]
原理如下:
常用於替換空元素
譬如將world_alcohol中的第五列中的留空的數據都替換為字符串0:
is_value_empty = world_alcohol[:, 4] == ' ' world_alcohol[is_value_empty, 4] = '0'
數據類型轉換
通過使用astype()函數來轉換一個數組的數據類型
vector = numpy.array(["1", "2", "3"]) vector = vector.astype(float) print(vector) 結果:[1.0, 2.0, 3.0]
簡單的運算
參考numpy的手冊:http://docs.scipy.org/doc/numpy-1.10.1/index.html
挑出幾個重要的運算函數:
- l sum() -- 計算一個向量中的全部元素的總和,或者是一個矩陣中的一個維度的總和
- l mean() -- 同上,計算的是平均值
- l max() -- 同上,計算的是最大值
vector = numpy.array([5, 10, 15, 20]) vector.sum() 結果為:50 matrix = numpy.array([ [5, 10, 15], [20, 25, 30], [35, 40, 45] ]) matrix.sum(axis=1) 結果:[30, 75, 120] 對於矩陣來說,需要指定axis參數,該參數等於1時表示計算的是每行,等於0時表示計算的是每列的總和
練習
使用world_alcohol.csv文件,計算在1986年里每個國家的飲料消耗量
import numpy world_alcohol = numpy.genfromtxt('world_alcohol.csv', dtype='U75', skip_header=True, delimiter=',') totals = {} year = world_alcohol[world_alcohol[:, 0] == '1989', :] # 選擇1989年的數據集 countries = set(world_alcohol[:,2]) # 選擇全部國家 for each in countries: # 分別計算每個國家 consumption = year[year[:,2] == each, :] consumption[consumption[:, 4] == '',4] = '0' temp = consumption[:,4].astype(float) # 將留空的數據轉變為浮點數0參與運算 country_consumption = temp.sum() totals[each] = country_consumption
總結
使用numpy的比直接對一個列表集合的運算更加方便,主要優於以下幾點:
- 更容易對數據進行計算
- 可以快速地進行數據索引和分片
- 可以快速地轉換數據類型
然而,numpy有一些不足之處:
- 在同一個數據集中的數據必須具有相同的數據類型,在處理多數據集時會變得很困難
- 行和列都需要使用數字來索引,而不能使用別名,這樣容易造成混淆
而Pandas解決了Numpy的幾點不足