2020,努力做一個無可替代的人!
寫在前面的話
沒想到吧,NumPy 還有一小節,請珍惜 NumPy 最後的美好時光。
這一節的內容源自於一個朋友的提問,我在交流羣裏也分享過,具體問題會在正文中復現,知道你們好奇,往下看就好。
害,差點忘了,先回顧下前三節的內容,同學們自行復習:
聽說擡起頭看天眼眶纔不會溼?
我想試試
正文
先來複現一下朋友當時問我的問題:
有一個數據a(DataFrame類型、3行4列的數據),數據b(Series類型、[0,1,2]),比較a和b後輸出布爾型數組
看一下代碼演示
# 創建 DataFrame
import pandas as pd
df_a = pd.DataFrame(np.arange(12).reshape(3, 4))
# 輸出
0 1 2 3
0 0 1 2 3
1 4 5 6 7
2 8 9 10 11
# 創建 Series
import numpy as np
series_b = pd.Series(np.arange(3))
# 輸出
0 0
1 1
2 2
dtype: int32
就這樣兩個數據類型,我剛開始一聽第一反應是:這咋比較?數據類型都不一樣,維度也不一樣。
直到我翻開書看了一下才想起這個概念:廣播
。
先看一下比較的結果是什麼
df_a > series_b
# 輸出
0 1 2 3
0 False False False False
1 True True True False
2 True True True False
如果你知道爲什麼會出現上面這個結果,那恭喜你,這一小節你可以直接跳過,相信我,你是最NB的
不知道的同學我們還是要繼續的,看完今天的文章想必你會明白。
廣播
上面問題提到的一個概念,也是今天唯一的一個知識點:廣播
廣播指的是不同形狀的數組之間的算術運算的執行方式。
首先,將標量數組和數組合並時就會發生簡單的廣播。
# 創建數組
data_arr1 = np.arange(5)
# 輸出
[0 1 2 3 4]
data_arr1 * 5
# 輸出
[ 0 5 10 15 20]
在上面的乘法運算中,標量值4你也可以看做是一個一行一列的數組,被廣播到其他所有的元素上。
這是最簡單的標量的廣播,那如果是數組的廣播呢?
看例子:
# 創建4行3列的二維數組
data_arr2 = np.array([[0, 0, 0], [1, 1, 1], [2, 2, 2], [3, 3, 3]])
# 輸出
[[0 0 0]
[1 1 1]
[2 2 2]
[3 3 3]]
# 創建一維數組
data_arr3 = np.array([1, 2, 3])
# 輸出
[1 2 3]
# A + B
data_arr2 + data_arr3
# 輸出
[[1 2 3]
[2 3 4]
[3 4 5]
[4 5 6]]
沒想到吧,竟然可以計算而沒有報錯。
這是因爲數組 data_arr3 在0軸上做的廣播(灰色數字),將原本1行3列的數組廣播成4行3列,從而可以與 data_arr2 進行計算
ok,想必你應該清楚廣播是什麼作用了吧
當然,廣播也不是說所有情況都會廣播,人家也是有原則的。
何爲廣播?
如果兩個數組的後緣維度(trailing dimension,即從末尾開始算起的維度)的軸長度相符或其中一方的長度爲1,則認爲它們是廣播兼容的
。廣播會在缺失和(或)長度爲1 的維度上進行。
這句話是理解廣播的核心,老實說,看懂了嗎?
不懂往下看,擡起頭看天是看不到答案的,只會不讓眼淚流下來!
廣播主要發生在三種情況下:
- 一種是兩個數組的維度不相等,但是它們的後緣維度的軸長相符
- 另一種是兩個數組的維度相同,對應維度的軸長要麼相等要麼任意一個爲1
- 上面兩種的結合體
第一種情況
兩個數組的維度不相等,但是它們的後緣維度的軸長相符
以上面的例子爲例
# 輸出數組形狀/維度
data_arr2.shape
data_arr3.shape
# 輸出
(4, 3)
(3,)
可以看到,data_arr2 (4, 3)是二維的,data_arr3 (3,)是一維的,兩個數組的維度不相等。同時,它們的後緣維度都是3,後緣維度的軸長相等。
完美符合我們的第一種情況,所以可以進行相加運算。
同樣的道理,多維數組也遵循廣播原則。
舉個圖例:
以此類推:
- (2,4,2,4) 和 (2,3,4) 是兼容的
- (2,4,2,4) 和 (2,4) 是兼容的
- (2,4,2,4) 和 (4) 是兼容的
只是它們需要擴展的軸個數不同。
第二種情況
兩個數組的維度相同,對應維度的軸長要麼相等要麼任意一個爲1
這個就比較容易理解了,兩個維度相同的數組,對應的維度長度有兩種情況:
要麼長度相同,要麼有一個長度爲1
# 創建4行1列的二維數組
data_arr4 = np.array([[1, 2, 3, 4]]).reshape(4, 1)
# 輸出
[[1]
[2]
[3]
[4]]
# 創建1行3列的二維數組
data_arr5 = np.array([[1, 2, 3]])
# 輸出
[[1 2 3]]
這兩個數組都是二維數組分別是(4, 1)、(1, 3)
與我們的 data_arr2 (4, 3) 相比,根據第二種情況:
(4, 3) 與 (4, 1) 維度相同,第一維長度相同,第二維存在長度爲1;
(4, 3) 與 (1, 3) 維度相同,第一維存在長度爲1,第二維長度相同;
(4, 1) 與 (1, 3) 維度相同,第一維存在長度爲1,第二維存在長度爲1。
所以,以上三個數組之間互相兼容。
稍微畫個圖例:
這個時候,第二個二維數組會在1軸上進行廣播(灰色數字)
第三種情況
明白了第一種和第二種形式的廣播,第三種就是兩者的結合體。
舉幾個簡單的例子你就明白了:
(4, 2, 5) 和 (1, 5) 是兼容的。但是不滿足第一、第二種情況
(4, 2, 5) 和 (2, 1) 是兼容的。同樣不滿足第一、第二種情況
看完這三種情況,是不是清楚了一些?
再來細品一下廣播的定義
如果兩個數組的後緣維度的軸長度相符或其中一方的長度爲1,則認爲它們是廣播兼容的
。
所以,當我們拿到兩個數組,需要判斷是否兼容時,先從後緣維度開始,依次往前。
要麼對應維度的長度相等,要麼對應維度存在某一方的長度爲1。
若兩個數組的每一個維度都符合這個要求,那這兩個數組一定是兼容的。
總結一下:
今天主要講到一個概念:廣播。
正文最後的總結我覺得很到位了,不妨多讀幾遍理解一下。
看到廣播概念的時候,我猜大部分人剛開始也會很懵逼,字都認識,說了個啥?
所以我列舉了三種情況去分解這個概念,還記得是哪三種嗎?
- 兩個數組的維度不相等,但是它們的後緣維度的軸長相符
- 兩個數組的維度相同,對應維度的軸長要麼相等要麼任意一個爲1
- 上面兩種的結合體
看完這三種情況後,我們回過頭再來看概念,是不是就清晰多了?
ok,《Hello NumPy》 系列就完結了,一共四小節,希望對你們有用!
寫在後面的話
靜下心來寫技術文真的也太舒服了吧,希望你們也能靜下心舒服的看文章。
我一直以爲這幾天做的最認真的事就是洗手,結果發現我寫文章也可以這麼認真。
最近不能去外面喫好的,下班一有空就窩家裏寫文章,都餓瘦了。
之前買的一箱泡麪差不多都喫完了,和我爸媽視頻的時候他們都說我餓瘦了
不說了,眼眶全溼了…
下個系列見
原創不易,歡迎點贊噢
文章首發:公衆號【知秋小夢】
文章同步:掘金,簡書
原文鏈接:《Hello NumPy》系列-廣播操作就看這一篇