Python數據分析之numpy學習(一)
Python是一門不錯的動態語言,其應用的領域非常廣泛,如web開發、Linux運維、數據挖掘、機器學習、爬蟲、推薦系統等。在學完《廖雪峰Python2.7教程》感覺受益匪淺,掌握了基本的語法之後開始接觸用Python進行數據分析。這裡向大家推薦兩本書《Python數據分析》和《利用Python進行數據分析》,而這兩本書也是目前我正在學習的材料,雖然這兩本書都是基於Python2.x,但對於Python3.x也能正常運行。
本期將會涉及到Python模塊中的numpy,這是一個處理數組的強大模塊,而該模塊也是其他數據分析模塊(如pandas和scipy)的核心。下面將從這5個方面來介紹numpu模塊的內容:
1)數組的創建
2)有關數組的屬性和函數
3)數組元素的獲取--普通索引、切片、布爾索引和花式索引
4)統計函數與線性代數運算
5)隨機數的生成
數組的創建
numpy中使用array()函數創建數組,array的首個參數一定是一個序列,可以是元組也可以是列表。
一維數組的創建
可以使用numpy中的arange()函數創建一維有序數組,它是內置函數range的擴展版。
In [1]: import numpy as np
In [2]: ls1 = range(10)
In [3]: list(ls1)
Out[3]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
In [4]: type(ls1)
Out[4]: range
In [5]: ls2 = np.arange(10)
In [6]: list(ls2)
Out[6]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
In [7]: type(ls2)
Out[7]: numpy.ndarray
通過arange生成的序列就不是簡簡單單的列表類型了,而是一個一維數組。
如果一維數組不是一個規律的有序元素,而是人為的輸入,就需要array()函數創建了。
In [8]: arr1 = np.array((1,20,13,28,22))
In [9]: arr1
Out[9]: array([ 1, 20, 13, 28, 22])
In [10]: type(arr1)
Out[10]: numpy.ndarray
上面是由元組序列構成的一維數組。
In [11]: arr2 = np.array([1,1,2,3,5,8,13,21])
In [12]: arr2
Out[12]: array([ 1, 1, 2, 3, 5, 8, 13, 21])
In [13]: type(arr2)
Out[13]: numpy.ndarray
上面是由列表序列構成的一維數組。
二維數組的創建
二維數組的創建,其實在就是列表套列表或元組套元組。
In [14]: arr3 = np.array(((1,1,2,3),(5,8,13,21),(34,55,89,144)))
In [15]: arr3
Out[15]:
array([[ 1, 1, 2, 3],
[ 5, 8, 13, 21],
[ 34, 55, 89, 144]])
上面使用元組套元組的方式。
In [16]: arr4 = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]])
In [17]: arr4
Out[17]:
array([[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12]])
上面使用列表套列表的方式。
對於高維數組在將來的數據分析中用的比較少,這裡關於高維數組的創建就不贅述了,構建方法仍然是套的方式。
上面所介紹的都是人為設定的一維、二維或高維數組,numpy中也提供了幾種特殊的數組,它們是:
In [18]: np.ones(3) #返回一維元素全為1的數組
Out[18]: array([ 1., 1., 1.])
In [19]: np.ones([3,4]) #返回元素全為1的3×4二維數組
Out[19]:
array([[ 1., 1., 1., 1.],
[ 1., 1., 1., 1.],
[ 1., 1., 1., 1.]])
In [20]: np.zeros(3) #返回一維元素全為0的數組
Out[20]: array([ 0., 0., 0.])
In [21]: np.zeros([3,4]) #返回元素全為0的3×4二維數組
Out[21]:
array([[ 0., 0., 0., 0.],
[ 0., 0., 0., 0.],
[ 0., 0., 0., 0.]])
In [22]: np.empty(3) #返回一維空數組
Out[22]: array([ 0., 0., 0.])
In [23]: np.empty([3,4]) #返回3×4二維空數組
Out[23]:
array([[ 0., 0., 0., 0.],
[ 0., 0., 0., 0.],
[ 0., 0., 0., 0.]])
有關數組的屬性和函數
當一個數組構建好後,我們看看關於數組本身的操作又有哪些屬性和函數:
In [24]: arr3
Out[24]:
array([[ 1, 1, 2, 3],
[ 5, 8, 13, 21],
[ 34, 55, 89, 144]])
In [25]: arr3.shape #shape方法返回數組的行數和列數
Out[25]: (3, 4)
In [26]: arr3.dtype #dtype方法返回數組的數據類型
Out[26]: dtype("int32")
In [27]: a = arr3.ravel() #通過ravel的方法將數組拉直(多維數組降為一維數組)
In [28]: a
Out[28]: array([ 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144])
In [29]: b = arr3.flatten() #通過flatten的方法將數組拉直
In [30]: b
Out[30]: array([ 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144])
兩者的區別在於ravel方法生成的是原數組的視圖,無需佔有內存空間,但視圖的改變會影響到原數組的變化。而flatten方法返回的是真實值,其值的改變並不會影響原數組的更改。
通過下面的例子也許就能明白了:
In [31]: b[:3] = 0
In [32]: arr3
Out[32]:
array([[ 1, 1, 2, 3],
[ 5, 8, 13, 21],
[ 34, 55, 89, 144]])
通過更改b的值,原數組沒有變化。
In [33]: a[:3] = 0
In [34]: arr3
Out[34]:
array([[ 0, 0, 0, 3],
[ 5, 8, 13, 21],
[ 34, 55, 89, 144]])
a的值變化後,會導致原數組跟著變化。
In [35]: arr4
Out[35]:
array([[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12]])
In [36]: arr4.ndim #返回數組的維數
Out[36]: 2
In [37]: arr4.size #返回數組元素的個數
Out[37]: 12
In [38]: arr4.T #返回數組的轉置結果
Out[38]:
array([[ 1, 5, 9],
[ 2, 6, 10],
[ 3, 7, 11],
[ 4, 8, 12]])
如果數組的數據類型為複數的話,real方法可以返回複數的實部,imag方法返回複數的虛部。
介紹完數組的一些方法後,接下來我們看看數組自身有哪些函數可操作:
In [39]: len(arr4) #返回數組有多少行
Out[39]: 3
In [40]: arr3
Out[40]:
array([[ 0, 0, 0, 3],
[ 5, 8, 13, 21],
[ 34, 55, 89, 144]])
In [41]: arr4
Out[41]:
array([[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12]])
In [42]: np.hstack((arr3,arr4))
Out[42]:
array([[ 0, 0, 0, 3, 1, 2, 3, 4],
[ 5, 8, 13, 21, 5, 6, 7, 8],
[ 34, 55, 89, 144, 9, 10, 11, 12]])
橫向拼接arr3和arr4兩個數組,但必須滿足兩個數組的行數相同。
In [43]: np.vstack((arr3,arr4))
Out[43]:
array([[ 0, 0, 0, 3],
[ 5, 8, 13, 21],
[ 34, 55, 89, 144],
[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12]])
縱向拼接arr3和arr4兩個數組,但必須滿足兩個數組的列數相同。
In [44]: np.column_stack((arr3,arr4)) #與hstack函數具有一樣的效果
Out[44]:
array([[ 0, 0, 0, 3, 1, 2, 3, 4],
[ 5, 8, 13, 21, 5, 6, 7, 8],
[ 34, 55, 89, 144, 9, 10, 11, 12]])
In [45]: np.row_stack((arr3,arr4)) #與vstack函數具有一樣的效果
Out[45]:
array([[ 0, 0, 0, 3],
[ 5, 8, 13, 21],
[ 34, 55, 89, 144],
[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12]])
reshape()函數和resize()函數可以重新設置數組的行數和列數:
In [46]: arr5 = np.array(np.arange(24))
In [47]: arr5 #此為一維數組
Out[47]:
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
17, 18, 19, 20, 21, 22, 23])
In [48]: a = arr5.reshape(4,6)
In [49]: a
Out[49]:
array([[ 0, 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10, 11],
[12, 13, 14, 15, 16, 17],
[18, 19, 20, 21, 22, 23]])
通過reshape函數將一維數組設置為二維數組,且為4行6列的數組。
In [50]: a.resize(6,4)
In [51]: a
Out[51]:
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15],
[16, 17, 18, 19],
[20, 21, 22, 23]])
通過resize函數會直接改變原數組的形狀。
數組轉換:tolist將數組轉換為列表,astype()強制轉換數組的數據類型,下面是兩個函數的例子:
In [53]: b = a.tolist()
In [54]: b
Out[54]:
[[0, 1, 2, 3],
[4, 5, 6, 7],
[8, 9, 10, 11],
[12, 13, 14, 15],
[16, 17, 18, 19],
[20, 21, 22, 23]]
In [55]: type(b)
Out[55]: list
In [56]: c = a.astype(float)
In [57]: c
Out[57]:
array([[ 0., 1., 2., 3.],
[ 4., 5., 6., 7.],
[ 8., 9., 10., 11.],
[ 12., 13., 14., 15.],
[ 16., 17., 18., 19.],
[ 20., 21., 22., 23.]])
In [58]: a.dtype
Out[58]: dtype("int32")
In [59]: c.dtype
Out[59]: dtype("float64")
數組元素的獲取
通過索引和切片的方式獲取數組元素,一維數組元素的獲取與列表、元組的獲取方式一樣:
In [60]: arr7 = np.array(np.arange(10))
In [61]: arr7
Out[61]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [62]: arr7[3] #獲取第4個元素
Out[62]: 3
In [63]: arr7[:3] #獲取前3個元素
Out[63]: array([0, 1, 2])
In [64]: arr7[3:] #獲取第4個元素即之後的所有元素
Out[64]: array([3, 4, 5, 6, 7, 8, 9])
In [65]: arr7[-2:] #獲取末尾的2個元素
Out[65]: array([8, 9])
In [66]: arr7[::2] #從第1個元素開始,獲取步長為2的所有元素
Out[66]: array([0, 2, 4, 6, 8])
二維數組元素的獲取:
In [67]: arr8 = np.array(np.arange(12)).reshape(3,4)
In [68]: arr8
Out[68]:
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
In [69]: arr8[1] #返回數組的第2行
Out[69]: array([4, 5, 6, 7])
In [70]: arr8[:2] #返回數組的前2行
Out[70]:
array([[0, 1, 2, 3],
[4, 5, 6, 7]])
In [71]: arr8[[0,2]] #返回指定的第1行和第3行
Out[71]:
array([[ 0, 1, 2, 3],
[ 8, 9, 10, 11]])
In [72]: arr8[:,0] #返回數組的第1列
Out[72]: array([0, 4, 8])
In [73]: arr8[:,-2:] #返回數組的後2列
Out[73]:
array([[ 2, 3],
[ 6, 7],
[10, 11]])
In [74]: arr8[:,[0,2]] #返回數組的第1列和第3列
Out[74]:
array([[ 0, 2],
[ 4, 6],
[ 8, 10]])
In [75]: arr8[1,2] #返回數組中第2行第3列對應的元素
Out[75]: 6
布爾索引,即索引值為True和False,需要注意的是布爾索引必須輸數組對象。
In [76]: log = np.array([True,False,False,True,True,False])
In [77]: arr9 = np.array(np.arange(24)).reshape(6,4)
In [78]: arr9
Out[78]:
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15],
[16, 17, 18, 19],
[20, 21, 22, 23]])
In [79]: arr9[log] #返回所有為True的對應行
Out[79]:
array([[ 0, 1, 2, 3],
[12, 13, 14, 15],
[16, 17, 18, 19]])
In [80]: arr9[-log] #通過負號篩選出所有為False的對應行
Out[80]:
array([[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[20, 21, 22, 23]])
舉一個場景,一維數組表示區域,二維數組表示觀測值,如何選取目標區域的觀測?
In [81]: area = np.array(["A","B","A","C","A","B","D"])
In [82]: area
Out[82]:
array(["A", "B", "A", "C", "A", "B", "D"],
dtype="<>< span=""><>
In [83]: observes = np.array(np.arange(21)).reshape(7,3)
In [84]: observes
Out[84]:
array([[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8],
[ 9, 10, 11],
[12, 13, 14],
[15, 16, 17],
[18, 19, 20]])
In [85]: observes[area == "A"]
Out[85]:
array([[ 0, 1, 2],
[ 6, 7, 8],
[12, 13, 14]])
返回所有A區域的觀測。
In [86]: observes[(area == "A") | (area == "D")] #條件值需要在&(and),|(or)兩端用圓括弧括起來
Out[86]:
array([[ 0, 1, 2],
[ 6, 7, 8],
[12, 13, 14],
[18, 19, 20]])
返回所有A區域和D區域的觀測。
當然,布爾索引也可以與普通索引或切片混合使用:
In [87]: observes[area == "A"][:,[0,2]]
Out[87]:
array([[ 0, 2],
[ 6, 8],
[12, 14]])
返回A區域的所有行,且只獲取第1列與第3列數據。
花式索引:實際上就是將數組作為索引將原數組的元素提取出來
In [88]: arr10 = np.arange(1,29).reshape(7,4)
In [89]: arr10
Out[89]:
array([[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12],
[13, 14, 15, 16],
[17, 18, 19, 20],
[21, 22, 23, 24],
[25, 26, 27, 28]])
In [90]: arr10[[4,1,3,5]] #按照指定順序返回指定行
Out[90]:
array([[17, 18, 19, 20],
[ 5, 6, 7, 8],
[13, 14, 15, 16],
[21, 22, 23, 24]])
In [91]: arr10[[4,1,5]][:,[0,2,3]] #返回指定的行與列
Out[91]:
array([[17, 19, 20],
[ 5, 7, 8],
[21, 23, 24]])
In [92]: arr10[[4,1,5],[0,2,3]]
Out[92]: array([17, 7, 24])
請注意!這與上面的返回結果是截然不同的,上面返回的是二維數組,而這條命令返回的是一維數組。
如果想使用比較簡單的方式返回指定行以列的二維數組的話,可以使用ix_()函數
In [93]: arr10[np.ix_([4,1,5],[0,2,3])]
Out[93]:
array([[17, 19, 20],
[ 5, 7, 8],
[21, 23, 24]])
這與arr10[[4,1,5]][:,[0,2,3]]返回的結果是一致的。
--------------------------------------------------------------------------------------------------------
由於正文部分不能超過20000字元,接下來的部分將在《Python數據分析之numpy學習(二)》中繼續講解。
--------------------------------------------------------------------------------------------------------
使用Python進行數據分析,一般都會使用到numpy,pandas,scipy和matplotlib等模塊,而numpy是最為基礎的模塊,其他模塊的使用都是以numpy為核心,所以這裡講解了有關numpy的方方面面,這部分的學習非常重要,希望感興趣的朋友多看看這方面的文檔和動手操作。
每天進步一點點2015
學習與分享,取長補短,關注小號!
推薦閱讀:
※雨沐田:數據分析從何處入手?
※精選 | 2018年1月R新包推薦
※超酷der !億信BI4.7重磅發布,數據大屏展現是這樣的
※《BI程序猿——2017年總結》
※紐約時報用數據可視化告訴你,美國黑人如何悲哀地規避了階層固化