使用Python进行科学计算:NumPy入门
編程派微信號(hào):codingpy
本文由?Python 翻譯組?最新翻譯出品,原作者為?Jamal Moir,譯者為?cystone,并由編程派作者?EarlGrey?校對(duì)。這是使用 Python 進(jìn)行科學(xué)計(jì)算的系列文章,上一篇可點(diǎn)此查看:Matplotlib 快速入門。
譯者簡(jiǎn)介:cystone, 成都信息工程大學(xué),計(jì)算機(jī)學(xué)院學(xué)生。擅長(zhǎng)領(lǐng)域:圖像處理,機(jī)器學(xué)習(xí)。
你可以用 NumPy 做很多有趣的事情。
NumPy 是一個(gè)運(yùn)行速度非常快的數(shù)學(xué)庫(kù),主要用于數(shù)組計(jì)算。它可以讓你在 Python 中使用向量和數(shù)學(xué)矩陣,以及許多用 C 語(yǔ)言實(shí)現(xiàn)的底層函數(shù),你還可以體驗(yàn)到從未在原生 Python 上體驗(yàn)過(guò)的運(yùn)行速度。
NumPy 是 Python 在科學(xué)計(jì)算領(lǐng)域取得成功的關(guān)鍵之一,如果你想通過(guò) Python 學(xué)習(xí)數(shù)據(jù)科學(xué)或者機(jī)器學(xué)習(xí),就必須學(xué)習(xí) NumPy。我認(rèn)為 NumPy 的功能很強(qiáng)大,而且入門也不難。
數(shù)組基礎(chǔ)
創(chuàng)建數(shù)組
NumPy 的核心是數(shù)組(arrays)。具體來(lái)說(shuō)是多維數(shù)組(ndarrays),但是我們不用管這些。通過(guò)這些數(shù)組,我們能以閃電般的速度使用像向量和數(shù)學(xué)矩陣之類的功能。趕緊撿起你的線性代數(shù)吧!(只是開玩笑,其實(shí)并不需要很多復(fù)雜的數(shù)學(xué)知識(shí))
# 1D Arraya = np.array([0, 1, 2, 3, 4]) b = np.array((0, 1, 2, 3, 4)) c = np.arange(5) d = np.linspace(0, 2*np.pi, 5)print(a) # >>>[0 1 2 3 4]
print(b) # >>>[0 1 2 3 4]
print(c) # >>>[0 1 2 3 4]
print(d) # >>>[ 0. ? ? ? ? ?1.57079633 ?3.14159265 ?4.71238898 ?6.28318531]
print(a[3]) # >>>3
上邊的代碼展示了創(chuàng)建數(shù)組的四種不同方式。最基本的方式是傳遞一個(gè)序列給 NumPy 的 array() 函數(shù);你可以傳給它任意的序列,不僅僅是我們常見(jiàn)的列表之類的。
注意,當(dāng)輸出的數(shù)組中的數(shù)值長(zhǎng)度不一樣的時(shí)候,它會(huì)自動(dòng)對(duì)齊。這在查看矩陣的時(shí)候很有用。數(shù)組的索引和 Python 中的列表或其他序列很像。你也可以對(duì)它們使用切片,這里我不再演示一維數(shù)組的切片,如果你想知道更多關(guān)于切片的信息,查看這篇文章。
上邊數(shù)組的例子給你展示了如何在 NumPy 中表示向量,接下來(lái)我將帶你們領(lǐng)略一下怎么表示矩陣和多維數(shù)組。
# MD Array,a = np.array([[11, 12, 13, 14, 15],[16, 17, 18, 19, 20],[21, 22, 23, 24, 25],[26, 27, 28 ,29, 30],[31, 32, 33, 34, 35]])print(a[2,4]) # >>>25
通過(guò)給 array() 函數(shù)傳遞一個(gè)列表的列表(或者是一個(gè)序列的序列),可以創(chuàng)建二維數(shù)組。如果我們想要一個(gè)三維數(shù)組,那我們就傳遞一個(gè)列表的列表的列表,四維數(shù)組就是列表的列表的列表的列表,以此類推。
注意二維數(shù)組是如何成行成列排布的(在我們的朋友—空格的幫助下)。如果要索引一個(gè)二維數(shù)組,只需要引用相應(yīng)的行數(shù)和列數(shù)即可。
背后的數(shù)學(xué)知識(shí)
為了更好的理解這些,我們需要來(lái)看一下什么是向量和矩陣。
向量是一個(gè)有方向和大小的量,通常用來(lái)表示速度、加速度和動(dòng)量等。向量能以多種方式書寫,但是我們最有用的方式是把它們寫在有 n 個(gè)元素的元組里邊,比如(1, 4, 6, 9)。這就是它們?cè)?NumPy 中的表示方式。
矩陣和向量很像,除了它是由行和列組成的;更像一個(gè)網(wǎng)格(grid)。矩陣中的數(shù)值可以用它們所在的行和列來(lái)表示。在 NumPy 中,可以像我們前面所做的那樣,通過(guò)傳遞序列的序列來(lái)創(chuàng)建數(shù)組。
多維數(shù)組切片
多維數(shù)組切片比一維數(shù)組要復(fù)雜一點(diǎn),同時(shí)它也是你在用 NumPy 的時(shí)候經(jīng)常會(huì)用到的。
# MD slicingprint(a[0, 1:4]) # >>>[12 13 14]
print(a[1:4, 0]) # >>>[16 21 26]
print(a[::2,::2]) # >>>[[11 13 15]# ? ? [21 23 25]# ? ? [31 33 35]]
print(a[:, 1]) # >>>[12 17 22 27 32]
就像你看到的一樣,多維數(shù)組切片就是要分別在每個(gè)維度上切片,并用逗號(hào)隔開。在二維數(shù)組中,第一個(gè)切片的含義是對(duì)行切片,第二個(gè)切片的含義是對(duì)列切片。
值得注意的是,你通過(guò)輸入數(shù)字來(lái)指定行和列。上邊第一個(gè)例子是從數(shù)組中選擇第 0 行。(注:原文為第 0 列,應(yīng)該是作者筆誤)
下邊的這幅圖闡明了上邊切片的例子的含義。
數(shù)組屬性
在使用 NumPy 時(shí),你會(huì)想知道數(shù)組的某些信息。很幸運(yùn),在這個(gè)包里邊包含了很多便捷的方法,可以給你想要的信息。
# Array propertiesa = np.array([[11, 12, 13, 14, 15],[16, 17, 18, 19, 20],[21, 22, 23, 24, 25],[26, 27, 28 ,29, 30],[31, 32, 33, 34, 35]])print(type(a)) # >>><class 'numpy.ndarray'>
print(a.dtype) # >>>int64
print(a.size) # >>>25
print(a.shape) # >>>(5, 5)
print(a.itemsize) # >>>8
print(a.ndim) # >>>2
print(a.nbytes) # >>>200
如你所看,在上邊的代碼中 NumPy 的數(shù)組其實(shí)被稱為 ndarray。我不知道為什么它被稱為 ndarray,如果有人知道請(qǐng)?jiān)谙逻吜粞?#xff01;我猜測(cè)它是表示 n 維數(shù)組(n dimensional array)。
數(shù)組的形狀(shape)是指它有多少行和列,上邊的數(shù)組有五行五列,所以他的形狀是(5,5)。
‘itemsize’ 屬性是每一個(gè)條目所占的字節(jié)。這個(gè)數(shù)組的數(shù)據(jù)類型是 int64,一個(gè) int64 的大小是 64 比特,8 比特為 1 字節(jié),64 除以 8 就得到了它的字節(jié)數(shù),8 字節(jié)。
‘ndim’ 屬性是指數(shù)組有多少維。這個(gè)數(shù)組有二維。但是,比如說(shuō)向量,只有一維。
‘nbytes’ 屬性表示這個(gè)數(shù)組中所有元素占用的字節(jié)數(shù)。你應(yīng)該注意,這個(gè)數(shù)值并沒(méi)有把額外的空間計(jì)算進(jìn)去,因此實(shí)際上這個(gè)數(shù)組占用的空間會(huì)比這個(gè)值大點(diǎn)。
使用數(shù)組
基本操作符
僅僅會(huì)賦值、取值和得到一些屬性是不能滿足你的需求的,有時(shí)候你還需要做一些數(shù)學(xué)運(yùn)算。你可以利用基本的操作符實(shí)現(xiàn)這些,比如 +, -, /,等等。
# Basic Operatorsa = np.arange(25) a = a.reshape((5, 5))b = np.array([10, 62, 1, 14, 2, 56, 79, 2, 1, 45,
? ? ? ? ? ? ? ? ? ? ?4, 92, 5, 55, 63, 43, 35, 6, 53, 24,
? ? ? ? ? ? ?? ? ? ? 56, 3, 56, 44, 78]) b = b.reshape((5,5))print(a + b) print(a - b) print(a * b) print(a / b) print(a ** 2) print(a < b)
print(a > b)print(a.dot(b))
除了 dot() 之外,這些操作符都是對(duì)數(shù)組進(jìn)行逐元素運(yùn)算。比如 (a, b, c) + (d, e, ?f) 的結(jié)果就是 (a+d, b+e, c+f)。它將分別對(duì)每一個(gè)元素進(jìn)行配對(duì),然后對(duì)它們進(jìn)行運(yùn)算。它返回的結(jié)果是一個(gè)數(shù)組。注意,當(dāng)使用邏輯運(yùn)算符比如 “<” 和 “>” 的時(shí)候,返回的將是一個(gè)布爾型數(shù)組,這點(diǎn)有一個(gè)很好的用處,后邊我們會(huì)提到。
dot() 函數(shù)計(jì)算兩個(gè)數(shù)組的點(diǎn)積。它返回的是一個(gè)標(biāo)量(只有大小沒(méi)有方向的一個(gè)值)而不是數(shù)組。
背后的數(shù)學(xué)知識(shí)
dot() 函數(shù)有時(shí)候也稱為點(diǎn)積。理解這個(gè)函數(shù)的最好方法就是看下邊它的計(jì)算過(guò)程。
數(shù)組的特定操作符
NumPy 還提供了一些其他很有用的操作符,用于處理數(shù)組。
# dot, sum, min, max, cumsuma = np.arange(10)print(a.sum()) # >>>45
print(a.min()) # >>>0
print(a.max()) # >>>9
print(a.cumsum()) # >>>[ 0 ?1 ?3 ?6 10 15 21 28 36 45]
很明顯就能看出 sum()、min() 和 max() 函數(shù)的功能:將所有元素加起來(lái),找到最小值和最大值。
cumsum() 函數(shù)就不是那么明顯了。它像 sum() 那樣把所有元素加起來(lái),但是它的實(shí)現(xiàn)方式是,第一個(gè)元素加到第二個(gè)元素上,把結(jié)果保存到一個(gè)列表里,然后把結(jié)果加到第三個(gè)元素上,再保存到列表里,依次累加。當(dāng)遍歷完數(shù)組中所有元素則結(jié)束,返回值為運(yùn)行數(shù)組的總和的列表。
cystone: 這里作者說(shuō)的比較拗口,其實(shí) cumsum() 就是一個(gè)累加計(jì)算并且保存每次累加的結(jié)果,返回值就是包含所有累加結(jié)果的一個(gè)列表。比如 np.array([1, 2, 3, 4, 5]).cumsum() = [1, 3, 6, 10, 15]
高級(jí)索引
花俏的索引
“花俏的索引”是獲取數(shù)組中我們想要的特定元素的有效方法。
# Fancy indexinga = np.arange(0, 100, 10) indices = [1, 5, -1] b = a[indices] print(a) # >>>[ 0 10 20 30 40 50 60 70 80 90]
print(b) # >>>[10 50 90]
如你所見(jiàn),上邊的例子中,我們用想獲取的索引的序列作為索引。它返回了我們索引的元素。
布爾過(guò)濾(boolean masking)
布爾過(guò)濾是一個(gè)奇妙的特性,它允許我們根據(jù)指定條件獲取數(shù)組中的元素。
# Boolean maskingimport matplotlib.pyplot as plta = np.linspace(0, 2 * np.pi, 50) b = np.sin(a) plt.plot(a,b) mask = b >= 0
plt.plot(a[mask], b[mask], 'bo') mask = (b >= 0) & (a <= np.pi / 2) plt.plot(a[mask], b[mask], 'go') plt.show()
上邊的代碼展示了實(shí)現(xiàn)布爾屏蔽。你需要做的就是傳遞給數(shù)組一個(gè)與它有關(guān)的條件式,然后它就會(huì)返回給定條件下為真的值。
上邊的例子將會(huì)生成下邊這幅圖:
我們用條件式選擇了圖中不同的點(diǎn)。藍(lán)色的點(diǎn)(也包含圖中的綠點(diǎn),只是綠點(diǎn)覆蓋了藍(lán)點(diǎn)),顯示的是值大于零的點(diǎn)。綠點(diǎn)顯示的是值大于 0 小于 Pi / 2 的點(diǎn)。
缺省索引
缺省索引是從多維數(shù)組的第一維獲取索引和切片便捷方法。例如,你有一個(gè)數(shù)組 a = [[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]],那么 a[3] 將會(huì)返回?cái)?shù)組第一維中索引值為 3 的元素,這里的結(jié)果是 4。
# Incomplete Indexinga = np.arange(0, 100, 10) b = a[:5] c = a[a >= 50] print(b) # >>>[ 0 10 20 30 40]
print(c) # >>>[50 60 70 80 90]
Where 函數(shù)
where() 函數(shù)是另外一個(gè)根據(jù)條件返回?cái)?shù)組中的值的有效方法。只需要把條件傳遞給它,它就會(huì)返回一個(gè)使得條件為真的元素的列表。
# Wherea = np.arange(0, 100, 10) b = np.where(a < 50) c = np.where(a >= 50)[0] print(b) # >>>(array([0, 1, 2, 3, 4]),)
print(c) # >>>[5 6 7 8 9]
這就是 NumPy,不算太難,對(duì)吧?當(dāng)然,這些只是一些基礎(chǔ),NumPy 還有很多其他的功能,如果你已經(jīng)熟悉了這些基礎(chǔ)內(nèi)容,你可以去探索一下。
總結(jié)
以上是生活随笔為你收集整理的使用Python进行科学计算:NumPy入门的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Matplotlib 快速入门
- 下一篇: 802.11 MAC Header(MA