NumPy
1 NumPy概述
?? NumPy(Numerical Python的簡稱)是Python數(shù)值計算最重要的基礎包腺晾。大多數(shù)提供科學計算的包都是用NumPy的數(shù)組作為構建基礎。
NumPy的優(yōu)點:
- 一個強大的N維數(shù)組對象ndarray,具有矢量算術運算和復雜廣播能力的快速且節(jié)省空間的多維數(shù)組
- 用于集成由C充尉、C++故觅、Fortran等語言類庫的C語言 API
- 線性代數(shù)掏觉、隨機數(shù)生成以及傅里葉變換功能繁堡。
- 用于對整組數(shù)據(jù)進行快速運算的標準數(shù)學函數(shù)(無需編寫循環(huán)),支持大量的數(shù)據(jù)運算
- 是眾多機器學習框架的基礎庫
NumPy之于數(shù)值計算特別重要的原因之一,是因為它可以高效處理大數(shù)組的數(shù)據(jù)口叙。這是因為:
- NumPy是在一個連續(xù)的內(nèi)存塊中存儲數(shù)據(jù)炼绘,獨立于其他Python內(nèi)置對象。NumPy的C語言編寫的算法庫可以操作內(nèi)存妄田,而不必進行類型檢查或其它前期工作俺亮。比起Python的內(nèi)置序列,NumPy數(shù)組使用的內(nèi)存更少疟呐。
- NumPy可以在整個數(shù)組上執(zhí)行復雜的計算铅辞,而不需要Python的for循環(huán)。
我們在使用NumPy時習慣給它起個別名np萨醒,推薦這么做
NumPy的運行速度:
import numpy as np
np_arr = np.arange(1000000)
py_list = list(range(1000000))
%time for _ in range(10): np_arr2 = np_arr ** 2
%time for _ in range(10): py_list2 = [x ** 2 for x in py_list]
Wall time: 20 ms
Wall time: 5.16 s
可以看到基于NumPy的算法比純python快100倍以上,并且使用的內(nèi)存更少
2 創(chuàng)建ndarry
?? NumPy最重要的一個特點就是ndarray(N-dimensional array)苇倡,即N維數(shù)組)富纸,該對象是一個快速而靈活的大數(shù)據(jù)集容器。你可以利用這種數(shù)組對整塊數(shù)據(jù)執(zhí)行一些數(shù)學運算旨椒,其語法跟標量元素之間的運算一樣晓褪。
import numpy as np
print(np.__version__)
nparr = np.array([i for i in range(10)])
print(nparr)
nparr2 = np.array(list('abcdefg'))
print(nparr2)
nparr3 = np.array([[11,22,33,44],[10,20,30,40]])
print(nparr3)
1.15.4
[0 1 2 3 4 5 6 7 8 9]
['a' 'b' 'c' 'd' 'e' 'f' 'g']
[[11 22 33 44]
[10 20 30 40]]
2.1 arange創(chuàng)建數(shù)組
arange函數(shù)是python內(nèi)置函數(shù)range函數(shù)的數(shù)組版本.
ndarray = np.arange(10)
print(ndarray)
ndarray1 = np.arange(10, 20)
print(ndarray1)
ndarray2 = np.arange(10, 20, 2)
print(ndarray2)
print(ndarray2.shape)
[0 1 2 3 4 5 6 7 8 9]
[10 11 12 13 14 15 16 17 18 19]
[10 12 14 16 18]
(5,)
2.2 其他創(chuàng)建numpy數(shù)組的方式
- 使用zeros和zeros_like創(chuàng)建數(shù)組
用于創(chuàng)建數(shù)組,數(shù)組元素默認值是0. 注意:zeros_linke函數(shù)只是根據(jù)傳入的ndarray數(shù)組的shape來創(chuàng)建所有元素為0的數(shù)組综慎,并不是拷貝源數(shù)組中的數(shù)據(jù).
ndarray4 = np.zeros(10)
ndarray5 = np.zeros((3, 3))
ndarray6 = np.zeros_like(ndarray5) # 按照 ndarray5 的shape創(chuàng)建數(shù)組
# 打印數(shù)組元素類型
print("以下為數(shù)組類型:")
print('ndarray4:', type(ndarray4))
print('ndarray5:', type(ndarray5))
print('ndarray6:', type(ndarray6))
print("-------------")
print("以下為數(shù)組元素類型:")
print('ndarray4:', ndarray4.dtype)
print('ndarray5:', ndarray5.dtype)
print('ndarray6:', ndarray6.dtype)
print("-------------")
print("以下為數(shù)組形狀:")
print('ndarray4:', ndarray4.shape)
print('ndarray5:', ndarray5.shape)
print('ndarray6:', ndarray6.shape)
以下為數(shù)組類型:
ndarray4: <class 'numpy.ndarray'>
ndarray5: <class 'numpy.ndarray'>
ndarray6: <class 'numpy.ndarray'>
以下為數(shù)組元素類型:
ndarray4: float64
ndarray5: float64
ndarray6: float64
以下為數(shù)組形狀:
ndarray4: (10,)
ndarray5: (3, 3)
ndarray6: (3, 3)
- ones和ones_like創(chuàng)建數(shù)組
# 用于創(chuàng)建所有元素都為1的數(shù)組.ones_like用法同zeros_like用法.
# 創(chuàng)建數(shù)組涣仿,元素默認值是1
ndarray7 = np.ones(10)
print(ndarray7)
ndarray8 = np.ones((3, 3))
print(ndarray8)
ndarray9 = np.ones_like(ndarray8) # 按照 ndarray8 的shape創(chuàng)建數(shù)組
print(ndarray9)
[1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
[[1. 1. 1.]
[1. 1. 1.]
[1. 1. 1.]]
[[1. 1. 1.]
[1. 1. 1.]
[1. 1. 1.]]
- empty和empty_like創(chuàng)建數(shù)組
ndarray10 = np.empty(5)
ndarray11 = np.empty((2, 3))
ndarray12 = np.empty_like(ndarray11)
print(ndarray10)
print(ndarray11)
print(ndarray12)
[2.12199579e-314 6.36598737e-314 1.06099790e-313 1.48539705e-313
1.90979621e-313]
[[2.12199579e-314 6.36598737e-314 1.06099790e-313]
[1.48539705e-313 1.90979621e-313 2.33419537e-313]]
[[2.12199579e-314 6.36598737e-314 1.06099790e-313]
[1.48539705e-313 1.90979621e-313 2.33419537e-313]]
- eye創(chuàng)建對角矩陣數(shù)組
該函數(shù)用于創(chuàng)建一個N*N的矩陣,對角線為1,其余為0.
ndarray13 = np.eye(5)
print(ndarray13)
[[1. 0. 0. 0. 0.]
[0. 1. 0. 0. 0.]
[0. 0. 1. 0. 0.]
[0. 0. 0. 1. 0.]
[0. 0. 0. 0. 1.]]
- full創(chuàng)建數(shù)組
創(chuàng)建指定形狀的數(shù)組并填充相應元素
ndarray14 = np.full((3, 5), 666)
print(ndarray14)
[[666 666 666 666 666]
[666 666 666 666 666]
[666 666 666 666 666]]
3 ndarray的數(shù)據(jù)類型及索引
3.1 ndarry數(shù)據(jù)類型
3.1.1 dtype 數(shù)據(jù)類型
dtype(數(shù)據(jù)類型)是一個特殊的對象好港,它含有ndarray將一塊內(nèi)存解釋為特定數(shù)據(jù)類型所需的信息:
arr1 = np.array([1, 2, 3], dtype=np.float64)
arr2 = np.array([1, 2, 3], dtype=np.int32)
print(arr1.dtype)
print(arr2.dtype)
float64
int32
dtype是NumPy靈活交互其它系統(tǒng)的源泉之一愉镰。多數(shù)情況下,它們直接映射到相應的機器表示钧汹,這使得“讀寫磁盤上的二進制數(shù)據(jù)流”以及“集成低級語言代碼(如C丈探、Fortran)”等工作變得更加簡單。數(shù)值型dtype的命名方式相同:一個類型名(如float或int)拔莱,后面跟一個用于表示各元素位長的數(shù)字碗降。標準的雙精度浮點值(即Python中的float對象)需要占用8字節(jié)(即64位)。因此塘秦,該類型在NumPy中就記作float64
類型 | 類型代碼 | 說明 |
---|---|---|
int8,uint8 | i1,u1 | 有符號和無符號的8位(1個字節(jié)長度)整型 |
int16,uint16 | i2,u2 | 有符號和無符號的16位(2個字節(jié)長度)整型 |
int32,uint32 | i4,u4 | 有符號和無符號的32位(4個字節(jié)長度)整型 |
float16 | f2 | 半精度浮點數(shù) |
float32 | f4或f | 標準單精度浮點數(shù) |
float64 | f8或d | 雙精度浮點數(shù) |
bool | 讼渊? | 布爾類型 |
object | O | python對象類型 |
unicode | U | 固定長度的unicode類型,跟字符創(chuàng)定義方式一樣 |
這些都不是必須要記住的尊剔,需要了解時直接百度即可
- 通過ndarray的astype方法明確地將一個數(shù)組從一個dtype轉換成另一個dtype
- 整數(shù)轉化成浮點數(shù)
arr = np.array([1, 2, 3, 4, 5])
print(arr.dtype)
float_arr = arr.astype(np.float64)
print(float_arr.dtype)
int32
float64
??2. 浮點數(shù)轉化成整數(shù)(丟失精度)
arr = np.array([3.7, -1.2, -2.6, 0.5, 12.9, 10.1])
print(arr)
arr1 = arr.astype(np.int32)
print(arr1)
[ 3.7 -1.2 -2.6 0.5 12.9 10.1]
[ 3 -1 -2 0 12 10]
??3. 數(shù)字字符串轉化成數(shù)值類型
numericstrings = np.array(['1.25', '-9.6', '42'],dtype=np.string_)
print(numericstrings.astype(float))
[ 1.25 -9.6 42. ]
注意:使用numpy.string_類型時爪幻,一定要小心,因為NumPy的字符串數(shù)據(jù)是大小固定的赋兵,發(fā)生截取時笔咽,不會發(fā)出警告。pandas提供了更多非數(shù)值數(shù)據(jù)的便利的處理方法霹期。NumPy很聰明叶组,它會將python類型映射到等價的dtype上,比如這里的float會被自動轉化成float64
int_array = np.arange(10)
calibers = np.array([.22, .270, .357, .380, .44, .50], dtype=np.float64)
print(int_array.astype(calibers.dtype))
[0. 1. 2. 3. 4. 5. 6. 7. 8. 9.]
dtype會自動省略浮點數(shù)中小數(shù)點后的零
??4. 使用簡寫形式
empty_uint32 = np.empty((3,3), dtype='u4') # uint32可以寫為u4
print(empty_uint32)
[[ 39583911 0 4600192]
[ 0 4600192 0]
[3636330753 2046 0]]
注意:調(diào)用astype總會創(chuàng)建一個新的數(shù)組(一個數(shù)據(jù)的備份)历造,即使新的dtype與舊的dtype相同甩十。
3.1.2 Numpy數(shù)組運算
?? 數(shù)組很重要,因為它使你不用編寫循環(huán)即可對數(shù)據(jù)執(zhí)行批量運算吭产。NumPy用戶稱其為矢量化(vectorization)侣监。大小相等的數(shù)組之間的任何算術運算都會將運算應用到元素級:(不需要循環(huán)即可對數(shù)據(jù)進行批量運算,叫做矢量化運算. 不同形狀的數(shù)組之間的算數(shù)運算臣淤,叫做廣播,后面會介紹)
- 相同形狀的數(shù)組的運算
arr = np.array([[1., 2., 3.], [4., 5., 6.]])
print(arr)
print(arr * arr)
print(arr - arr)
[[1. 2. 3.]
[4. 5. 6.]]
[[ 1. 4. 9.]
[16. 25. 36.]]
[[0. 0. 0.]
[0. 0. 0.]]
- 數(shù)組與標量的運算
數(shù)組與標量的算術運算會將標量值傳播到各個元素
print(1 / arr)
print(arr ** 0.5)
[[1. 0.5 0.33333333]
[0.25 0.2 0.16666667]]
[[1. 1.41421356 1.73205081]
[2. 2.23606798 2.44948974]]
- 數(shù)組的比較
形狀相同的數(shù)組之間的比較會生成布爾值數(shù)組
arr2 = np.array([[0., 4., 1.], [7., 2., 12.]])
print(arr2)
print(arr2 > arr)
[[ 0. 4. 1.]
[ 7. 2. 12.]]
[[False True False]
[ True False True]]
- 數(shù)組的索引和切片
numpy數(shù)組的索引是一個內(nèi)容豐富的主題橄霉,因為選取數(shù)據(jù)子集或單個元素的方式有很多。一維數(shù)組很簡單邑蒋,從表面上看姓蜂,它們和python列表的功能差不多。所以主要看二維數(shù)組和三維數(shù)組:
import numpy as np
x = np.arange(10)
print(x)
X = np.arange(15).reshape((3,5))
print(X)
# 訪問x中索引是1的元素
print(x[1])
# 賦值 損失了精度医吊,截斷操作
x[1] = 3.64
print(x)
# 切片
print(x[1:4])
# 按照先行后列的訪問方式
print(X[1][4])
# 第二種寫法钱慢,推薦, 逗號前面是行索引卿堂,后面是列索引
print(X[1,4])
X[1,4] = 33
print(X)
# X的切片
print(X[:2, 2:4])
[0 1 2 3 4 5 6 7 8 9]
[[ 0 1 2 3 4]
[ 5 6 7 8 9]
[10 11 12 13 14]]
1
[0 3 2 3 4 5 6 7 8 9]
[3 2 3]
9
9
[[ 0 1 2 3 4]
[ 5 6 7 8 33]
[10 11 12 13 14]]
[[2 3]
[7 8]]
3.1.3 numpy的特殊之處
- 當把一個數(shù)字值賦值給一個切片時束莫,該值會自動傳播到整個選區(qū)懒棉。跟列表的區(qū)別在于,數(shù)組切片是原始數(shù)組的視圖览绿,這意味著數(shù)據(jù)不會被賦值策严,視圖上的任何修改都會直接反應到源數(shù)組上.
- 大家可能對此感到不解,由于Numpy被設計的目的是處理大數(shù)據(jù)挟裂,如果Numpy將數(shù)據(jù)復制來復制去的話會產(chǎn)生何等的性能和內(nèi)存問題.
- 如果要得到一個切片副本的話享钞,必須顯式進行復制操作.
# 切片賦值
x[3:6] = 12
print(x)
# 對切片的值進行修改,也會體現(xiàn)到原數(shù)組身上
arr_slice = x[3:6]
arr_slice[0] = 999
print(arr_slice)
arr_slice[:] =666
print(x)
# 如果你還是想要數(shù)組切片的拷貝而不是一份視圖的話诀蓉,可以進行如下操作
print(X[:2, 2:4].copy())
[ 0 3 2 12 12 12 6 7 8 9]
[999 12 12]
[ 0 3 2 666 666 666 6 7 8 9]
[[2 3]
[7 8]]
3.2 Fancy indexing花式索引
花式索引是一個NumPy術語栗竖,它指的是利用整數(shù)數(shù)組進行索引
arr = np.empty((8, 4))
for i in range(8):
arr[i] = i
print(arr)
[[0. 0. 0. 0.]
[1. 1. 1. 1.]
[2. 2. 2. 2.]
[3. 3. 3. 3.]
[4. 4. 4. 4.]
[5. 5. 5. 5.]
[6. 6. 6. 6.]
[7. 7. 7. 7.]]
# 為了以特定順序選取行子集,只需傳入一個用于指定順序的整數(shù)列表或ndarray即可
print(arr[[4, 3, 0, 6]])
[[4. 4. 4. 4.]
[3. 3. 3. 3.]
[0. 0. 0. 0.]
[6. 6. 6. 6.]]
# 這段代碼確實達到我們的要求了渠啤!使用負數(shù)索引將會從末尾開始選取行
print(arr[[-3, -5, -7]])
[[5. 5. 5. 5.]
[3. 3. 3. 3.]
[1. 1. 1. 1.]]
# 一次傳入多個索引數(shù)組會有一點特別狐肢。它返回的是一個一維數(shù)組,其中的元素對應各個索引元組
arr = np.arange(32).reshape((8, 4))
print(arr)
print()
print(arr[[1, 5, 7, 2], [0, 3, 1, 2]]) # 第一個索引中是行坐標沥曹,第二個索引中的是列坐標份名。相同位置的元素組成一個坐標,選出一個元素
[[ 0 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 29 30 31]][ 4 23 29 10]
?? 最終選出的是元素(1,0)妓美、(5,3)僵腺、(7,1)和(2,2)。無論數(shù)組是多少維的壶栋,花式索引總是一維的辰如。
?? 這個花式索引的行為可能會跟某些用戶的預期不一樣,選取矩陣的行列子集應該是矩形區(qū)域的形式才對贵试。下面是得到該結果的一個辦法:
print(arr[[1, 5, 7, 2]][:, [0, 3, 1, 2]])
[[ 4 7 5 6]
[20 23 21 22]
[28 31 29 30]
[ 8 11 9 10]]
注意:花式索引跟切片不一樣琉兜,它總是將數(shù)據(jù)復制到新數(shù)組中。對于新數(shù)組中數(shù)據(jù)的改變不會反映到原數(shù)組中
3.3 布爾型索引
?? 來看這樣一個例子毙玻,假設我們有一個用于存儲數(shù)據(jù)的數(shù)組以及一個存儲姓名的數(shù)組(含有重復項)豌蟋。在這里,我將使用numpy.random中的randn函數(shù)生成一些正態(tài)分布的隨機數(shù)據(jù):
names = np.array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'])
print(names)
print()
# 我將使用numpy.random中的randn函數(shù)生成一些正態(tài)分布的隨機數(shù)據(jù)
data = np.random.randn(7, 4)
print(data)
['Bob' 'Joe' 'Will' 'Bob' 'Will' 'Joe' 'Joe']
[[-2.33086753e-01 -2.11559329e-01 -5.68176123e-03 4.25333048e-01]
[ 3.51430509e-01 -3.75894745e-03 -1.50462755e+00 9.31211514e-03]
[ 4.09926614e-01 -7.18040329e-01 1.22509643e+00 8.95648381e-01]
[ 3.99166096e-01 -3.76927909e-01 1.71268889e-03 -1.23910399e+00]
[ 2.11765485e-01 -8.20546694e-01 4.44831659e-01 -1.78620834e+00]
[ 9.65591103e-01 -9.40774521e-01 4.76456319e-01 -9.68547600e-01]
[ 1.85897140e+00 3.81405447e-01 -7.36214596e-01 -1.89778617e+00]]
假設每個名字都對應data數(shù)組中的一行桑滩,而我們想要選出對應于名字"Bob"的所有行梧疲。跟算術運算一樣,數(shù)組的比較運算(如==)也是矢量化的运准。因此往声,對names和字符串"Bob"的比較運算將會產(chǎn)生一個布爾型數(shù)組:
print(names == 'Bob')
[ True False False True False False False]
這個布爾型數(shù)組可用于數(shù)組索引:
print(data[names == 'Bob']) # 實際上選的是第1行和第4行的篩選
[[-0.23308675 -0.21155933 -0.00568176 0.42533305]
[ 0.3991661 -0.37692791 0.00171269 -1.23910399]]
# 如果布爾型數(shù)組的長度不對,布爾型選擇就會出錯戳吝,因此一定要小心。
# 下面的例子贯涎,我選取了names == 'Bob'的行听哭,并索引了列:
print(data[names == 'Bob', 2:])
[[-0.00568176 0.42533305]
[ 0.00171269 -1.23910399]]
# 要選擇除"Bob"以外的其他值,既可以使用不等于符號(!=),也可以通過~對條件進行否定:
print(names != 'Bob')
print(data[~(names == 'Bob')])
[False True True False True True True]
[[ 0.35143051 -0.00375895 -1.50462755 0.00931212]
[ 0.40992661 -0.71804033 1.22509643 0.89564838]
[ 0.21176548 -0.82054669 0.44483166 -1.78620834]
[ 0.9655911 -0.94077452 0.47645632 -0.9685476 ]
[ 1.8589714 0.38140545 -0.7362146 -1.89778617]]
3.3.1 使用布爾類型數(shù)組設置值是一種經(jīng)常用到的手段
import numpy as np
ndarray1 = np.arange(5)
print(ndarray1)
ndarray2 = np.arange(16).reshape((4, 4))
print(ndarray2)
names = np.array(['aaa', 'bbb', 'ccc', 'ddd'])
print(names)
# 將數(shù)組ndarray1中所有大于2的元素設置成8
ndarray1[ndarray1 > 2] = 8
print(ndarray1)
# 將ndarray2的aaa這一行所有的元素設置為0
ndarray2[names == 'aaa'] = 0
# 將ndarray2的bbb這一行2位置往后所有的元素設置為1
ndarray2[names == 'bbb', 2:] = 1
print(ndarray2)
# 將ndarray2的ccc ddd這2行所有的元素設置為2
ndarray2[(names == 'ccc') | (names == 'ddd')] = 2
print(ndarray2)
[0 1 2 3 4]
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]
[12 13 14 15]]
['aaa' 'bbb' 'ccc' 'ddd']
[0 1 2 8 8]
[[ 0 0 0 0]
[ 4 5 1 1]
[ 8 9 10 11]
[12 13 14 15]]
[[0 0 0 0]
[4 5 1 1]
[2 2 2 2]
[2 2 2 2]]
4 數(shù)組函數(shù)
4.1 通用函數(shù):快速的元素級數(shù)組函數(shù)
?? 通用函數(shù)(即universal function)是一種對ndarray中的數(shù)據(jù)執(zhí)行元素級運算的函數(shù)陆盘。你可以將其看做簡單函數(shù)(接受一個或多個標量值普筹,并產(chǎn)生一個或多個標量值)的矢量化包裝器。 許多ufunc都是簡單的元素級變體隘马,如sqrt和exp:
- 常用的一元ufunc:
函數(shù) | 說明 |
---|---|
abs | 計算證書太防、浮點數(shù)的絕對值 |
aqrt | 計算各元素的平方根。相當于arr ** 0.5 |
square | 計算各元素的平方酸员。相當于arr ** 2 |
sign | 計算各元素的正負號蜒车,1(正數(shù))、0(零)幔嗦、-1(負數(shù)) |
cell | 計算各元素的celling值酿愧,即大于該值的最小整數(shù) |
floor | 計算各元素的floor值,即小于該值的最大整數(shù) |
rint | 將各元素值四舍五入到最近的整數(shù)邀泉,保留dtype |
modf | 將數(shù)組的小數(shù)和整數(shù)部分以兩個獨立數(shù)組的形式返回 |
isnan | 返回一個表示“那些是NaN(這不是一個數(shù)字)”的布爾類型數(shù)組 |
import numpy as np
ndarray1 = np.array([3.5, 1.7, 2.2, -7.8, np.nan, 4.6, -3.4])
print(ndarray1)
# abs 計算整數(shù)嬉挡、浮點數(shù)的絕對值。
print(np.abs(ndarray1))
# square計算各元素的平方汇恤。相當于arr ** 2
print(np.square(ndarray1))
# sign 計算各元素的正負號,1(正數(shù))庞钢、0(零)、-1(負數(shù))
print(np.sign(ndarray1))
# ceil 計算各元素的celling值因谎,即大于該值的最小整數(shù)基括。
print(np.ceil(ndarray1))
# floor 計算各元素的floor值,即小于等于該值的最大整數(shù)蓝角。
print(np.floor(ndarray1))
# rint 將各元素值四舍五入到最近的整數(shù)阱穗,保留dtype
print(np.rint(ndarray1))
# isnan 返回一個表示“那些是NaN(這不是一個數(shù)字)”的布爾類型數(shù)組.
print(np.isnan(ndarray1))
[ 3.5 1.7 2.2 -7.8 nan 4.6 -3.4]
[3.5 1.7 2.2 7.8 nan 4.6 3.4]
[12.25 2.89 4.84 60.84 nan 21.16 11.56]
[ 1. 1. 1. -1. nan 1. -1.]
[ 4. 2. 3. -7. nan 5. -3.]
[ 3. 1. 2. -8. nan 4. -4.]
[ 4. 2. 2. -8. nan 5. -3.]
[False False False False True False False]
- 常用的二元ufunc:
函數(shù) | 說明 |
---|---|
add | 將數(shù)組中對應的元素相加 |
subtract | 從第一個數(shù)組中減去第二個數(shù)組中的元素 |
multiply | 數(shù)組元素相乘 |
divide、floor_divide | 除法使鹅、向下整除法(丟棄余數(shù)) |
power | 對第一個數(shù)組中元素A揪阶,根據(jù)第二數(shù)組中的相應元素B,計算A的B次方 |
maximum患朱、fmax | 元素級的最大值計算鲁僚,fmax將忽略NaN |
minimum、fmin | 元素級的最小值計算裁厅,fmin將忽略NaN |
mod | 元素級的求模運算 |
copysign | 將第二個數(shù)組中的值的符號賦值給第一個數(shù)組中的值 |
greater冰沙、greater_equal | 執(zhí)行元素級的運算比較,最終產(chǎn)生布爾類型數(shù)組 |
ndarray2 = np.random.randint(1, 20, (4, 5))
ndarray3 = np.random.randint(-10, 10, (4, 5))
ndarray3 = np.where(ndarray3 == 0, 1, ndarray3)
print(ndarray2)
print(ndarray3)
# add 將數(shù)組中對應的元素相加.
print(np.add(ndarray2, ndarray3))
# subtract 從第一個數(shù)組中減去第二個數(shù)組中的元素.
print(np.subtract(ndarray2, ndarray3))
# maximum执虹、fmax 從兩個數(shù)組中取出最大值拓挥。fmax將忽略NaN
print(np.maximum(ndarray2, ndarray3))
# mod 元素級的求模計算.
print(np.mod(ndarray2, ndarray3))
# copysign 將第二個數(shù)組中的值的符號復制給第一個數(shù)組中的值.
print(np.copysign(ndarray2, ndarray3))
# greater、greater_equal 執(zhí)行元素級的運算比較袋励,最終產(chǎn)生布爾類型數(shù)組侥啤。
print(np.greater(ndarray2, ndarray3))
[[ 5 4 4 9 13]
[ 8 19 19 15 13]
[16 11 1 9 15]
[11 8 13 14 8]]
[[-7 -5 -5 1 3]
[ 5 -5 -5 -7 -1]
[ 8 5 7 -7 1]
[-7 1 6 5 -4]]
[[-2 -1 -1 10 16]
[13 14 14 8 12]
[24 16 8 2 16]
[ 4 9 19 19 4]]
[[12 9 9 8 10]
[ 3 24 24 22 14]
[ 8 6 -6 16 14]
[18 7 7 9 12]]
[[ 5 4 4 9 13]
[ 8 19 19 15 13]
[16 11 7 9 15]
[11 8 13 14 8]]
[[-2 -1 -1 0 1]
[ 3 -1 -1 -6 0]
[ 0 1 1 -5 0]
[-3 0 1 4 0]]
[[ -5. -4. -4. 9. 13.]
[ 8. -19. -19. -15. -13.]
[ 16. 11. 1. -9. 15.]
[-11. 8. 13. 14. -8.]]
[[ True True True True True]
[ True True True True True]
[ True True False True True]
[ True True True True True]]
4.2 數(shù)組統(tǒng)計函數(shù)
?? 可以通過數(shù)組上的一組數(shù)學函數(shù)對整個數(shù)組或某些數(shù)據(jù)進行統(tǒng)計計算当叭。 基本的數(shù)組統(tǒng)計方法:
方法 | 說明 |
---|---|
mean | 算術平均數(shù)。零長度的數(shù)組的mean為NaN |
sum | 所有元素之和 |
max盖灸、min | 所有元素的最大值蚁鳖、所有元素的最小值 |
std、var | 所有元素的標準差赁炎、所有元素的方差 |
argmax/argmin | 最大值的下標索引值醉箕、最小值的下標索引值 |
cumsum/cumprod | 所有元素的累計和、所有元素的累計積 |
多維數(shù)組默認統(tǒng)計全部維度徙垫,axis參數(shù)可以按指定軸心統(tǒng)計讥裤,值為0則按列統(tǒng)計,值為1則按行統(tǒng)計松邪。
import numpy as np
ndarray1 = np.random.randint(1, 10, (4, 5))
print(ndarray1)
[[2 1 8 1 6]
[7 7 3 6 7]
[1 2 6 1 7]
[3 3 1 5 4]]
- sum求元素和
# 0-列 1-行
# sum-計算所有元素和
print(np.sum(ndarray1))
# sum-計算每一列的元素和
print(np.sum(ndarray1, axis=0))
# sum-計算每一行的元素和
print(np.sum(ndarray1, axis=1))
81
[13 13 18 13 24]
[18 30 17 16]
- armax求最大值索引
# argmax-默認情況下按照一維數(shù)組索引
print(np.argmax(ndarray1))
# argmax-統(tǒng)計每一列最大
print(np.argmax(ndarray1, axis=0))
# argmax-統(tǒng)計每一行最大
print(np.argmax(ndarray1, axis=1))
2
[1 1 0 1 1]
[2 0 4 3]
- mean求平均數(shù)
# mean-求所有元素的平均值
print(np.mean(ndarray1))
# mean-求每一列元素的平均值
print(np.mean(ndarray1, axis=0))
# mean-求每一行元素的平均值
print(np.mean(ndarray1, axis=1))
4.05
[3.25 3.25 4.5 3.25 6. ]
[3.6 6. 3.4 3.2]
- cumsum求元素累計和
# cumsum-前面元素的累計和
print(np.cumsum(ndarray1))
# cumsum-每一列元素的累計和
print(np.cumsum(ndarray1, axis=0))
# cumsum-每一行元素的累計和
print(np.cumsum(ndarray1, axis=1))
[ 2 3 11 12 18 25 32 35 41 48 49 51 57 58 65 68 71 72 77 81]
[[ 2 1 8 1 6]
[ 9 8 11 7 13]
[10 10 17 8 20]
[13 13 18 13 24]]
[[ 2 3 11 12 18]
[ 7 14 17 23 30]
[ 1 3 9 10 17]
[ 3 6 7 12 16]]
4.3 all和any函數(shù)
import numpy as np
# 判斷兩個數(shù)組元素是否相等
ndarray1 = np.arange(6).reshape((2, 3))
ndarray2 = np.arange(6).reshape((2, 3))
print(ndarray1)
print(ndarray2)
ndarray3 = np.array([[ 0, 1, 2], [ 8, 9, 10]])
print(ndarray3)
print((ndarray1 == ndarray2).all())
print((ndarray1 == ndarray3).all())
print((ndarray1 == ndarray3).any())
[[0 1 2]
[3 4 5]]
[[0 1 2]
[3 4 5]]
[[ 0 1 2]
[ 8 9 10]]
True
False
True
4.4 添加和刪除函數(shù)
方法 | 描述 |
---|---|
delete | 返回一個新的數(shù)組坞琴,該數(shù)組具有沿軸刪除的子數(shù)組 |
insert(arr,obj,values[,axis]) | 沿給定軸插入值 |
append(arr,values[,axis]) | 將值添加到數(shù)組的末尾 |
resize(a,new_shape) | 返回具有指定形狀的新數(shù)組 |
concatenate((a1,a2,...),axis=0) | 沿現(xiàn)有軸合并多個數(shù)組 |
注意:reshape:有返回值,即不對原始多維數(shù)組進行修改逗抑; resize:無返回值剧辐,即會對原始多維數(shù)組進行修改;
import numpy as np
ndarray1 = np.arange(4)
ndarray2 = np.arange(4)
print(ndarray2)
ndarray3 = np.arange(12).reshape((3, 4))
print(ndarray3)
[0 1 2 3]
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
- delete刪除一行或者一列數(shù)組元素
ndarray5 = np.arange(20).reshape((4, 5))
print(ndarray5)
# 刪除第0行元素
print(np.delete(ndarray5, 0, axis=0))
# 刪除第2列元素
print(np.delete(ndarray5, 1, axis=1))
# 刪除第0邮府、2荧关、3列元素
print(np.delete(ndarray5, [0, 2, 3], axis=1))
# 使用np.s_[::]創(chuàng)建切片對象
# 刪除1、2列元素
print(np.delete(ndarray5, np.s_[1:3], axis=1))
[[ 0 1 2 3 4]
[ 5 6 7 8 9]
[10 11 12 13 14]
[15 16 17 18 19]]
[[ 5 6 7 8 9]
[10 11 12 13 14]
[15 16 17 18 19]]
[[ 0 2 3 4]
[ 5 7 8 9]
[10 12 13 14]
[15 17 18 19]]
[[ 1 4]
[ 6 9]
[11 14]
[16 19]]
[[ 0 3 4]
[ 5 8 9]
[10 13 14]
[15 18 19]]
- append數(shù)組中追加元素
# 數(shù)組追加一個數(shù)值元素
print(np.append(ndarray1, 100))
# 在一維數(shù)組后追加一維數(shù)組
print(np.append(ndarray1, ndarray2))
# 在二維數(shù)組后追加標量元素
print(np.append(ndarray3, 100))
# append總是返回一維數(shù)組
print(np.append(ndarray1, ndarray3))
[ 0 1 2 3 100]
[0 1 2 3 0 1 2 3]
[ 0 1 2 3 4 5 6 7 8 9 10 11 100]
[ 0 1 2 3 0 1 2 3 4 5 6 7 8 9 10 11]
- insert插入元素
# 在第2個位置插入元素100
ndarray6 = np.arange(4)
print(ndarray6)
print(np.insert(ndarray6, 1, 100))
# 在第3個位置插入兩個元素10褂傀、20
print(np.insert(ndarray6, 2, [10, 20]))
# 在第2行插入一行元素
print(np.insert(ndarray6, 1, np.array([100, 200, 300, 400]), axis=0)) # ndarray6是一維數(shù)組所以不會添加在第一行下面忍啤,而是會添加在相應位置。結果還是一維數(shù)組
# 在第3列插入一列元素
ndarray7 = np.arange(12).reshape((3, 4))
print(np.insert(ndarray7, 2, np.array([100, 200, 300]), axis=1))
[0 1 2 3]
[ 0 100 1 2 3]
[ 0 1 10 20 2 3]
[ 0 100 200 300 400 1 2 3]
[[ 0 1 100 2 3]
[ 4 5 200 6 7]
[ 8 9 300 10 11]]
- concatenate合并兩個數(shù)組元素
ndarray4 = np.arange(12).reshape((3, 4))
print(ndarray4)
# 合并兩個一維數(shù)組
print(np.concatenate((ndarray1, ndarray2)))
# 合并兩個二維數(shù)組(列)
print(np.concatenate((ndarray3, ndarray4), axis=0))
# 合并兩個二維數(shù)組(行)
print(np.concatenate((ndarray3, ndarray4), axis=1))
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
[0 1 2 3 0 1 2 3]
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]
[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
[[ 0 1 2 3 0 1 2 3]
[ 4 5 6 7 4 5 6 7]
[ 8 9 10 11 8 9 10 11]]
5 唯一化和集合函數(shù)
?? NumPy提供了一些針對一維ndarray的基本集合運算仙辟。最常用的就是np.unique了同波,它用于找出數(shù)組中的唯一值并返回已排序的結果。
方法 | 說明 |
---|---|
unique(x) | 計算x中惟一的元素叠国,并返回有序結果 |
intersect1d(x,y) | 計算x和y中的公共元素未檩,并返回有序結果 |
union1d(x,y) | 計算x和y的并集,并返回有序結果 |
in1d(x,y) | 得到一個表示“x的元素是否包含于y”的布爾型數(shù)組 |
setdiff1d(x,y) | 集合的差粟焊,即元素在x中且不在y中 |
- 唯一化
import numpy as np
names = np.array(['aaa', 'bbb', 'ccc', 'aaa', 'ddd', 'eee', 'ccc'])
ndarray1 = np.random.randint(1, 5, 10)
ndarray2 = np.random.randint(1, 5, (3, 4))
print(ndarray1)
print(ndarray2)
print(np.unique(names))
print(np.unique(ndarray1))
print(np.unique(ndarray2))
[2 1 4 1 4 2 4 1 2 4]
[[3 4 2 3]
[2 4 4 2]
[3 4 4 1]]
['aaa' 'bbb' 'ccc' 'ddd' 'eee']
[1 2 4]
[1 2 3 4]
- 計算兩個數(shù)組交集
ndarray3 = np.arange(1, 10)
ndarray4 = np.arange(5, 15)
print(ndarray3)
print(ndarray4)
print(np.intersect1d(ndarray3, ndarray4))
[1 2 3 4 5 6 7 8 9]
[ 5 6 7 8 9 10 11 12 13 14]
[5 6 7 8 9]
- 計算兩個數(shù)組并集
ndarray5 = np.arange(1, 10)
ndarray6 = np.arange(5, 15)
print(ndarray5)
print(ndarray6)
print(np.union1d(ndarray5, ndarray6))
[1 2 3 4 5 6 7 8 9]
[ 5 6 7 8 9 10 11 12 13 14]
[ 1 2 3 4 5 6 7 8 9 10 11 12 13 14]
- 數(shù)組中的元素是否在另一個數(shù)組中存在
ndarray7 = np.arange(1, 6)
ndarray8 = np.arange(3, 8)
print(ndarray7)
print(ndarray8)
print(np.in1d(ndarray7, ndarray8))
[1 2 3 4 5]
[3 4 5 6 7]
[False False True True True]
- 計算兩個數(shù)組的差集
ndarray9 = np.arange(1, 6)
ndarray10 = np.arange(3, 8)
print(ndarray9)
print(ndarray10)
print(np.setdiff1d(ndarray9, ndarray10))
[1 2 3 4 5]
[3 4 5 6 7]
[1 2]
5.1 隨機數(shù)生成函數(shù)
?? numpy.random模塊對python內(nèi)置的random進行了補充冤狡。我們使用numpy.random可以很方便根據(jù)需要產(chǎn)生大量樣本值。而python內(nèi)置的random模塊則一次生成一個樣本值.
參數(shù) | 解釋 |
---|---|
.rand(d0,d1,...,dn) | 創(chuàng)建d0-dn維度的均勻分布的隨機數(shù)數(shù)組项棠,浮點數(shù)悲雳,范圍是0-1 |
.randn(d0,d1,...,dn) | 創(chuàng)建d0-dn維度的標準正態(tài)分布的隨機數(shù)數(shù)組,浮點數(shù)香追,平均數(shù)是0合瓢,標準差是1 |
.randint(low,high,(shape)) | 從給定上下限范圍選取隨機數(shù)整數(shù),范圍是low-high透典,形狀是shape |
.uniform(low,high,(size)) | 產(chǎn)生具有均勻分布的數(shù)組晴楔,low起始值迁央,high結束值,size形狀 |
.normal(loc,scale,(size)) | 從指定正態(tài)分布中隨機抽取樣本滥崩,分布中心是loc(概率分布的均值),標準差是scale讹语,形狀是size |
.seed(s) | 隨機數(shù)種子钙皮,s是給定的種子值。因為計算機生成的是偽隨機數(shù)顽决,所以通過設定相同的隨機數(shù)種子短条,可以每次生成相同的隨機數(shù) |
下圖簡單回憶一下均勻分布和正態(tài)分布
函數(shù) | 說明 |
---|---|
permutation | 如果給的是數(shù)字,則生成指定個數(shù)隨機數(shù)才菠;如果給的是數(shù)組茸时,則打亂數(shù)組返回(有返回值,原有數(shù)組順序不變) |
shuffle | 打亂一個序列的原有順序(無返回值赋访,原有數(shù)組順序打亂) |
randint | 從指定的上下限隨機選取整數(shù) |
import numpy as np
ndarray1 = np.arange(10)
print(np.random.permutation(5))
print(np.random.permutation(ndarray1))
np.random.shuffle(ndarray1)
print(ndarray1)
print(np.random.randint(10, 20))
print(np.random.randint(10, 20, 20))
print(np.random.randint(10, 20, (3, 4)))
[3 2 1 4 0]
[4 0 6 3 1 7 2 8 5 9]
[8 3 0 4 9 6 2 5 1 7]
15
[14 17 18 15 15 16 12 19 10 17 10 18 10 13 19 10 13 18 13 12]
[[19 19 19 18]
[16 13 13 15]
[17 11 17 13]]
6 數(shù)組排序函數(shù)
- 對一維數(shù)組排序
import numpy as np
ndarray1 = np.random.randint(1, 10, (1, 5))
print(ndarray1)
ndarray1.sort()
print(ndarray1)
[[7 5 1 4 1]]
[[1 1 4 5 7]]
- 對二維數(shù)組排序
ndarray2 = np.random.randint(1, 10, (5, 5))
print(ndarray2)
# 對每行數(shù)據(jù)進行排序
ndarray2.sort()
print(ndarray2)
# 對每列數(shù)據(jù)進行排序
ndarray2.sort(axis=0)
print(ndarray2)
ndarray3 = np.sort(ndarray2) # 返回排序副本可都,源數(shù)據(jù)不變
print(ndarray3)
[[6 6 5 6 4]
[8 5 2 2 1]
[2 1 5 3 6]
[3 5 4 5 9]
[7 5 8 4 3]]
[[4 5 6 6 6]
[1 2 2 5 8]
[1 2 3 5 6]
[3 4 5 5 9]
[3 4 5 7 8]]
[[1 2 2 5 6]
[1 2 3 5 6]
[3 4 5 5 8]
[3 4 5 6 8]
[4 5 6 7 9]]
[[1 2 2 5 6]
[1 2 3 5 6]
[3 4 5 5 8]
[3 4 5 6 8]
[4 5 6 7 9]]
- argsort函數(shù)(很重要) argsort函數(shù)返回的是數(shù)組值從小到大的索引值
import numpy as np
x = np.arange(10)
print(x)
np.random.shuffle(x)
print(x)
print(np.argsort(x))
[0 1 2 3 4 5 6 7 8 9]
[2 9 7 6 8 3 0 1 5 4]
[6 7 0 5 9 8 3 2 4 1]
7 廣播
?? 廣播(broadcasting)指的是不同形狀的數(shù)組之間的算術運算的執(zhí)行方式。它是一種非常強大的功能蚓耽,但也容易令人誤解渠牲,即使是經(jīng)驗豐富的老手也是如此。將標量值跟數(shù)組合并時就會發(fā)生最簡單的廣播:
import numpy as np
arr = np.arange(5)
print(arr)
print(arr * 4)
[0 1 2 3 4]
[ 0 4 8 12 16]
這里我們說:在這個乘法運算中步悠,標量值4被廣播到了其他所有的元素上签杈。
?? 看一個例子,我們可以通過減去列平均值的方式對數(shù)組的每一列進行距平化處理鼎兽。這個問題解決起來非常簡單:
arr = np.random.randn(4, 3)
print(arr)
print(arr.mean(0))
demeaned = arr - arr.mean(0)
print(demeaned)
print(demeaned.mean(0))
[[ 0.80034723 1.32912842 -0.68108329]
[ 0.36787938 1.46662177 -0.0787044 ]
[ 0.20019622 -0.52519415 -1.22136111]
[ 0.00911344 0.36198295 -0.80211758]]
[ 0.34438407 0.65813475 -0.69581659]
[[ 0.45596316 0.67099367 0.0147333 ]
[ 0.02349531 0.80848702 0.6171122 ]
[-0.14418785 -1.18332889 -0.52554451]
[-0.33527063 -0.2961518 -0.10630099]]
[ 2.77555756e-17 -4.16333634e-17 8.32667268e-17]
下圖形象地展示了該過程答姥。用廣播的方式對行進行距平化處理會稍微麻煩一些。幸運的是谚咬,只要遵循一定的規(guī)則鹦付,低維度的值是可以被廣播到數(shù)組的任意維度的(比如對二維數(shù)組各列減去行平均值)。
畫張圖并想想廣播的原則序宦。再來看一下最后那個例子睁壁,假設你希望對各行減去那個平均值。由于arr.mean(0)的長度為3互捌,所以它可以在0軸向上進行廣播:因為arr的后緣維度是3潘明,所以它們是兼容的。根據(jù)該原則秕噪,要在1軸向上做減法(即各行減去行平均值)钳降,較小的那個數(shù)組的形狀必須是(4,1):
print(arr)
row_means = arr.mean(1)
print(row_means)
print(row_means.shape)
print(row_means.reshape((4, 1)))
demeaned = arr - row_means.reshape((4, 1))
print(demeaned)
print(demeaned.mean(1))
[[-1.09267495 0.26367303 -1.62088787]
[-0.7179292 0.70332572 -1.02413652]
[-0.31145341 0.12550098 0.78108721]
[ 1.76536402 -0.06664222 0.3858461 ]]
[-0.81662993 -0.34624667 0.19837826 0.69485597]
(4,)
[[-0.81662993]
[-0.34624667]
[ 0.19837826]
[ 0.69485597]]
[[-0.27604502 1.08030296 -0.80425794]
[-0.37168253 1.04957238 -0.67788985]
[-0.50983167 -0.07287728 0.58270895]
[ 1.07050805 -0.76149819 -0.30900986]]
[ 0.00000000e+00 3.70074342e-17 -3.70074342e-17 1.85037171e-17]
- 下圖說明了該運算的過程
下圖展示了另外一種情況,這次是在一個三維數(shù)組上沿0軸向加上一個二維數(shù)組腌巾。