1. 程式人生 > >資料分析與挖掘入門——學習筆記(三)numpy的基本函式使用

資料分析與挖掘入門——學習筆記(三)numpy的基本函式使用

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