# 一,Numpy 知識點總結:
# 1, 建立 ndarray:
# 1)np.array()方法: 接收一切序列類型對象,包括其他數組。
import numpy as np
myndarry=np.array([1,2,3,4,"a","b"])
# 2)其他方法,如:np.zeros(),np.ones(),np.empty(),np.arange(),np.ones_like(),np.zeros_like(),
# np.eye(),np.empty_like(),np.identity()等。
np.zeros(5), np.zeros((2,3))
np.ones(5), np.ones((2,3))
np.empty((2,2)) # np.empty傳回全0數組是不安全的,很多情況下,傳回的都是一些未初始化的垃圾值.
np.arange(5), np.arange(1,5), np.arange(1,10,2) # array([0, 1, 2, 3, 4]) # 一維數組
arr02=np.zeros_like(arr01)
arr03=np.ones_like(arr01)
arr04=np.empty_like(arr01)
# 2, 數組的屬性:
print(myarray.ndim) # 1 維數
print(myarray.size) # 5 元素總數
print(myarray.shape) # (5,) 形狀 一維數組的形狀 (n,)或(1,n)
print(myarray.dtype) # int32 資料類型
print(myarray.itemsize) # 4 每個元素的位元組大小 32/8=4
# 3, ndarray 的資料類型:
# 1)自動推斷類型:
arr01=np.array([0,1,2,3,4])
arr01.dtype # dtype('int32')
# 2)建立數組時為數組指定資料類型時:
arr02=np.array([0,1,2,3,4],dtype='float64')
arr02.dtype #dtype('folat64')
# 3)使用astype顯示轉換資料類型,傳回一個新數組:
arr01=np.array([0,1,2.5,3.1,4.2],dtype='float64')
arr02=arr01.astype(np.int32) # 将浮點型數組轉為整數,并不會四舍五入,而是直接截斷 array([0, 1, 2, 3, 4])
arr01=np.array(['0','1','2.5','3.1','4.2'])
arr02=arr01.astype(np.float64)
arr02 # array([0. , 1. , 2.5, 3.1, 4.2])
arr01=np.array([0,1,2,3,4],dtype='float64')
arr02=np.array(["1","4","5"])
arr03=arr02.astype(arr01.dtype) # 使用其他數組的資料類型
arr03.dtype
# 4, 數組和标量之間的運算
# 大小相等的數組之間的任何算術運算都會将運算應用到元素級:
# 不同大小的數組之間的運算叫做廣播,本書不對廣播機制做深入了解,可在附錄A NUmpy進階應用中了解一下。
arr*arr
arr+arr
arr-arr
arr/arr
arr**2
1/arr
arr-0.5
3*arr+2
arr>arr2 # 傳回布爾類型數組
# 5, 基本索引和切片
# 1)一維數組: Numpy 數組的索引方法非常多,一維數組很簡單和pyton 清單類似。
# 一維數組元素的通路:arr1d[5]
# 一維數組的切片:arr1d[5:8]
# 一維數組的切片指派:arr1d[3:7]=12 會影響原數組的值
# 一維數組切片的顯式複制: arr_new=arr1d[5:8].copy() 對 arr_new的修改,不會影響 arr1d
# 6, 高維數組的索引(通路)和切片: 二維數組 擷取行,擷取列,擷取行列子集,擷取元素
arr2d=np.arange(1,10).reshape(3,3)
# 二維數組的元素索引--擷取一維數組(行):arr2d[2] 相當于 arr2d[2,] # array([7, 8, 9])
# 二維數組的元素索引--擷取單個元素:arr2d[2][1] 相當于 arr2d[2,1] # 8
# 二維數組的元素索引--擷取一維數組(列)arr2d[:,1] # 擷取列需要切片 array([2, 5, 8])
# 二維數組的元素索引--擷取二維的子集數組(行列子集)arr2d[:2,1:] # 擷取行列子集需要切片
# 注意:
#上面所有的隻要有兩個[][]的都可以看作兩次索引,比如 arr2d[2][1]相當于 arr_new01=arr2d[2] arr_new02=arr_new01[1]
#當然,對切片的指派也會廣播到整個選區:arr2d[:,:1]=9
# 7, 布爾索引 == != ~ | < > <= >=
# 傳回結果的次元與布爾索引數組的次元相同:
names=np.array(["Bob","Joe","Will","Bob","Will","joe","joe"]) # size=7
data=np.random.randn(7,4) # 行數為 7
bool_Bob = names == 'Bob' # bool_Bob 是一個 size=7的一維布爾數組。 作為下面的索引條件,True表示滿足條件
data[names == 'Bob'] 相當于 data[names == 'Bob',] # 傳回所有滿足條件的單行或多行 一維或二維數組
data[names == 'Bob',:4] 相當于 data[names == 'Bob',] # 前4列中滿足條件的行 二維數組
data[names!='Bob']
data[~(names=='Bob')]
mask=(names=='Bob')|(names=='Will') data[mask] # 必須帶括号
mask=(names=='Bob')&(names=='Will') data[mask] # 必須帶括号 # data[mask]為空數組
# names中元素的值是确定的,不可能既是‘Bob’又是的'Will',是以可以預想 mask 的元素全是False
data[data<0]
# 對使用布爾索引獲得的所有元素或行指派:
data[data<0]=0 # 會影響 data
data[(data==0.1)|(data<0.2)]=0.25
data[names=='joe']=7
# 對使用布爾索引獲得的整列指派:
bool_arr=np.array([False,False,True,False])
data=data.swapaxes(0,1) # 軸對換傳回的是一個新的數組,是以還用data來接收才能改變data數組。
data[bool_arr]=100 # 為列指派
data=data.swapaxes(0,1) # 再次轉回來
data
# 8, 花式索引(整數數組索引):
# 與切片的一個很大不同點是,它總是将資料複制到新數組中,對花式索引結果的指派,不影響原數組,
# 因為其形狀與原數組都不一樣了,自然沒法指派給原數組。
arr84=np.empty((8,4))
for i in range(8):
# arr84[i,]=i
arr84[i]=i
arr84[[4,3,0,6]] # 取arr84數組的第5,第4,第1和第7行資料
arr84[[-3,-5,-7]] #使用負的索引,會從數組的末尾開始選行,-3表示倒數第三行。
newarr84=np.arange(32).reshape((8,4))
newarr84[[1,5,7,2],[0,3,1,2]]
newarr84[[1,5,7,2]][:,[0,3,1,2]] # 4x4 分開寫:new=newarr84[[1,5,7,2]],new2=new[:,[0,3,1,2]] 輸出new2
# 9,數組轉置和軸對換
# 轉置是重塑的一種特殊形式,傳回的是原數組的視圖(不會進行任何複制操作)
# 我的了解,arr和arr.T ,arr.transpose() 都是arr的不同形式,對arr.T ,arr.transpose()的指派操作會影響arr
# 1)array.T 屬性 2)arr.transpose(軸号元組)方法 3)array.swapaxes(1,0)方法
# 上面三種方法或屬性都不改變原來數組。
arr35=np.arange(15).reshape((3,5))
arr35.T
arrdot=np.dot(arr35.T,arr35) # 點積操作
arr35=np.arange(15).reshape((3,5))
arr35.transpose((1,0)) # 軸号元組(1,0)
arr35.swapaxes(1,0) # 兩個軸号做參數,不是元組
# 10,通用函數 ufunc:快速的元素級的數組函數
# 可以看作是簡單函數(接受一個或多個标量值,并産生一個或多個标量值)的矢量化包裝器。
# 許多ufunc都是簡單的元素級變體,如sqrt,exp:
# 一進制 ufunc:(操作單個數組) 文法:np.ufunc(arr)
# abs,fabs--計算整數,浮點數,複數的絕對值,對于非複數值,可以使用更快的fabs
# sqrt------計算各元素的平方根,相當于arr**0.5
# square----計算各元素的平方,相當于arr**2
# exp-------計算各元素的以e為底的指數
# log,log10,log2,log1p--分别表示自然對數,底數為10的log,底數為2的log,log(1+x)
# sign--計算各元素的正負号:1(正數),0(零),-1(負數)
# ceil--計算各元素的ceiling值,即大于等于該值的最小整數。 (天花闆值)
# floor--計算該值的floor值,即小于等于該值的最大整數。(地闆值)
# rint--将各元素的值四舍五入到最接近的整數,保留dtype。
# modf--将數組的小數和整數部分以兩個獨立數組的形式傳回。
# isnan--傳回一個表示哪些值是 NAN (not a number)的布爾型數組
# isfinite--傳回一個表示哪些元素是有盡的(非inf,非NAN)的布爾型數組
# isinf--傳回一個表示哪些元素是無窮的的布爾型數組
# cos,cosh,sin,sinh,tan,tanh--普通型和雙曲型三角函數
# arccos,aeccosh,arcsin,arcsinh,arctan,arctanh--反三角函數
# logicl-not--計算各元素not x的真值。相當于 -arr
# 二進制ufunc:(操作兩個數組) 文法:np.ufunc(arr1,arr2)
# add--将兩個數組中對應的元素相加
# subtract--将兩個數組中對應的元素相減
# multiply--将兩個數組中對應的元素相乘
# devide,floor_divide--除法或向下圓整除法(丢棄餘數)
# power--對于第一個數組中的元素A,根據第二個數組中的相應的元素B,計算A**B
# maximum,fmax--元素級的最大值計算,fmax将忽略NAN
# minimum,fmin--元素級的最小值計算,fmin将忽略NAN
# mod--元素級的取模計算(除法的餘數)餘數。
# copysign--将第二個數組中的符号複制給第一個數組中的值
# greater、greater_equal、less、less_equal、equal、not equal--執行數組元素的比較運算,産生布爾型數組。相當于中辍運算符 >,>=,<,<=,==,!=
# logical_and、logical_or、logical_xor--執行元素級的真值邏輯運算。相當于中辍運算符 &、|、^
#示例:
arr=np.arange(10)
np.sqrt(arr) np.exp(arr)
arrfloat=np.random.randn(7)*5
np.modf(arrfloat) # 傳回兩個數組
arr1=np.random.randn(8) arr2=np.random.randn(8)
np.add(arr1,arr2) np.maximum(arr1,arr2)
# 11,面向數組程式設計
# 1) np.meshgrid(arr1,arr2) 生成網格點坐标矩陣
# 假設我們想得到一組值(網格型)上計算sqrt(x^2+y^2)。np.meshingrid(arr1,arr2)函數接受兩個一維數組,并産生兩個二維矩陣
# 假設一維數組的長度為n,那麼二維數組的shape為(n,n)
#(對應于兩個數組中所有的(x,y)對):
import numpy as np
points=np.arange(-5,5,0.01) # 一維數組
xs,ys=np.meshgrid(points,points) # xs,ys均為二維數組,兩個數組互為轉置關系
z=np.sqrt(xs**2+ys**2) # xs**2+ys**2是數組間的運算得到一個新數組 然後再sqrt
import matplotlib.pyplot as plt
plt.imshow(z,cmap=plt.cm.gray);plt.colorbar() # 作圖
plt.title("Image plot of $\sqrt{x^2+y^2})$ for a grid of values")
# 2) np.where(boolarr或傳回布爾數組的表達式,arr1或标量1,arr2或标量2)
# 傳回一個數組
xarr=np.array([1.1,1.2,1.3,1.4,1.5])
yarr=np.array([2.1,2.2,2.3,2.4,2.5])
condarr=np.array([True,False,True,True,False])
np.where(condarr,xarr,yarr)
arrrandn = np.random.randn(4,4)
new_arr = np.where(arrrandn>0,2,-2) # np.where()常用于根據一個數組 arrrandn,而生成另一個新數組 new_arr。
arrrandn = np.random.randn(4,4)
new_arr = np.where(arrrandn>0,2,arr) # 大于0的元素指派為2,其他元素依然是arr對應的元素(即其他元素不變)。
# -------------------------這部分可不看--------------------------
# np.where(boolarr或傳回布爾數組的表達式) 沒搞明白存在的意義
# 傳回元組
import numpy as np
a = np.array([1,3,5,7,9])
arr=np.where(a>5) # (array([3, 4], dtype=int64),) 是【元組】
arr2=a[arr,] # 等同于 a[arr] 傳回:array([[7, 9]]) 一個二維數組
arr2.ndim # 2
arr2.shape # (1,2)
a[a>5] # array([7, 9]) # 一維數組,這可能才是我們想要的。
arr01=np.array([[7,9]]) # array([[7, 9]])
arr01.ndim # 2
arr01.shape # (1, 2)
# --------------------------------------------------------------
# numpy.where的嵌套使用:
# 兩個布爾類型的數組cond1和cond2,如果對應元素都是True,就是11,如果隻有第一個數組的元素是True,就是10,
# 如果隻有第二個數組的元素是True,就是01,如果兩個數組的對應元素都是False元,就是00,用清單接收他們。
results=[]
arr1=np.array([True,False,False,False,True])
arr2=np.array([False,False,True,False,True])
n=arr1.size
for i in range(n):
if arr1[i] and arr2[i]:
results.append('11')
elif arr1[i]:
results.append('10')
elif arr2[i]:
results.append('01')
else:
results.append('00')
results
# 使用np.where進行嵌套就可以寫得更簡單:
np.where((arr1 & arr2),'11',np.where(arr1,'10',np.where(arr2,'01','00'))).tolist()
# 12,數學和統計方法 聚合函數和其他函數
# 可以作為數組的執行個體方法被調用,也可以作為頂級numpy函數使用
# 聚合函數:
# sum 沿着軸向計算所有的累計和,0長度的數組,累計和就是0
# mean 數學平均,0長度的數組平均值是 NAN
# std 标準差,可以選擇自由度調整(預設分母是 n)
# var 方差,可以選擇自由度調整(預設分母是 n)
# min,max 最小值和最大值
# argmin,argmax 最小值和最大值的位置
# 其他統計方法:
# cumsum 所有元素的累積和,第一個加數為0
# cumprod 所有元素的累積,第一個乘數是1
# 這兩個函數不會使數組聚合,而是會産生一個中間結果的數組。
# 示例:
arr=np.random.randn(5,4)
print(arr.mean(),"--",np.mean(arr)) # 整個數組的平均值
print(arr.mean(1),"--",np.mean(arr,1)) # 每行的平均值
print(arr.mean(0),"--",np.mean(arr,0)) # 每列的平均值
print(arr.sum(axis=1),"--",np.sum(arr,axis=1)) # 計算每一列的和
print(arr.std(axis=1),"--",np.std(arr,axis=1)) # 計算每一列的标準差
# 對一維數組的某個軸資料使用cumsum,umprod:
arr1=np.array([1,2,3,4,5,6,7])
arr1.cumsum() # array([1, 3, 6, 10, 15, 21, 28], dtype=int32) 等同 np.cumsum(arr1)
arr1.cumprod() # array([ 1, 2, 6, 24, 120, 720, 5040], dtype=int32) 等同 np.cumprod(arr1)
# 對二維數組的某個軸資料使用cumsum,umprod:
arr3=np.arange(9).reshape((3,3))
arr3
# 13,操作布爾值數組的方法 sum(),any(),all()
# sum(),any(),all() 既可以作為數組執行個體的方法被調用,也可以作為頂級numpy函數使用。
# 這些函數用于非布爾類型數組,所有非 0元素,都會被認為是True.
# sum()
arr=np.random.randn(100)
print((arr>0.1).sum()) # 統計數組中元素大于0.1的個數 布爾類型數組的True相當于1,False相當于0 等同于 print(np.sum(arr>0.1))
# any()和all(), any檢查數組中是否至少有一個True,all檢查數組中是否全是True, 傳回布爾類型的值
bools=np.array([False,True,False,False])
print(bools.any()) # True print(np.any(bools))
print(bools.all()) # False print(np.all(bools))
# 14, 數組排序 arr.sort() 會改變原數組; np.sort(arr)傳回數組的copy,不會改變原數組。
# arr.sort()對一維數組排序:
arr=np.random.randn(6)
arr # array([-1.5197868 , 0.70317138, -1.32870498, -0.79815157, 0.44850826, 0.84079777])
arr.sort() # 不傳回值,原數組改變。
arr # array([-1.5197868 , -1.32870498, -0.79815157, 0.44850826, 0.70317138,0.84079777])
# np.sort(arr)對一維數組排序:
arr=np.random.randn(6)
arr # array([ 1.69866908, -0.93876399, -2.17448296, 1.18976963, -0.52686091, -0.54713395])
np.sort(arr) # array([-2.17448296, -0.93876399, -0.54713395, -0.52686091, 1.18976963, 1.69866908])
arr # array([ 1.69866908, -0.93876399, -2.17448296, 1.18976963, -0.52686091, -0.54713395]) 原數組未改變
# arr.sort()對于二維數組排序,參數為軸号,預設時預設為 1(不推薦預設):
arr2=np.random.randn(5,3)
arr2
arr2.sort() 相當于 arr2.sort(1)
arr2 # 數組改變
np.sort(arr2,1) # 原數組不改變 行資料排序
np.sort(arr2,0) # 原數組不改變 列資料排序
# 15, 一維 ndarray的基礎集合操作
# 注,都是numpy的頂層方法,ndarray對象不存在這些方法。
# np.unique(arr) 計算arr的唯一值,并排序
# np.intersect1d(arr1,arr2) 計算兩個數組的交集,并排序
# np.union1d(arr1,arr2) 計算兩個數組的并集,并排序
# np.ind1d(arr1,arr2) 計算arr1的元素,是否存在于arr2中,傳回一個和 arr1長度一緻的布爾類型數組
# np.setdifferent(arr1,arr2) 差集,在arr1中,但不在arr2中的元素
# np.setxor1d(arr1,arr2) 異或集,在arr1中或在arr2中,但不在二者的交集中
# 示例 1:np.unique(arr)
names=np.array(['Bob','Joe','Will','Bob','Will','Joe','Joe'])
np.unique(names) # array(['Bob', 'Joe', 'Will'], dtype='<U4')
# 用純python 來實作上面的例子:
# 使用set()函數,将數組轉化為set集合,自動去重,然後用sorted()函數對set集合排序,得到清單:
# 知識點:set(ndarray對象)得到去重後的set集合, sorted(set)得到排序後的清單。
names=np.array(['Bob','Joe','Will','Bob','Will','Joe','Joe'])
names_set=set(names)
sorted(names_set) # ['Bob', 'Joe', 'Will']
# 示例 2:np.in1d(arr1,arr2)
values01=np.array([5,6,7,9,0,0,3])
values02=np.array([5,8,7,5])
np.in1d(values01,values02) # array([ True, False, True, False, False, False, False])
# 16, 使用數組進行檔案輸入和輸出 (忽略)
# Numpy 可以将資料以【文本】或【二進制】的形式存入硬碟,或從硬碟載入。
# 由于大部分使用者更傾向于使用pandas等其他工具來載入文本或表格型資料,是以,忽略。
# 17, 線性代數 (對于目前工作用不到,忽略)
# 18, 僞随機數生成 (記住幾個常用的随機函數,用來生成測試數組)
# numpy.random 子產品填補了python子產品的不足,可以高效的生成多種機率分布下的完整樣本值數組。
# numpy.random 中的部分函數清單:
# seed 像随機數生成器傳遞随即狀态種子
# permutation 傳回一個序列的随機排列,或者傳回一個亂序的整數範圍序列
# shuffle 随機排列一個序列
# rand 從均勻分布中抽取樣本
# randint 根據給定的由低到高的範圍抽取随機整數 np.random.randint(start,end,size=n),n是想生成的一維随機數組的大小
# randn 從均值0方差1的正态分布中抽取樣本 (MATLAB 型接口)
# binomial 從二項分布中抽取樣本
# normal 從正态(高斯)分布中抽取樣本
# beta 從beta分布中抽取樣本
# chisquare 從卡方分布中抽取樣本
# python 中random.randint()用法: random.randint(0,1) 表示從0和1随機選取一個整數,
# random.randint(0,5) 表示從0,1,2,3,4,5中随機選取一個整數
# 如,可以使用normal 來獲得一個4x4的正态分布樣本數組:
samples=np.random.normal(size=(4,4)) # 注意參數的寫法
samples
# 19,綜合示例 随機漫步 (見之前的部落格)