天天看點

Numpy 知識總結(濃縮)

# 一,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,綜合示例 随機漫步 (見之前的部落格)