numpy
numpy的主要對象是同種元素的多維數組。
numpy底層是用C語言實現的。
面試:
數組和列表有什麼區別?
結構同樣都是[元素1,元素2,元素3 … ]。
在C語言、java中叫做數組;在python中叫做列表。
python中的列表可以存儲不同類型的對象;C語言中的數組只能存放相同類型的數據。
導包
import numpy as np
一、numpy介紹
numpy是用於數據科學計算的基礎,不但能夠完成科學計算任務,還能被用作高效地多維數據容器。用於存儲和處理大型矩陣。
python提供了一個 array 模塊,和 list 不同,它直接保存數值,但是python的 array模塊不支持多維,也沒有各種運算函數。
numpy彌補了這一遺憾。numpy 提供了一種存儲單一數據類型的多維數組–ndarray。
軸(axes)–維度
秩(rank)–軸的個數
(一)array創建數組
1.一維數組
arr1 = np.array([1,2,3])
print('arr1的維度:',arr1.shape) #(3,)
print('arr1的秩:',arr1.ndim) # 1
2.二維數組
arr2 = np.array([[1],[2],[3]])
print('arr2的維度:',arr2.shape) # (3, 1)
print('arr2的秩:',arr2.ndim) # 2
結論
一位數組的秩爲1,二維數組的秩爲2
即arr.ndim = len(arr.shape)
(二)常用屬性
1.秩:ndim
2.維度:shape
arr3 = np.array([[1,2,3],[4,5,6],[7,8,9]])
print(arr3.shape)
print(arr3.ndim)
print(len(arr3.shape))
3.數組元素的總個數size
print(arr3.size)
4.數組元素的類型dtype
print(arr3.dtype) # int32
arr4 = np.array([0.1,0.2,0.3])
print(arr4.dtype) # float64
5.每個元素的字節大小itemsize
一個字節(byte)=8 位(bit)
print(arr3.itemsize) # 4
print(arr4.itemsize) # 8
6.緩衝區:data
arr5 = np.array([1,2,3])
print(arr5.dtype)
print(arr5.itemsize)
print(arr5.data) # <memory at 0x00000000038F14C8>
print(arr5[0])
索引從0開始的原因:
arr5就是arr5.data,即存儲地址的別名
[]中的數字,表示取指定元素,需要跨進的單元
取第一個元素,不用跨進,所以爲0
(三)創建數組的方法
1.使用array()
# def array(p_object, dtype=None, copy=True, order='K', subok=False, ndmin=0):
# p_onject--接收一個array
# dtype--接受一個data-type,表示數組所需要的數據類型,如果沒有給定,則根據傳入元素的,指定隨需要的最小數據類型
arr1 = np.array([1,2,3,4])
print(arr1)
arr2 = np.array([[1,2],[3,4]])
print(arr2)
arr3 = np.array([(1,2),(3,4)])
print(arr3)
arr4 = np.array([1,2,3,4],dtype=np.float64)
print(arr4)
2.使用arange()
# def arange(start=None, stop=None, step=None, dtype=None):
# 值域[start,stop)
arr5 = np.arange(0,1,0.1)
print(arr5)
3.使用linspace()
# def linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None):
# 值域[start,stop],num--元素數量
arr6 = np.linspace(0.1,1,10)
print(arr6)
4.使用logspace()–等比
# def logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None):
arr7 = np.logspace(1,3,3)
print(arr7)
arr8 = np.logspace(1,10,10,base=2)
print(arr8)
5.使用zeros()–全0數組
# def zeros(shape, dtype=None, order='C')
arr9 = np.zeros((2,3))
print(arr9)
6.使用ones()–全1數組
# def ones(shape, dtype=None, order='C'):
arr10 = np.ones((2,3))
print(arr10)
7.使用empty()
創建一個內容隨機並且依賴於內存狀態的數組。
print(np.empty((2,3)))
8.使用eye()–單位數組
arr11 = np.eye(3)
print(arr11)
# [[ 1. 0. 0.]
# [ 0. 1. 0.]
# [ 0. 0. 1.]]
print(np.eye(2,3))
# [[ 1. 0. 0.]
# [ 0. 1. 0.]]
9.使用diag()
arr12 = np.diag([1,2,3,4])
print(arr12)
# [[1 0 0 0]
# [0 2 0 0]
# [0 0 3 0]
# [0 0 0 4]]
練習
1.生成一個3*5的數組,數組元素爲0-14之間的整數
方法1:
arr1 = np.arange(0,15)
arr1.shape = (3,5)
print(arr1)
方法2:
arr2 = np.arange(0,15).reshape(3,5)
print(arr2)
2.輸出數據的維度、秩、元素類型、元素個數
print('維度:',arr1.shape)
print('秩:',arr1.ndim)
print('元素類型:',arr1.dtype)
print('元素個數:',arr1.size)
(四)生成隨機數組
1.random.random(n)
值域[0,1),n表示生成元素的個數。
arr1 = np.random.random(3)
print(arr1)
arr2 = np.random.random(15).reshape((3,5))
print(arr2)
2.random.rand(m,n,…)
表示生成一個m*n*...
的多維數組,值域爲[0,1)。
arr3 = np.random.rand(2,3)
3.random.randn(n)
生成正態隨機數,n表示生成元素的個數。
arr4 = np.random.randn(4)
print(arr4)
import matplotlib.pyplot as plt
plt.hist(arr4)
plt.show()
發現並沒有看出什麼正態分佈的趨勢。
這就涉及到了大數定理。
把n的值變爲1000試試?
arr4 = np.random.randn(1000)
import matplotlib.pyplot as plt
plt.hist(arr4)
plt.show()
這次就有正態分佈的效果了
4.random.randint(a,b,size=(m,n))
# def randint(low, high=None, size=None, dtype='l'):
# 值域[a,b],維度(m,n)的數組
arr5 = np.random.randint(1,10,size=(2,5))
print(arr5)
5.擴展:random模塊常用隨機生成函數
normal():生成正態(高斯)分佈的隨機數
# def normal(loc=0.0, scale=1.0, size=None):
# loc:float--概率分佈的均值,對應着整個分佈的中心center
# scale:float--概率分佈的標準差,對應於分佈的寬度,scale越大越矮胖,scale越小,越瘦高
# size:int or tuple of ints--輸出的shape,默認爲None,只輸出一個值
beta():生成beta分佈的隨機數
在概率論中,貝塔分佈,也稱B分佈,是指一組定義在(0,1)區間的連續概率分佈。
chisqusre():生成卡方分佈的隨機數
gamma():生成gamma分佈的隨機數
伽瑪分佈(Gamma Distribution)是統計學的一種連續概率函數,是概率統計中一種非常重要的分佈。“指數分佈”和“χ2分佈”都是伽馬分佈的特例。
二、數據類型
(一)基本數據類型
(二)數據類型轉換
# 例
print(np.float64(42))
print(np.int32(42.0))
print(np.bool(1)) # 所有非零數據轉換成bool類型都是True
(三)自定義數據類型
例:創建一個存儲餐飲企業庫存信息的數據類型
規定:
(1)用一個長度爲40的字符串來記錄商品的名稱
(2)用一個64位整數來記錄商品庫存
(3)用一個64位單精度浮點型來記錄商品的價格
df = np.dtype([('name',np.str_,40),('numitems',np.int64),('price',np.float64)])
print('df數據結構:',df) # [('name', '<U40'), ('numitems', '<i8'), ('price', '<f8')]
# <U40--長度小於40的字符串,<i8--小於八字節的int類型
table1 = np.array([('tomatos',42,4.14),('cabbages',13,1.72)],dtype=df)
print(table1)
# 輸出商品名
print(table1['name']) # ['tomatos' 'cabbages']
print(table1[0],type(table1[0])) # <class 'numpy.void'>
arr1 = np.array([1,2,3])
print(arr1[0],type(arr1[0])) # <class 'numpy.int32'>
三、數據元素的訪問
通過索引訪問數組元素
(一)一維數組
arr1 = np.arange(10)
print(arr1)
print(arr1[0])
print(arr1[-1])
# 支持切片
print(arr1[3:5])
print(arr1[:5])
print(arr1[3:])
arr1[2:4] = 100,101 # 個數不對應,會報錯
print(arr1) # [ 0 1 100 101 4 5 6 7 8 9]
print(arr1[1:-1:2])
print(arr1[5:1:-2])
注意:從後向前利用切片取數組中的元素時,步長爲負。
(二)二維數組
arr2 = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]])
print(arr2)
# [[ 1 2 3 4]
# [ 5 6 7 8]
# [ 9 10 11 12]]
print(arr2[0][0])
例:取第一行,第3,4列的元素
1.切片
print(arr2[0][2:])
2.數組名[行索引,列索引]
print(arr2[0,2:])
3.數組名[(行下標),(列下標)]
說明:該種寫法主要用於獲取指定行或列的值;而切片寫法,獲取到的是連續的行或列的值。
print(arr2[(0,2),(1,3)]) # [ 2 12]
# 2--(0,2),12--(2,3)
# 也可以配合使用
print(arr2[(0,2),:])
(三)遮罩–mask
arr3 = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]])
mask = np.array([1,0,1],dtype=np.bool)
print(mask) # [ True False True],True顯示,False不顯示
print(arr3[mask,2])
print(arr3[(True,False,True),2])
四、變換數組形態
(一)shape和reshape()
arr1 = np.arange(0,15)
arr1.shape = (3,5)
print(arr1)
arr2 = np.arange(0,15).reshape(3,5)
print(arr2)
(二)展平數組
1.ravel()
是reshape()函數的逆操作
注意:並不修改原數組,而是返回了一個新數組。
arr1 = np.arange(10000)
arr2 = arr1.reshape((100,100))
print(arr1)
print(arr2)
arr3 = arr2.ravel()
print(arr3)
tip1:
如果輸出的數組數量太大,在輸出時,numpy自動省略中間部分,只打印兩邊元素。
如果不想省略,可以在打印前設置如下信息:
np.set_printoptions(threshold=np.NaN)
# 之後再打印
print(arr2)
2.flatten()
# 默認order='C'
# 以行展平
arr3 = np.arange(10).reshape((2,5))
arr4 = arr3.flatten()
arr5 = arr3.ravel()
print(arr3)
print(arr4)
print(arr5)
# order='F'
# 以列展平
arr6 = np.array([[1,2],[3,4]])
arr7 = arr6.flatten(order='F')
print(arr7)
ravel()和flatten()
共同點:
都是將多維數組展開爲一維,輸出結果相同。
不同點:
flatten返回的是一份拷貝,強調的是數據。
ravel返回的是一份視圖,側重的是數據的展現,而不是數據本身。
例:
a1 = np.array([[1,2],[3,4]])
f_a = a1.flatten()
r_a = a1.ravel()
print(a1)
print('f_a:',f_a)
print('r_a:',r_a)
print('--------------------------------------------------------')
f_a[2] = 100
print('f_a:',f_a)
print(a1) # flatten的數組元素髮生變化不影響原數組
a1 = np.array([[1,2],[3,4]])
f_a = a1.flatten()
r_a = a1.ravel()
print(a1)
print('f_a:',f_a)
print('r_a:',r_a)
print('--------------------------------------------------------')
r_a[2] = 101
print('r_a:',r_a)
print(a1) # ravel的數組元素變化,原數據也會同時發生變化
(三)組合/切割數組
1.組合
(1)hstack()和vstack()
arr1 = np.arange(1,6,2)
arr2 = np.arange(7,12,2)
print(arr1,arr2) # [1 3 5] [ 7 9 11]
arr3 = np.hstack((arr1,arr2))
print(arr3)
# [ 1 3 5 7 9 11]
arr4 = np.vstack((arr1,arr2))
print(arr4)
# [[ 1 3 5]
# [ 7 9 11]]
注意:
如果兩個數組,元素個數不相等,橫向正常拼接,但縱向將會報錯。
在stack函數中,參數爲tuple,但其實list也是可以的。
arr1 = np.array([[1,1],[2,2]])
arr2 = np.array([[3,3],[4,4]])
arr3 = np.hstack((arr1,arr2))
arr4 = np.vstack((arr1,arr2))
print('arr1:\n',arr1)
# arr1:
# [[1 1]
# [2 2]]
print('arr2:\n',arr2)
# arr2:
# [[3 3]
# [4 4]]
print('arr3:\n',arr3)
# arr3:
# [[1 1 3 3]
# [2 2 4 4]]
print('arr4:\n',arr4)
# arr4:
# [[1 1]
# [2 2]
# [3 3]
# [4 4]]
(2)concatenate()和軸
axis–軸
# 橫向拼接
arr5 = np.concatenate((arr1,arr2),axis=1)
print('arr5:\n',arr5)
# 縱向拼接
arr6 = np.concatenate((arr1,arr2),axis=0)
print('arr6:\n',arr6)