Numpy:数组合矢量计算
Numpy, 數(shù)組和矢量計算包
前幾年前想學(xué)數(shù)據(jù)分析,于是就去學(xué)習(xí)Python的Numpy。然而看完《利用Python進行數(shù)據(jù)分析》后,也對它沒有多大印象的。但是學(xué)了一段時間R語言,并且將R語言和Python進行一些比較,再次學(xué)習(xí)Numpy就特別輕松了。
由于學(xué)過R語言,我可以簡單認(rèn)為Numpy提供的多維數(shù)據(jù)對象ndarray就是Python版本的R語言的vector, matrix和array。幾乎沒有特殊說明,這兩者的任何操作都是一致的。
Numpy的部分功能如下:
- ndarray, 一個具有矢量算術(shù)運算和復(fù)雜廣播能力的快速且節(jié)省空間的多維數(shù)組
- 用于對整組數(shù)據(jù)進行快速運算的標(biāo)準(zhǔn)數(shù)學(xué)函數(shù)(無需編寫循環(huán)函數(shù))
- 用于讀寫磁盤數(shù)據(jù)的工具以及用于操作內(nèi)存映射文件的工具
- 線性代數(shù), 隨機數(shù)生成以及傅里葉變換功能
- 用于繼承由C, C++, Fortran等語言編寫的代碼的工具
約定俗成:
import numpy as np也就說不會特意去聲明導(dǎo)入numpy。
創(chuàng)建多維數(shù)組
多維數(shù)組有多種創(chuàng)建方法,其中最簡單的就是使用arrary函數(shù)。以一切序列類型的對象作為輸入
# 一維數(shù)組,也就是R語言的最基本元素,vector In [1]: import numpy as np In [2]: data1 = [1,2,3,4,5] In [3]: arr1 = np.array(data1) In [4]: ?arr1 # 內(nèi)省下arr1對象 # 二維數(shù)組,也就是R語言的matrix In [5]: data2 = [[1,2,3],[4,5,6]] In [6]: arr2 = np.array(data2) In [7]: ?arr2 # 在R語言中用dim(), nrows, ncols查看數(shù)據(jù)維度 # 在Python中,這些可以用對象的方法查看。 In [10]: arr2.ndim Out[10]: 2 In [11]: arr2.shape Out[11]: (2, 3) # 和R語言一樣,ndarray的對象不允許存在多種數(shù)據(jù)類型 # ndarray會自動根據(jù)輸入選擇最合適的數(shù)據(jù)類型 In [17]: data3 = [1,"string", True] In [18]: arr3 = np.array(data3) In [19]: arr3 Out[19]: array(['1', 'string', 'True'], dtype='<U11') In [20]: arr3.dtype Out[20]: dtype('<U11')除了用array轉(zhuǎn)換序列型數(shù)據(jù)輸入以外,還可以用arange(類似于內(nèi)置的ranges), asarray(類似于array)。后面的方法和線性代數(shù)密切相關(guān),建議查看相應(yīng)的說明: ones ones_like, zeros zeros_like empty empty_like,eye identity。
關(guān)于數(shù)據(jù)類型, 一般情況下我們沒必要對它太過于關(guān)注。但是對于大數(shù)據(jù)集,則需要自己主動聲明。因為數(shù)據(jù)類型(dtype)負(fù)責(zé)將一塊內(nèi)存解釋為特定數(shù)據(jù)類型,即直接映射到相應(yīng)的機器表示。在R語言中有一類類型轉(zhuǎn)換函數(shù)(例如as.numeric)對數(shù)組內(nèi)的數(shù)據(jù)類型進行轉(zhuǎn)換,在Numpy則通過dtype.
數(shù)組運算
R語言的一大特點就是矢量化運算,能用來檢查你是否理解R語言。簡單理解,就是不用循環(huán)就能對數(shù)據(jù)批量運算。
個人愚見:矢量化運算是Numpy用C語言編寫,在C語言層面是也是循環(huán)。這也是為什么一個數(shù)組內(nèi)的數(shù)據(jù)類型要一致。
# R > arr1 [1] 1 2 3 4 5 > arr1 + 1 [1] 2 3 4 5 6 # Python In [29]: arr1 + 1 Out[29]: array([2, 3, 4, 5, 6]) In [35]: arr2 * 3 Out[35]: array([[ 3, 6, 9],[12, 15, 18]]) In [36]: arr2 * arr2 Out[36]: array([[ 1, 4, 9],[16, 25, 36]])我曾經(jīng)在 Python和R的異同(一)里談到原生Python要想實現(xiàn)R語言的矢量化就要使用列表推導(dǎo)式, 而目前可以用numpy帶來的矢量化運算屬性了。
索引和切片
切片
在R語言和Numpy,包括原生的Python都有切片的功能, 所謂的切片(slicing) 就是從已有的數(shù)組中返回選定的元素,而索引(index)提供指向存儲在數(shù)組指定位置的數(shù)據(jù)值的指針。
# R arr <- 0:9 arr_sub <- arr[1:5] # Python default list data = [i for i in range(10)] data_sub = data[0:5] # Python Numpy arr = np.arange(10) arr_sub = arr[0:5]上面的結(jié)果都是一致的,都是提取前5個元素。只不過要注意R語言的索引從1開始(5-1+1),而Python從0開始(5-0)。表面看起來是相同的,但其實Numpy切片得到只是原始數(shù)據(jù)的視圖(view),也就是淺復(fù)制,即你對Numpy切片后的數(shù)據(jù)進行操作,會影響到原始數(shù)據(jù)。
# Python Numpy In [60]: arr_sub[1] = 100 In [61]: arr Out[61]: array([ 0, 100, 2, 3, 4, 5, 6, 7, 8, 9]) # Python default list In [65]: data_sub[1] = 100 In [66]: data_sub Out[66]: [0, 100, 2, 3, 4] In [67]: data Out[67]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] # R 同Python默認(rèn)的列表原因就是Numpy的目的是處理大數(shù)據(jù),對大規(guī)模的數(shù)據(jù)進行實際復(fù)制會消耗不必要的性能和內(nèi)存。
numpy的索引操作和R語言幾乎一模一樣,分為切片索引,布爾值索引,花式索引。這些都在《R語言實戰(zhàn)》基本數(shù)據(jù)管理章節(jié)中的數(shù)據(jù)集選取子集里面提及。
切片索引:
In [79]: arr = np.eye(9,9) ## 類似于R的操作 In [80]: arr[1,1] Out[80]: 1.0 In [82]: arr[:,:] ## Python原來是通過遞歸對元素進行訪問 In [81]: arr[1][1] Out[81]: 1.0布爾值索引, 也就是先產(chǎn)生一個True, False的數(shù)組,然后根據(jù)這個數(shù)組提取數(shù)據(jù)
In [87]: arr[arr == 1] Out[87]: array([ 1., 1., 1., 1., 1., 1., 1., 1., 1.])花式索引, 就是提供指定順序的整數(shù)型列表
In [94]: arr = np.empty((8,4)) In [95]: for i in range(8):...: arr[i] = i...: ## 選取第4,3,1,6行數(shù)據(jù) In [99]: arr[[3,2,0,5]] Out[99]: array([ 3., 2., 0., 5.]) ## 在R里面就是 ## arr[c(4,3,1,6)]注意,如果一次性傳入多個索引數(shù)據(jù),Numpy會返回一維數(shù)組,但是R依舊會返回多維。這是目前第一個與R不太一樣,當(dāng)然和預(yù)想的結(jié)果也不同。
# R > mdata <- matrix(1:32,nrow=8, ncol=4) > mdata[c(2,6,8,2),c(1,4,2,3)][,1] [,2] [,3] [,4] [1,] 2 26 10 18 [2,] 6 30 14 22 [3,] 8 32 16 24 [4,] 2 26 10 18 # Numpy In [110]: arr = np.arange(1,33).reshape(8,4) In [111]: arr[[1,5,7,2],[0,3,1,2]] Out[111]: array([ 5, 24, 30, 11]) ## 為了解決這個問題,有兩種方法 In [112]: arr[[1,5,7,2]][:,[0,3,1,2]] Out[112]: array([[ 5, 8, 6, 7],[21, 24, 22, 23],[29, 32, 30, 31],[ 9, 12, 10, 11]]) In [113]: arr[np.ix_([1,5,7,2],[0,3,1,2])] Out[113]: array([[ 5, 8, 6, 7],[21, 24, 22, 23],[29, 32, 30, 31],[ 9, 12, 10, 11]])注: 花式索引以及布爾值索引和切片索引不同, 前者將數(shù)據(jù)復(fù)制到新的數(shù)組中,而后者是原始數(shù)據(jù)的視圖。 可能原因是前兩者的得到數(shù)據(jù)在原始數(shù)據(jù)中位置不是整塊存放。
數(shù)據(jù)轉(zhuǎn)置和軸對換
轉(zhuǎn)置(transpose)是數(shù)據(jù)重塑的一種特殊形式,返回的是原始數(shù)據(jù)的視圖(這一點和R不同)。數(shù)組不僅有transpose方法,還有一個T屬性, 這兩者在二維數(shù)組上是相同的。
arr = np.arange(1,33).reshape(8,4) arr.T np.transpose(arr) # 線性代數(shù)的矩陣內(nèi)積 np.dot(arr.T, arr)但是在更高維度上,T屬性依舊還是軸對換,transpose方法還需要提供軸編號組成的元組,這個真的是非常難以理解。
通用函數(shù):快速的元素級數(shù)組函數(shù)
我曾經(jīng)寫過一篇文章,叫做R語言的數(shù)據(jù)管理里面提到了基石函數(shù),來源于《R語言實戰(zhàn)》的高級數(shù)學(xué)管理。在numpy,這類函數(shù)叫做通用函數(shù)(UNIVERSAL FUNCTIONS, UFUNC),能夠進行矢量化運算的函數(shù)。按照官方文檔的劃分,大致分為
- 數(shù)學(xué)運算
- 三角函數(shù)
- 位運算函數(shù)
- 比較函數(shù)
- 浮點函數(shù)
按照《利用Pyton進行數(shù)據(jù)分析》可以分為一元函數(shù)和二元函數(shù)。
對于一些自定義的函數(shù),R語言采用的apply家族函數(shù)進行矢量化操作,避免循環(huán)。而在Numpy則是frompyfunc。不過這已經(jīng)比較高級了。
Numpy更多是Python進行科學(xué)計算的基礎(chǔ)包,因此數(shù)據(jù)分析部分的內(nèi)容就交給pandas吧。
總結(jié)
以上是生活随笔為你收集整理的Numpy:数组合矢量计算的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: $.ajax详解
- 下一篇: Iocomp控件教程之Pie Chart