官术网_书友最值得收藏!

2.2 創建數組

NumPy就是用來操作數組的,我們學習NumPy,其實就是學習數組的各種操作。了解了這一點,可以讓后續的學習方向變得更加清晰。

在Python中,可以使用NumPy來創建一個數組。數組和列表很相似,但是它們之間有本質上的區別。

? 列表的元素可以是不同數據類型,而數組的元素必須是同一數據類型。

? 列表不可以進行四則運算,而數組可以進行四則運算。

對于NumPy中的數組,讀者可以簡單地把它看成“增強版的列表”,因為它的功能比列表強大得多。

2.2.1 基本方法

在NumPy中,創建數組的方法有很多,常用的方法如表2-1所示。

表2-1 創建數組的常用方法

除了上表列出的方法,NumPy還有一個empty()方法。empty()在實際開發中用得并不多,這里就不展開介紹了。

1.array()

在NumPy中,可以使用array()來創建一個數組。array()是NumPy中最基礎也是最常用的一個方法。

語法
np.array(列表或元組)
說明

array()的參數可以是一個列表,也可以是一個元組。array()其實就是將一個列表轉換為一個數組,或者將一個元組轉換為一個數組。

舉例:將列表轉換為數組
import numpy as np
arr = np.array([1, 2, 3, 4, 5])
print(arr)
print(type(arr))
print(arr.dtype)

輸出結果如下:

[1 2 3 4 5]
<class 'numpy.ndarray'>
int32
分析

從輸出結果可以看出,數組元素之間是用空格隔開的,而不是用逗號隔開的,這一點和列表不一樣。dtype屬性用于獲取數組元素的類型,這個在下一節會詳細介紹。

array()會自動根據“列表元素的類型”來確定“數組元素的數據類型”。np.array()返回的是一個ndarray對象,這個ndarray對象非常重要,我們在后面會大量接觸到。

可能一些讀者會問:為什么要將列表轉換成數組?原因很簡單,對于列表,只能使用列表的方法來對其中的元素進行操作,但是將列表轉換成數組之后,就可以使用數組提供的豐富方法來對其中的元素進行操作了。

舉例:將元組轉換為數組
import numpy as np
arr = np.array((1, 2, 3, 4, 5))
print(arr)
print(type(arr))
print(arr.dtype)

輸出結果如下:

[1 2 3 4 5]
<class "numpy.ndarray">
int32
分析

np.array()除了可以將列表轉換成數組,還可以將元組轉換成數組。不過在實際開發中,我們更多是將一個列表轉換成數組。

2.arange()

在NumPy中,可以使用arange()來創建元素值在“指定范圍”內的一維數組。需要特別注意的是,arange()只能創建一維數組,而不能創建多維數組。

語法
np.arange(start, end, step)
說明

start是開始值,end是結束值,step是步長。np.arange()的取值范圍為[start, end),也就是包含開始值,但是不包含結束值。

? 當np.arange()有一個參數時,表示只有結束值,此時開始值是0。

? 當np.arange()有兩個參數時,表示只有開始值和結束值,此時開始值是start。

? 當np.arange()有3個參數時,表示有開始值、結束值和步長。所謂步長,指的是元素遞增的量。

舉例:一個參數
import numpy as np
arr = np.arange(10)
print(arr)

輸出結果如下:

[0 1 2 3 4 5 6 7 8 9]
分析

np.arange(10)表示結束值為10,也就是取值范圍為[0, 10)。從結果可以看出,結束值是沒有包含進去的。讀者記住這一點就可以了:不管np.arange()的參數是多少個,結束值都不會被包含進去。

對于這個例子來說,下面3種方式是等價的,讀者可以思考一下為什么:

# 方式1
np.arange(10)
# 方式2
np.arange(0, 10)
# 方式3
np.arange(0, 10, 1)
舉例:兩個參數
import numpy as np
arr = np.arange(5, 10)
print(arr)

輸出結果如下:

[5 6 7 8 9]
分析

np.arange(5, 10)表示開始值為5、結束值為10,也就是取值范圍為[5, 10)。對于這個例子來說,下面兩種方式是等價的:

# 方式1
np.arange(5, 10)
# 方式2
np.arange(5, 10, 1)
舉例:3個參數
import numpy as np
arr = np.arange(10, 30, 3)
print(arr)

輸出結果如下:

[10 13 16 19 22 25 28]
分析

np.arange(10, 30, 3)的取值范圍為[10, 30),步長為3。np.arange()不僅可以用于創建元素的類型是整型的數組,還可以用于創建元素的類型是浮點型的數組。

舉例:元素是浮點數
import numpy as np
arr = np.arange(1.5, 10.5, 2)
print(arr)

輸出結果如下:

[1.5 3.5 5.5 7.5 9.5]
分析

np.arange(1.5, 10.5, 2)的取值范圍為[1.5, 10.5),步長為2。

舉例:步長是浮點數
import numpy as np
arr = np.arange(1, 10, 1.5)
print(arr)

輸出結果如下:

[1.  2.5 4.  5.5 7.  8.5]
分析

np.arange(1, 10, 1.5)的取值范圍為[1, 10),步長為1.5。np.arange()和range()非常相似,但是它們之間也有一定的區別:range()的步長只能是整數,而np.arange()的步長可以是任意數。

此外,arange()只能創建一維數組。如果想要創建多維數組,可以結合“2.5 數組操作”這一節介紹的reshape()來實現。

3.linspace()

除了arange()之外,還可以使用linspace()來創建元素值在“指定范圍”內的一維數組。

語法
np.linspace(start, end, num, endpoint=True或False)
說明

start是開始值,end是結束值,num是個數。默認情況下,linspace()的取值范圍為[start, end],也就是包含開始值和結束值。但是可以使用endpoint=False,使得它的取值范圍為[start, end)。

舉例:包含結束值
import numpy as np
arr = np.linspace(0, 10, 20)
print(arr)

輸出結果如下:

[ 0.          0.52631579  1.05263158  1.57894737  2.10526316  2.63157895
  3.15789474  3.68421053  4.21052632  4.73684211  5.26315789  5.78947368
  6.31578947  6.84210526  7.36842105  7.89473684  8.42105263  8.94736842
9.47368421 10.        ]
分析

np.linspace(0, 10, 20)表示開始值為0,結束值為10,元素個數為20。需要注意的是,np.linspace(0, 10, 20)的取值范圍為[0, 10],也就是包含結束值10。如果不希望把結束值包含進去,可以使用endpoint=False。

舉例:不包含結束值
import numpy as np
arr = np.linspace(0, 10, 20, endpoint=False)
print(arr)

輸出結果如下:

[0.  0.5 1.  1.5 2.  2.5 3.  3.5 4.  4.5 5.  5.5 6.  6.5 7.  7.5 8.  8.5  9.  9.5]
4.zeros()和ones()

在NumPy中,可以使用zeros()來創建一個元素值全為0的數組,也可以使用ones()來創建一個元素值全為1的數組。

語法
np.zeros((a, b, ..., n), dtype=int或float)
np.ones((a, b, ..., n), dtype=int或float)
說明

zeros()和ones()都可以接收兩個參數。第1個參數是一個元組,它是一個必選參數,表示創建一個a×b×…×n的數組;第2個參數是一個可選參數,它用于定義元素的類型,默認是float類型。

舉例:默認情況
import numpy as np
arr1 = np.zeros((3, 3))
arr2 = np.ones((3, 3))
print(arr1)
print(arr2)

輸出結果如下:

[[0. 0. 0.]
 [0. 0. 0.]
 [0. 0. 0.]]
[[1. 1. 1.]
 [1. 1. 1.]
[1. 1. 1.]]
分析

實際上,np.zeros((3, 3))是一種簡寫方式,它等價于np.zeros(shape=(3,3))。shape是數組的形狀,下一節會詳細介紹。

對于shape參數來說,它的值是一個元組或列表,所以下面兩種方式是等價的。這兩種方式在實際開發中都會出現,我們需要了解一下:

# 方式1
arr1 = np.zeros((3, 3))
arr2 = np.ones((3, 3))
# 方式2
arr1 = np.zeros([3, 3])
arr2 = np.ones([3, 3])

默認情況下,使用zeros()和ones()創建的數組的元素都是float類型,以下兩種方式是等價的:

# 方式1
arr1 = np.zeros((3, 3))
arr2 = np.ones((3, 3))
# 方式2
arr1 = np.zeros((3, 3), dtype=float)
arr2 = np.ones((3, 3), dtype=float)
舉例:int類型
import numpy as np
arr1 = np.zeros((3, 3), dtype=int)
arr2 = np.ones((3, 3), dtype=int)
print(arr1)
print(arr2)

輸出結果如下:

[[0 0 0]
 [0 0 0]
 [0 0 0]]
[[1 1 1]
 [1 1 1]
[1 1 1]]
分析

如果想要將數組元素定義成int類型,可以使用dtype=int。

2.2.2 隨機數組

在實際開發中,有時手動創建的數據并不能滿足開發需求,所以我們還得借助一種特殊數組,那就是“隨機數組”。

在NumPy中,可以使用random模塊來創建一個隨機數組。創建隨機數組的方法主要有3種,如表2-2所示。

表2-2 創建隨機數組的方法

1.randint()

在NumPy中,可以使用random模塊的randint()方法來創建一個整型隨機數組。

語法
np.random.randint(start, end, size=元組或整數)
說明

元素的取值范圍為[start, end),包含start但不包含end。size的取值分為以下兩種情況。

? 當size是一個元組時,size=(m)表示創建一個m行的一維數組,size=(m, n)表示創建一個m×n的二維數組,以此類推。

? 當size是一個整數時,size=m表示創建一個m行的一維數組。實際上,size=(m)和size=m是等價的,因為對于一個數來說,使用“()”和不使用“()”是一樣的。

舉例:一維數組
import numpy as np
arr = np.random.randint(10, 20, size=(5))
print(arr)

輸出結果如下:

[14 11 17 16 12]
分析

randint(10, 20, size=(5))表示創建一個包含5個元素的一維隨機數組,元素都是[10, 20)內的整數。

對于這個例子來說,下面3種方式是等價的。這3種方式我們都要了解一下,因為很多地方都會出現:

# 方式1
arr = np.random.randint(10, 20, size=(5))
# 方式2
arr = np.random.randint(10, 20, size=5)
# 方式3
arr = np.random.randint(10, 20, 5)
舉例:二維數組
import numpy as np
arr = np.random.randint(10, 20, size=(2, 5))
print(arr)

輸出結果如下:

[[14 14 19 12 19]
[17 12 15 14 12]]
分析

randint(10, 20, size=(2, 5))表示創建一個2×5的二維隨機數組,元素都是[10, 20)內的整數。2×5也就是2行5列,如圖2-3所示。

圖2-3

對于這個例子來說,以下兩種方式是等價的:

# 方式1
arr = np.random.randint(10, 20, size=(2, 5))
# 方式2
arr = np.random.randint(10, 20, (2, 5))
2.rand()

在NumPy中,可以使用random模塊的rand()方法來創建一個浮點型隨機數組,其元素的取值范圍為[0,1)。

語法
np.random.rand(m, n)
說明

當rand()有一個參數時,例如rand(m),表示創建一個包含m個元素的一維隨機數組。當rand()有兩個參數時,例如rand(m, n),表示創建一個m×n的二維隨機數組。

舉例:一維數組
import numpy as np
arr = np.random.rand(5)
print(arr)

輸出結果如下:

[0.52039969 0.44537686 0.66946674 0.91937385 0.6516376]
分析

在這個例子中,rand(5)表示創建一個包含5個元素的一維隨機數組。其中,元素都是[1,0)內的浮點數。

舉例:二維數組
import numpy as np
arr = np.random.rand(2, 5)
print(arr)

輸出結果如下:

[[0.23881446 0.78932247 0.58749747 0.86061954 0.65791401]
[0.59769419 0.12579491 0.79234194 0.74421893 0.27629203]]
分析

在這個例子中,rand(2, 5)表示創建一個2×5的二維隨機數組。

3.randn()

在NumPy中,可以使用random模塊的randn()方法來生成一個隨機數組,該數組的元素符合正態分布。

語法
np.random.randn(m, n)
說明

當randn()有一個參數時,例如randn(m),表示創建一個包含m個元素的一維隨機數組。當randn()有兩個參數時,例如randn(m, n),表示創建一個m×n的二維隨機數組。

randn()和rand()的參數是一樣的,只是生成的元素的值不一樣。

舉例:一維數組
import numpy as np
arr = np.random.randn(5)
print(arr)

輸出結果如下:

[-1.05723124 -0.00507968 -0.20048986  0.0417768   1.51705339]
分析

在這個例子中,randn(5)表示創建一個包含5個元素的一維隨機數組。

舉例:二維數組
import numpy as np
arr = np.random.randn(2, 5)
print(arr)

輸出結果如下:

[[-2.0953303  0.03843233  -0.63218314  1.22316454  0.21490433]
[-0.5237318  -1.01258678  0.58363956  0.11605207  1.39723533]]
分析

在這個例子中,randn(2, 5)表示創建一個2×5的二維隨機數組。需要說明的是,隨機數組在后面的學習中會大量用到,所以randint()、rand()、randn()這幾個方法,讀者要重點掌握。

2.2.3 數組與列表的區別

到這里,讀者可能會有這樣的一個疑問:為什么有了列表之后,還要搞一個數組出來呢?它們之間有什么區別嗎?其實,數組和列表(見圖2-4)最本質的區別在于:它們在內存中的存儲方式不同。

圖2-4

列表可以存儲不同類型的元素,元素可以是數字、字符串、列表、字典等。對于列表中的每一個元素來說,需要為元素分配一定的內存空間來保存元素的類型信息。當所有元素都是同一種類型時,本來只需要存儲一次類型信息就可以了,但是卻要為每一個元素分配“額外的內存”來保存類型信息。此時這些信息是冗余的,并且白白浪費了內存空間。

為了解決這個問題,最好的辦法就是使用只包含相同類型元素的數組。當元素個數非常龐大(例如上百萬)時,列表和數組的性能差異就變得非常明顯了。在對大量數據進行數學操作時,當然也可以使用列表來操作,只是并不推薦這樣去做,因為此時列表的性能太差了。

NumPy中數組的元素要比列表中的元素“純潔”得多,元素的類型只能是同一種數據類型。對于NumPy中的數組來說,元素的類型大多數情況下都是整型或浮點型,很少情況下是其他類型。

舉例:不同類型
import numpy as np
arr = np.array([1, "2", True, "4", 5])
print(arr)
print(arr.dtype)               # 輸出數組的類型

輸出結果如下:

["1" "2" "True" "4" "5"]
<U11
分析

np.array()用于將列表轉換為數組,一般要求列表的元素是相同的類型。當列表元素是不同類型時,程序不會報錯,但是并不推薦這樣去做。讀者在使用NumPy數組時,要避免出現這種問題。

【常見問題】

1. 為什么不用[1 2 3 4 5]這樣的方式來創建數組,而是采用np.array()這種更加復雜的方式呢?

這是因為在Python中,中括號已經用于創建列表了。如果數組也使用中括號來創建,那么Python就無法判斷此時創建的到底是列表還是數組了。

2. 為什么NumPy要提供那么多個創建數組的方式呢?

原因其實很簡單,NumPy的核心就是數組。所以不管是創建數組還是操作數組,它都提供了盡可能多的方式,以便我們更好地靈活操作。

3. 對于隨機數組來說,什么情況下包含結束值,什么情況下不包含結束值呢?

對于隨機數組來說,絕大多數情況下都是不包含結束值的。讀者暫且可以先這樣簡單地記憶。

主站蜘蛛池模板: 沈阳市| 英吉沙县| 湖口县| 长治县| 武城县| 汉源县| 务川| 图木舒克市| 眉山市| 平塘县| 石河子市| 商都县| 尚义县| 新沂市| 宁武县| 阿拉善盟| 独山县| 南安市| 旌德县| 金湖县| 乳山市| 古丈县| 庆安县| 吴堡县| 从江县| 永春县| 桑日县| 商城县| 敦化市| 怀仁县| 江北区| 营山县| 永年县| 阳春市| 唐海县| 神农架林区| 金门县| 衡阳市| 阳高县| 台前县| 玉林市|