資料分析與挖掘入門——學習筆記(三)numpy的基本函式使用
阿新 • • 發佈:2019-02-09
numpy的基本函式使用
1 通用函式彙總
一元函式
函式 | 說明 |
---|---|
abs,fabs | 計算整數、浮點數或複數的絕對值,對於非複數值,可以使用更快的fabs |
sqrt | 計算各元素的平方根 |
square | 計算各元素的平方 |
exp | 計算各元素的指數ex |
log、log10、log2、log1p | 分別為自然對數(底數為e)、底數為10的log,底數為2的log、log(1+x) |
sign | 計算各元素的正負號:1(正數)、0(零)、-1(負數) |
cell | 計算各元素的celling值,即大於等於該數值的最小整數 |
floor | 計算各元素的floor值,即小於等於該數值的最大整數 |
rint | 將各元素值四捨五入到最接近的整數,保留dtype |
modf | 將陣列的小數和整數部分以兩個獨立陣列的形式返回 |
isnan | 返回一個表示“哪些值是NaN(這不是一個數字)”的布林型陣列 |
isfinite,isinf | 分別返回一個表示“那些元素是有窮的(非inf,非NAN)”或“哪些元素是無窮的”的布林型陣列 |
cos、cosh、sin、sinh、tan、tanh | 普通型和雙曲型三角函式 |
arccos、arccosh、arcsin、arcsinh、arctan、arctanh | 反三角函式 |
logical_not | 計算各元素的notx的真值,相當於-arr |
二元函式
函式 | 說明 |
---|---|
add | 將陣列中對於的元素相加 |
subtract | 從第一個陣列中減去第二個陣列中的對應元素 |
multiply | 陣列元素相乘 |
divide、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 | 執行元素級的真值邏輯運算,相當於中綴運算子&、 |
示例:
from numpy.random import randn
import numpy as np
arr = np.arange(10)
np.sqrt(arr) # 陣列開方
# array([ 0. , 1. , 1.41421356, 1.73205081, 2. ,
# 2.23606798, 2.44948974, 2.64575131, 2.82842712, 3. ])
np.exp(arr) # 計算各元素的指數ex
# array([ 1.00000000e+00, 2.71828183e+00, 7.38905610e+00,
# 2.00855369e+01, 5.45981500e+01, 1.48413159e+02,
# 4.03428793e+02, 1.09663316e+03, 2.98095799e+03,
# 8.10308393e+03])
x = randn(8) # 產生均勻分佈長度為8的陣列
# array([ 2.67418546, 0.90315486, -2.47206977, -0.35658059, 0.57355642,
# 1.52281374, -0.96843312, 0.73204949])
y = randn(8)
# array([-0.49406981, -1.94060909, -1.00077323, -0.46237836, -0.68793955,
# -1.945622 , 1.00339571, 0.03237167])
np.maximum(x, y) # 獲取x,y陣列的元素級最大值
# array([ 2.67418546, 0.90315486, -1.00077323, -0.35658059, 0.57355642,
# 1.52281374, 1.00339571, 0.73204949])
arr = randn(7) * 5
arr
# array([ -2.12987982, 1.91488972, 0.99737023, -3.18350423,
# 13.03076565, 1.76507418, -6.61314238])
np.modf(arr) # 把整數部分和小數部分分開成兩個陣列
# (array([-0.12987982, 0.91488972, 0.99737023, -0.18350423, # 0.03076565, 0.76507418, -0.61314238]),
# array([ -2., 1., 0., -3., 13., 1., -6.]))
2 利用陣列進行資料處理
points = np.arange(-5, 5, 0.1)
xs, ys = np.meshgrid(points, points) # 生成網格的函式,以輸入的引數分別作為xy座標,第一個返回值在y方向上延伸到最後,每次延伸都複製相同的x陣列相同的數值 ,y也一樣
ys
# array([[-5. , -5. , -5. , ..., -5. , -5. , -5. ],
# [-4.9, -4.9, -4.9, ..., -4.9, -4.9, -4.9],
# [-4.8, -4.8, -4.8, ..., -4.8, -4.8, -4.8],
# ...,
# [ 4.7, 4.7, 4.7, ..., 4.7, 4.7, 4.7],
# [ 4.8, 4.8, 4.8, ..., 4.8, 4.8, 4.8],
# [ 4.9, 4.9, 4.9, ..., 4.9, 4.9, 4.9]])
xs
# array([[-5. , -5. , -5. , ..., -5. , -5. , -5. ],
# [-4.9, -4.9, -4.9, ..., -4.9, -4.9, -4.9],
# [-4.8, -4.8, -4.8, ..., -4.8, -4.8, -4.8],
# ...,
# [ 4.7, 4.7, 4.7, ..., 4.7, 4.7, 4.7],
# [ 4.8, 4.8, 4.8, ..., 4.8, 4.8, 4.8],
# [ 4.9, 4.9, 4.9, ..., 4.9, 4.9, 4.9]])
import matplotlib.pyplot as plt
z = np.sqrt(xs ** 2 + ys ** 2)
z
# array([[ 7.07106781, 7.00071425, 6.93108938, ..., 6.86221539,
# 6.93108938, 7.00071425],
# [ 7.00071425, 6.92964646, 6.85930026, ..., 6.78969808,
# 6.85930026, 6.92964646],
# [ 6.93108938, 6.85930026, 6.7882251 , ..., 6.71788657,
# 6.7882251 , 6.85930026],
# ...,
# [ 6.86221539, 6.78969808, 6.71788657, ..., 6.64680374,
# 6.71788657, 6.78969808],
# [ 6.93108938, 6.85930026, 6.7882251 , ..., 6.71788657,
# 6.7882251 , 6.85930026],
# [ 7.00071425, 6.92964646, 6.85930026, ..., 6.78969808,
# 6.85930026, 6.92964646]])
plt.imshow(z, cmap=plt.cm.gray); plt.colorbar()
plt.title("Image plot of $\sqrt{x^2 + y^2}$ for a grid of values")
plt.show()
3 將條件邏輯表達為陣列運算
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])
cond = np.array([True, False, True, True, False])
# 如果c為True就顯示x,否則顯示y
result = [(x if c else y) for x, y, c in zip(xarr, yarr, cond)]
result
# [1.1000000000000001, 2.2000000000000002, 1.3, 1.3999999999999999, 2.5]
arr = randn(4, 4)
arr
# array([[ 0.60957796, 0.74768715, -0.93253626, -2.37603571],
# [-1.15791558, 0.89261081, 0.0314375 , -1.54906174],
# [-1.27154771, -0.71850562, 0.0137652 , -0.17702787],
# [-0.82037751, 0.60648808, 0.68717213, 0.21144662]])
np.where(arr > 0, 2, -2) # 和if else一樣的效果,如果arr大於0,顯示2,否則顯示-2
# array([[ 2, 2, -2, -2],
# [-2, 2, 2, -2],
# [-2, -2, 2, -2],
# [-2, 2, 2, 2]])
np.where(arr > 0, 2, arr) # 如果arr大於0,顯示2,否則保持原樣
# array([[ 2. , 2. , -0.93253626, -2.37603571],
# [-1.15791558, 2. , 2. , -1.54906174],
# [-1.27154771, -0.71850562, 2. , -0.17702787],
# [-0.82037751, 2. , 2. , 2. ]])
# 使用判斷語句新增元素
result = []
for i in range(5):
if cond1[i] and cond2[i]:
result.append(0)
elif cond1[i]:
result.append(1)
elif cond2[i]:
result.append(2)
else:
result.append(3)
# 用where可以更加簡單做到
np.where(cond1 & cond2, 0
np.where(cond1, 1
np.where(cond2, 2, 3))) # 效果和上面一樣
result = 1 * cond1 + 2 * cond2 + 3 * -(cond1 | cond2) # 效果和上面一樣,看看就好
4 數學與統計學方法
常見的數學與統計學方法
方法 | 說明 |
---|---|
sum | 對陣列中全部或某軸向的元素求和。零長度的陣列的sum為0 |
mean | 算術平均數,零長度的陣列的mena為NaN |
std、var | 分別為標準差和方差,自由度可調(預設為n) |
min、max | 最大值和最小值 |
argmin、argmax | 分別為最大值和最小值的索引 |
cumsum | 所有元素的累計和 |
cumprod | 所有元素的累計積 |
arr = np.random.randn(5, 4) # 標準正態分佈資料
arr
# array([[-0.79079955, -0.51042752, 1.32228185, 1.46213944],
# [ 1.56778413, -0.74179834, -0.18338049, -0.08344147],
# [-1.78944583, 0.6194595 , -2.01494555, 0.90297391],
# [-0.51760096, 0.4273585 , -0.83706239, -1.69153002],
# [ 0.69562321, -0.21437187, -0.39440854, -0.45583535]])
arr.mean() # 求算術平均數,長度為0的陣列返回NaN
# -0.16137136672375366
np.mean(arr) # 效果和上面一樣
# -0.16137136672375366
arr.sum() # 對陣列中全部或者某軸向的元素求和,長度為0的陣列返回0
# -3.227427334475073
arr.mean(axis=1) # 對軸向為1的陣列求算術平均數
# array([ 0.37079855, 0.13979096, -0.57048949, -0.65470872, -0.09224814])
arr.sum(0) # 對軸向為0的陣列求和
# array([-0.834439 , -0.41977972, -2.10751512, 0.1343065 ])
arr = np.array([[0, 1, 2],[3,4,5], [6,7,8]])
arr.cumsum() # 求所有元素的累計和,可以用axis=0指定
# array([ 0, 1, 3, 6, 10, 15, 21, 28, 36], dtype=int32)
arr.cumsum(axis=0) # 在軸向為0的方向上求所有元素的累計和
# array([[ 0, 1, 2], [ 3, 5, 7], [ 9, 12, 15]], dtype=int32)
arr.cumprod() # 求所有元素的累計積
# array([0, 0, 0, 0, 0, 0, 0, 0, 0], dtype=int32)
arr.cumprod(axis=1) # 求軸向為1的方向上的累計積
# array([[ 0, 0, 0], [ 3, 12, 60], [ 6, 42, 336]], dtype=int32)
5 用於布林型陣列的方法
arr = randn(100)
(arr > 0).sum() # 對陣列中大於0的元素求和
# 46
bools = np.array([False, False, True, False])
bools.any() # 陣列中是否至少有一個為True
# True
bools.all() # 陣列中是否全為True
# False
6 排序
arr = np.random.randn(8)
arr
# array([ 0.5262729 , 1.45124523, -1.34766636, 0.67057873, 0.26844326,
# -0.85504644, -1.26322892, -0.44348677])
arr.sort()
arr
# array([-1.34766636, -1.26322892, -0.85504644, -0.44348677, 0.26844326,
# 0.5262729 , 0.67057873, 1.45124523])
arr = np.random.randn(5, 3)
arr
# array([[ 0.78248008, -1.38347958, -0.38976053],
# [ 1.47689177, -2.8602724 , 0.79504317],
# [-1.59349714, -0.90894399, -0.83149836],
# [-0.94749844, -0.41368077, -1.79180925],
# [-0.98469535, 0.17109746, -0.69903727]])
arr.sort(1) # 在軸向為1的方向上排序
arr
# array([[-1.38347958, -0.38976053, 0.78248008],
# [-2.8602724 , 0.79504317, 1.47689177],
# [-1.59349714, -0.90894399, -0.83149836],
# [-1.79180925, -0.94749844, -0.41368077],
# [-0.98469535, -0.69903727, 0.17109746]])
large_arr = randn(1000)
large_arr.sort()
large_arr[int(0.05 * len(large_arr))] # 求latge_arr第5%的數
# -1.6198294990696145
7 唯一化以及其他的集合邏輯
唯一化以及其他集和邏輯方法
方法 | 說明 |
---|---|
unique(x) | 計算x的唯一元素,並返回有序結果 |
intersect1d(x,y) | 計算x和y中的公共元素,並返回有序結果 |
union1d(x,y) | 計算x和y的並集,並返回有序結果 |
in1d(x,y) | 得到一個表示“x的元素是否包含於y”的布林型陣列 |
setdiff1d(x,y) | 集和的差,即元素在x中且不再y中 |
setxor1d(x,y) | 集和的對稱差,即存在於一個數組中但不同時存在於兩個陣列中的元素 |
names = np.array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'])
np.unique(names) # 去重
# array(['Bob', 'Joe', 'Will'], dtype='<U4')
ints = np.array([3,3,3,2,2,1,1,4,4,4])
np.unique(ints) # 還有排序功能
# array([1, 2, 3, 4])
sorted(set(names)) # 效果等同於python的去重排序
# ['Bob', 'Joe', 'Will']
values = np.array([6, 0, 0, 3, 2, 5, 6])
np.in1d(values, [2,3,6]) # 在元素級水平上查詢values是否在【2,3,6】中,是就返回True,否則False
# array([ True, False, False, True, True, False, True], dtype=bool)
8 矩陣計算
常用的numpy.linalg函式
函式 | 說明 |
---|---|
diag | 以一維陣列的形式返回方陣的對角線(或非對角線元素),或將一維陣列轉換為方陣(非對角線元素為0) |
dot | 矩陣乘法 |
trace | 計算對角線元素的和 |
det | 計算矩陣行列式 |
eig | 計算方陣的本徵值和本徵向量 |
inv | 計算方陣的逆 |
pinv | 計算矩陣的Moore-Penrose偽逆 |
qr | 計算QR分解 |
svd | 計算奇異值分解(SVD) |
solve | 解線性方程組Ax=b,其中A為一個方陣 |
lstsq | 計算Ax=b的最小二乘解 |
x = np.array([[1., 2., 3.], [4., 5., 6.]])
y = np.array([[6., 23.], [-1, 7], [8, 9]])
x
# array([[ 1., 2., 3.], [ 4., 5., 6.]])
y
# array([[ 6., 23.], [ -1., 7.], [ 8., 9.]])
x.dot(y) # 矩陣x和矩陣y相乘
# array([[ 28., 64.],
# [ 67., 181.]])
np.dot(x, np.ones(3)) # 使用np.dot()也可以矩陣相乘
# array([ 6., 15.])
np.random.seed(12345) # 設定random隨機數生成器的種子,只要生成的時候使用這個種子就會一直產生相同隨機數
from numpy.linalg import inv, qr
X = randn(5,5)
mat = X.T.dot(X)
mat
# array([[ 6.48716715, 0.5005592 , 5.24573443, 3.11736602, 4.43777643],
# [ 0.5005592 , 2.56767069, 1.99957088, 3.21212377, 1.4716587 ],
# [ 5.24573443, 1.99957088, 8.85278893, 5.53060762, 3.78181517],
# [ 3.11736602, 3.21212377, 5.53060762, 5.64556872, 2.96483369],
# [ 4.43777643, 1.4716587 , 3.78181517, 2.96483369, 6.18767109]])
inv(mat) # 計算矩陣的逆
# array([[ 0.78151986, 1.27611828, 0.03474932, -0.97110873, -0.41994161],
# [ 1.27611828, 4.89591304, 1.00862543, -4.09215006, -0.73535442],
# [ 0.03474932, 1.00862543, 0.62968878, -1.16085305, -0.09344266],
# [-0.97110873, -4.09215006, -1.16085305, 3.91434663, 0.50367199],
# [-0.41994161, -0.73535442, -0.09344266, 0.50367199, 0.45346251]])
mat.dot(inv(mat)) # 矩陣mat和它的逆相乘
# array([[ 1.00000000e+00, 1.92577998e-16, 1.86585249e-16,
# 7.76292342e-16, -1.72545323e-16],
# [ -9.14712991e-18, 1.00000000e+00, -4.48981893e-17,
# 1.52816424e-15, 2.60912874e-16],
# [ -3.59417748e-16, 1.19991073e-15, 1.00000000e+00,
# -1.83959835e-16, -3.78441404e-16],
# [ 1.51525668e-16, 1.51753148e-15, -3.14074718e-16,
# 1.00000000e+00, -2.58660222e-16],
# [ -4.70854737e-16, 6.04696092e-16, 1.30899313e-16,
# 2.08083112e-16, 1.00000000e+00]])
q, r = qr(mat) # 計算矩陣的qr分解
r
# array([[ -9.9631048 , -3.16828525, -11.59217132, -8.19015819,
# -8.63843372],
# [ 0. , -3.64516982, -3.30987354, -4.77774054,
# -1.32302282],
# [ 0. , 0. , -3.07309828, -1.11206654,
# 1.63274562],
# [ 0. , 0. , 0. , -0.37924622,
# 1.83213316],
# [ 0. , 0. , 0. , 0. ,
# 0.91857526]])
9 隨機數生成
常用的numpy.random函式
函式 | 說明 |
---|---|
seed | 確定隨機數生成器的種子 |
permutation | 返回一個序列的隨機排列或返回一個隨機排列的範圍 |
shuffle | 對一個序列就地隨機排列 |
rand | 產生均勻分佈的樣本值 |
randint | 從給定的上下限範圍內隨機選取整數,可以指定步距 |
randn | 產生正態分佈(平均值為0,標準差為1)的樣本值 |
binomial | 產生二項分佈的樣本值 |
normal | 產生正態(高斯)分佈的樣本值 |
beta | 產生beta分佈的樣本值 |
samples = np.random.normal(size=(4,4)) # 產生正態(高斯)分佈的維度為4,4的矩陣
samples
# array([[ 0.06987669, 0.24667411, -0.0118616 , 1.00481159],
# [ 1.32719461, -0.91926156, -1.54910644, 0.0221846 ],
# [ 0.75836315, -0.66052433, 0.86258008, -0.0100319 ],
# [ 0.05000936, 0.67021559, 0.85296503, -0.95586885]])
from random import normalvariate
N = 1000000
get_ipython().magic(u'timeit samples = [normalvariate(0, 1) for _ in range(N)]')
# 820 ms ± 8.95 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
get_ipython().magic(u'timeit np.random.normal(size=N)')
# 33.6 ms ± 618 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
10 隨機漫步
import random
position = 0
walk = [position]
steps = 1000
# 生成1000個數,初始值為0,接下來每個數隨機+1或者-1,一直到出現1000個數為止
for i in range(steps):
step = 1 if random.randint(0, 1) else -1
position += step
walk.append(position)
# 和上面一樣,也是生成1000個隨機漫步的數
np.random.seed(12345)
nsteps = 1000
draws = np.random.randint(0, 2, size=nsteps)
steps = np.where(draws > 0, 1, -1)
walk = steps.cumsum()
walk
# array([-1, 0, 1, 2, 1, 2, 1, 0, 1, 0, 1, 2, 1, 2, 3, 2, 3,
# 4, 5, 4, 3, 2, 3, 4, 5, 4, 5, 4, 3, 4, 5, 6, 7, 8,
# ·····
# 14, 13, 14, 13, 14, 13, 14, 15, 14, 13, 14, 13, 14, 15, 16, 15, 16,
# 15, 16, 15, 14, 15, 14, 13, 14, 13, 12, 13, 12, 13, 14], dtype=int32)
walk.max() # 隨機漫步的最大值
# 31
walk.min() # 隨機漫步的最小值
# -3
(np.abs(walk) >= 10).argmax() # 返回walk陣列中大於等於10的第一個數的索引
# 37
11 一次模擬多個隨機漫步
nwalks = 5000
nsteps = 1000
draws = np.random.randint(0, 2, size=(nwalks, nsteps))
steps = np.where(draws>0, 1, -1)
walks = steps.cumsum(1)
walks
# array([[ 1, 0, 1, ..., 8, 7, 8],
# [ 1, 0, -1, ..., 34, 33, 32],
# [ 1, 0, -1, ..., 4, 5, 4],
# ...,
# [ 1, 2, 1, ..., 24, 25, 26],
# [ 1, 2, 3, ..., 14, 13, 14],
# [ -1, -2, -3, ..., -24, -23, -22]], dtype=int32)
hits30 = (np.abs(walks) > 30).any(1) # 是否在軸向為1的方向上的陣列有一個以上的數的絕對值大於30,是就返回True,否則為False
hits30
# array([False, True, False, ..., False, True, False], dtype=bool)
hits30.sum() # 到達30或-30的數量
# 3268
# 在軸向為1的方向上尋找hits30集和中陣列第一次達到30的索引的算術平均值
crossing_times = (np.abs(walks[hits30]) >= 30).argmax(1)
crossing_times.mean()
# 493.64810281517748