Numpy進階操做

目錄python

  • 1. 如何獲取知足條設定件的索引git

  • 2. 如何將數據導入和導出csv文件github

  • 3. 如何保存和加載numpy對象web

  • 4. 如何按列或行拼接numpy數組算法

  • 5. 如何按列對numpy數組進行排序數組

  • 6. 如何用numpy處理日期app

  • 7.高階numpy函數介紹dom

1. 如何獲取知足條設定件的索引

# 定義數組
import numpy as np
arr_rand = np.array([8, 8, 3, 7, 7, 0, 4, 2, 5, 2])
#根據數組是否大於4,知足爲True,不知足爲False
b = arr_rand > 4
b
Out[3]: 
array([ True,  True, False,  True,  True, False, False, False,  True,
       False])

 獲取知足條件的索引ide

# 定位數組大於5的索引
index_gt5 = np.where(arr_rand > 5)
print("Positions where value > 5: ", index_gt5)
Positions where value > 5:  (array([0, 1, 3, 4], dtype=int64),)

由索引獲得知足條件的值.函數

# 根據索引獲得知足條件的數組值
arr_rand.take(index_gt5)
Out[5]: array([[8, 8, 7, 7]])

np.where也能夠接受另兩個可選擇的參數x和y。當條件知足時,輸出x,反之輸出y.

# 若是值大於5,輸出字符串'gt5',反之輸出'le5'
np.where(arr_rand > 5, 'gt5', 'le5')
Out[6]: 
array(['gt5', 'gt5', 'le5', 'gt5', 'gt5', 'le5', 'le5', 'le5', 'le5',
       'le5'], dtype='<U3')

np.argmax和np.argmin分別獲取數組最大值和最小值的索引.

# 最大值索引
print('Position of max value: ', np.argmax(arr_rand))  
# 最小值索引
print('Position of min value: ', np.argmin(arr_rand))
Position of max value:  0
Position of min value:  5

 np.max和np.min分別獲取數組的最大值和最小值.獲取最大最小值

# 最大值
print('max value: ', np.max(arr_rand))  
# 最小值
print('min value: ', np.min(arr_rand)) 
max value:  8
min value:  0

2. 如何將數據導入和導出csv文件

導入數據的標準方法是使用np.genfromtxt函數,它能夠從web URLs導入數據,處理缺失值,多種分隔符,處理不規則的列數等功能。一個不太通用的版本是用np.loadtxt函數導入數據,它假設數據集完好失值.

做爲示例,咱們嘗試從下面的URL讀取.csv文件,因爲numpy數組的全部元素都應該是同一種類型,所以文本的最後一列默認爲'nan'。經過設置參數'filling_values',你能夠用其餘值代替缺失值.

# 關閉數字的科學表示方法
np.set_printoptions(suppress=True)  

# 從url的csv文件導入數據
path = 'https://raw.githubusercontent.com/selva86/datasets/master/Auto.csv'
# delimiter:分隔符,skip_header:從多少行開始讀數據,以0開始,filling_values:缺失值表示,dtype:數據類型
data = np.genfromtxt(path, delimiter=',', skip_header=1, filling_values=-999, dtype='float')

data[:3]  # 顯示前3行數據

#> array([[   18. ,     8. ,   307. ,   130. ,  3504. ,    12. ,    70. ,
#>             1. ,  -999. ],
#>        [   15. ,     8. ,   350. ,   165. ,  3693. ,    11.5,    70. ,
#>             1. ,  -999. ],
#>        [   18. ,     8. ,   318. ,   150. ,  3436. ,    11. ,    70. ,
#>             1. ,  -999. ]])

若設置參數dtype爲'object'或'None',np.genfromtxt在未設置佔位符的前提下能同時處理具備數字和文本列的數據集.

# data2 = np.genfromtxt(path, delimiter=',', skip_header=1, dtype='object')
data2 = np.genfromtxt(path, delimiter=',', skip_header=1, dtype=None)
data2[:3]  # 顯示前三行

#> array([( 18., 8,  307., 130, 3504,  12. , 70, 1, b'"chevrolet chevelle malibu"'),
#>        ( 15., 8,  350., 165, 3693,  11.5, 70, 1, b'"buick skylark 320"'),
#>        ( 18., 8,  318., 150, 3436,  11. , 70, 1, b'"plymouth satellite"')],
#>       dtype=[('f0', '<f8'), ('f1', '<i8'), ('f2', '<f8'), ('f3', '<i8'), ('f4', '<i8'), ('f5', '<f8'), ('f6', '<i8'), ('f7', '<i8'), ('f8', 'S38')])

最後,'np.savetxt'將數據保存爲csv文件.

# 保存數據爲csv文件
np.savetxt("out.csv", data, delimiter=",")

3. 如何保存和加載numpy數據

Numpy提供了.npy和.npz文件類型來實現。若是保存一個ndarray數據,使用np.save保存爲.npy文件;若保存多個ndarray數據,使用np.savez保存爲.npz文件。加載numpy數據,則統一用np.load函數.

# 保存單一的numpy數據,使用.npy文件
np.save('myarray.npy', arr2d)  

# 保存多個numpy數據,使用.npz文件
np.savez('array.npz', arr2d_f, arr2d_b)

# 加載.npy文件
a = np.load('myarray.npy')
print(a)

#> [[0 1 2]
#>  [3 4 5]
#>  [6 7 8]]

加載.npz文件,獲取特定的數組值.

# 加載.npz文件
b = np.load('array.npz')
print(b.files)
b['arr_0']

#> ['arr_0', 'arr_1']

#> array([[ 0.,  1.,  2.],
#>        [ 3.,  4.,  5.],
#>        [ 6.,  7.,  8.]])

雖然經過'arr_0'和'arr_1'獲取了數組值,可是咱們對這兩個索引比較陌生,下面介紹手動設置索引保存和加載數組.

# 增長索引保存數據
b=np.savez('array.npz',arr2d_f=arr2d_f,arr2d_b=arr2d_b)
c = np.load('array.npz')
print(c.files)

c['arr2d_f']

#> ['arr2d_f', 'arr2d_b']

#> array([[1., 2., 3., 4.],
       [3., 4., 5., 6.],
       [5., 6., 7., 8.]])

4. 如何按列或行拼接numpy數組

本節介紹三種拼接numpy數組的方法:

  • 方法1:設置np.concatenate參數axis的值爲1或0,實現數組的列拼接或行拼接。

  • 方法2:np.vstack和np.hstack

  • 方法3:np.r_和np.c_

須要注意的是,np.r_和np.c_使用方括號來拼接數組,其餘兩種方法使用括號。

首先,定義兩個須要拼接的數組.

# 定義兩個拼接的數組
a = np.zeros([4, 4])
b = np.ones([4, 4])
print(a)
print(b)

#> [[ 0.  0.  0.  0.]
#>  [ 0.  0.  0.  0.]
#>  [ 0.  0.  0.  0.]
#>  [ 0.  0.  0.  0.]]

#> [[ 1.  1.  1.  1.]
#>  [ 1.  1.  1.  1.]
#>  [ 1.  1.  1.  1.]
#>  [ 1.  1.  1.  1.]]

行拼接數組

# 行拼接數組
np.concatenate([a, b], axis=0)  
np.vstack([a,b])  
np.r_[a,b]  

#> array([[ 0.,  0.,  0.,  0.],
#>        [ 0.,  0.,  0.,  0.],
#>        [ 0.,  0.,  0.,  0.],
#>        [ 0.,  0.,  0.,  0.],
#>        [ 1.,  1.,  1.,  1.],
#>        [ 1.,  1.,  1.,  1.],
#>        [ 1.,  1.,  1.,  1.],
#>        [ 1.,  1.,  1.,  1.]])

列拼接數組

# 列拼接
np.concatenate([a, b], axis=1) 
np.hstack([a,b])  
np.c_[a,b]

#> array([[ 0.,  0.,  0.,  0.,  1.,  1.,  1.,  1.],
#>        [ 0.,  0.,  0.,  0.,  1.,  1.,  1.,  1.],
#>        [ 0.,  0.,  0.,  0.,  1.,  1.,  1.,  1.],
#>        [ 0.,  0.,  0.,  0.,  1.,  1.,  1.,  1.]])

5. 如何按列對數據進行排序

本節介紹三種按列排序方法:np.sort,np.argsort和np.lexsort。在介紹三種排序方法前,先定義一個2維數組.

arr = np.random.randint(1,6, size=[8, 4])
arr

#> array([[3, 3, 2, 1],
#>        [1, 5, 4, 5],
#>        [3, 1, 4, 2],
#>        [3, 4, 5, 5],
#>        [2, 4, 5, 5],
#>        [4, 4, 4, 2],
#>        [2, 4, 1, 3],
#>        [2, 2, 4, 3]])

np.sort基於列對arr數組進行排序.

# axis=0表示列排序,1表示行排序
np.sort(arr, axis=0)

#> array([[1, 1, 1, 1],
#>        [2, 2, 2, 2],
#>        [2, 3, 4, 2],
#>        [2, 4, 4, 3],
#>        [3, 4, 4, 3],
#>        [3, 4, 4, 5],
#>        [3, 4, 5, 5],
#>        [4, 5, 5, 5]])

由上面結果分析,np.sort排序函數認爲全部列是相互獨立的,對全部列進行排序,破壞了每行的結構,

使用np.argsort函數能夠保留行的完整性 .

# 對arr的第一列進行排序,返回索引
sorted_index_1stcol = arr[:, 0].argsort()

# 根據第一列的索引對數組排序,保留了行的完整性
arr[sorted_index_1stcol]

#> array([[1, 5, 4, 5],
#>        [2, 4, 5, 5],
#>        [2, 4, 1, 3],
#>        [2, 2, 4, 3],
#>        [3, 3, 2, 1],
#>        [3, 1, 4, 2],
#>        [3, 4, 5, 5],
#>        [4, 4, 4, 2]])

倒轉argsort索引實現遞減排序

# 遞減排序
arr[sorted_index_1stcol[::-1]]

#> array([[4, 4, 4, 2],
#>        [3, 4, 5, 5],
#>        [3, 1, 4, 2],
#>        [3, 3, 2, 1],
#>        [2, 2, 4, 3],
#>        [2, 4, 1, 3],
#>        [2, 4, 5, 5],
#>        [1, 5, 4, 5]])

若要基於多個列對數組進行排序,使用np.lexsort函數,它的參數是元組類型,元組的每一個元素表示數組的某一列,排序規則是:越靠近右邊的列,優先級越高.

# 先比較第一列,第一列相同的狀況下再比較第二列
lexsorted_index = np.lexsort((arr[:, 1], arr[:, 0])) 
arr[lexsorted_index]

#> array([[1, 5, 4, 5],
#>        [2, 2, 4, 3],
#>        [2, 4, 5, 5],
#>        [2, 4, 1, 3],
#>        [3, 1, 4, 2],
#>        [3, 3, 2, 1],
#>        [3, 4, 5, 5],
#>        [4, 4, 4, 2]])
 

6. 如何用Numpy處理日期

np.datatime64建立日期對象,精確度達到納秒,你可使用標準的YYYY-MM-DD格格式的字符串做爲參數建立日期.

# 建立datetime64對象
date64 = np.datetime64('2018-02-04 23:10:10')
date64

#> numpy.datetime64('2018-02-04T23:10:10')

從datatime64對象分離時間

# 從datatime64對象分離時間
dt64 = np.datetime64(date64, 'D')
dt64

#> numpy.datetime64('2018-04-14')

若是你想增長天數或其餘任什麼時候間單元,好比月份,小時,秒等,使用np.timedelta函數很是方便.

# np.delta創建多個時間單元
tenminutes = np.timedelta64(10, 'm')  		# 10 分鐘
tenseconds = np.timedelta64(10, 's')  		# 10 秒鐘
tennanoseconds = np.timedelta64(10, 'ns')  	# 10 納秒

print('Add 10 days: ', dt64 + 10)		# 增長10天
print('Add 10 minutes: ', dt64 + tenminutes)	# 增長10分鐘
print('Add 10 seconds: ', dt64 + tenseconds)	# 增長10秒
print('Add 10 nanoseconds: ', dt64 + tennanoseconds)  # 增長10納秒

#> Add 10 days:  2018-02-14
#> Add 10 minutes:  2018-02-04T00:10
#> Add 10 seconds:  2018-02-04T00:00:10
#> Add 10 nanoseconds:  2018-02-04T00:00:00.000000010

dt64對象轉化爲字符串

# dt64轉化爲字符串
np.datetime_as_string(dt64)

#> '2018-04-14'

np.is_busday函數判斷日期是否爲工做日,工做日默認爲週一至週五.

print('Date: ', dt64)
print("Is it a business day?: ", np.is_busday(dt64))

#> Date:  2018-02-04
#> Is it a business day?:  False    # False表示不是

手動設置工做日的時間,如設置工做日爲週六週日,其餘時間爲休息日.

date64 = np.datetime64('2019-04-14')
# 設置週六週日爲工做日
np.is_busday(date64,weekmask='Sat Sun')

#> True

np.busday_offset查看後幾個工做日的日期.

# 週四
date64 = np.datetime64('2019-04-11')
# 查看兩個工做往後的日期
t = np.busday_offset(date64, 2)
t

#> numpy.datetime64('2019-04-15')

若當前工做日爲非工做日,則默認是報錯的.

# 週六
date64 = np.datetime64('2019-04-13')
# 查看兩個工做往後的日期
t = np.busday_offset(date64, 2)
t

#> ValueError: Non-business day date in busday_offset  # 非工做日不能做爲busday_offset的參數

能夠增長參數forward或backward來報錯,forward的含義是若當前日期非工做日,那麼往前尋找最接近當前日期的工做日,backward的含義則是日後尋找最接近當前日期的工做日.

#當前時間爲週六(2019-04-13),往前最接近當前時間的工做日是2019-04-15,兩個工做日偏移後的日期是2019-04-17
print("Add 2 business days, rolling forward to nearest biz day: ", np.busday_offset(date64, 2, roll='forward'))
#當前時間爲週六(2019-04-13),日後最接近當前時間的工做日是2019-04-12,兩個工做日偏移後的日期是2019-04-16
print("Add 2 business days, rolling backward to nearest biz day: ", np.busday_offset(date64, 2, roll='backward'))

#> Add 2 business days, rolling forward to nearest biz day:  2019-04-17
#> Add 2 business days, rolling backward to nearest biz day:  2019-04-16

6.1 如何建立日期序列

np.arange可簡單建立日期序列

# 創建日期序列
dates = np.arange(np.datetime64('2018-02-01'), np.datetime64('2018-02-10'))
print(dates)

# 檢查是否爲工做日
np.is_busday(dates)

#> ['2018-02-01' '2018-02-02' '2018-02-03' '2018-02-04' '2018-02-05'
#>  '2018-02-06' '2018-02-07' '2018-02-08' '2018-02-09']

array([ True,  True, False, False,  True,  True,  True,  True,  True], dtype=bool)

6.2 如何把numpy.data64對象轉化爲datatime.datatime對象

# np.datetime64類型轉化爲datetime.datetime類型
import datetime
dt = dt64.tolist()
dt

#> datetime.date(2018, 02, 10)

獲取datatime對象的年月日很是簡便

print('Year: ', dt.year)  
print('Day of month: ', dt.day)
print('Month of year: ', dt.month)  
print('Day of Week: ', dt.weekday())  # 週五

#> Year:  2018
#> Day of month:  4
#> Month of year:  2
#> Day of Week:  6

7. 高階numpy函數介紹

7.1 標量函數的向量化

標量函數只能處理標量,不能處理數組

# 定義標量函數
def foo(x):
    if x % 2 == 1:
        return x**2
    else:
        return x/2

# On a scalar
print('x = 10 returns ', foo(10))
print('x = 11 returns ', foo(11))

#> x = 10 returns  5.0
#> x = 11 returns  121

# 函數不能處理數組
# print('x = [10, 11, 12] returns ', foo([10, 11, 12]))  # 錯誤

np.vectorize使標量函數也能處理數組,可選參數otypes爲輸出的類型.

# 函數向量化,向量化的輸出類型是float
foo_v = np.vectorize(foo, otypes=[float])

print('x = [10, 11, 12] returns ', foo_v([10, 11, 12]))
print('x = [[10, 11, 12], [1, 2, 3]] returns ', foo_v([[10, 11, 12], [1, 2, 3]]))

#> x = [10, 11, 12] returns  [   5.  121.    6.]
#> x = [[10, 11, 12], [1, 2, 3]] returns  [[   5.  121.    6.]
#>  [   1.    1.    9.]]

7.2 apply_along_axis函數

首先定義一個二維數組

# 定義一個4x10的隨機二維數組
np.random.seed(100)
arr_x = np.random.randint(1,10,size=[4,10])
arr_x

#> array([[9, 9, 4, 8, 8, 1, 5, 3, 6, 3],
#>        [3, 3, 2, 1, 9, 5, 1, 7, 3, 5],
#>        [2, 6, 4, 5, 5, 4, 8, 2, 2, 8],
#>        [8, 1, 3, 4, 3, 6, 9, 2, 1, 8]])

若是咱們要找數組每行或每列的最大值,numpy的一個最大特色是基於向量化操做的,所以咱們使用np.apply_along_axis函數找每行或每列的最大值.

# 基於列操做,找每列的最大值
print('max of per column: ', np.apply_along_axis(np.max, 0, arr=arr_x))

# 基於行操做,找每行的最大值
print('max of per row: ', np.apply_along_axis(np.max, 1, arr=arr_x))

#> max of per column:  [9 9 4 8 9 6 9 7 6 8]
#> max of per row:  [9 9 8 9]

7.3 searchsorted函數

np.searchsorted函數返回某一變量在有序數組的位置,在該位置插入變量後數組仍然是有序的.

# 生成有序數組
x = np.arange(10)
print('Where should 5 be inserted?: ', np.searchsorted(x, 5))
# 若遇到相同大小的數值,輸入變量放在右邊位置
print('Where should 5 be inserted (right)?: ', np.searchsorted(x, 5, side='right'))

#> Where should 5 be inserted?:  5
#> Where should 5 be inserted (right)?:  6

7.4 如何增長數組維度

在不增長任何額外數據的前提下,np.newaxis函數能夠增長數組的維數,newaxis在的位置就是要增長的維度.

# 定義一維數組
x = np.arange(5)
print('Original array: ', x)
# 數組維度爲2
print('ndims of x:', x.ndim)

# 列維度增長
x_col = x[:, np.newaxis]
print(x_col)
# 數組維度爲2
print('ndims of x_col: ', x_col.ndim)
print('x_col shape: ', x_col.shape)

# 行維度增長
x_row = x[np.newaxis, :]
print(x_row)
print('x_row shape: ', x_row.shape)
# 數組維度爲2
print('ndims of x_row: ', x_row.ndim)

#> Original array:  [0 1 2 3 4]
#> ndims of x: 1
#> [[0]
    [1]
    [2]
    [3]
    [4]]
#> ndims of x_col:  2
#> x_col shape:  (5, 1)
#> [[0 1 2 3 4]]
#> x_row shape:  (1, 5)
#> ndims of x_row:  2

7.5 Digitize函數

np.digitize函數返回數組每一個元素屬於bin的索引位置.

# 構建數組和bin
x = np.arange(10)
bins = np.array([0, 3, 6, 9])

# 返回bin索引位置
np.digitize(x, bins)

#> array([1, 1, 1, 2, 2, 2, 3, 3, 3, 4])

可視化分析digitize算法原理:

 

 

如上圖,根據變量落在bin的區間範圍,返回對應的索引.

7.7 Clip函數

np.clip函數將數字限制在給定截止範圍內,全部小於範圍下限的數被當成下限值,大於範圍上限的數被當成上限值.

# 限制x的全部元素位於3和8之間
np.clip(x, 3, 8)

#> array([3, 3, 3, 3, 4, 5, 6, 7, 8, 8])

7.8 Histogram函數和Bincount函數

np.bincount函數統計最小值到最大值的個數,最小值爲0.

# Bincount例子
x = np.array([1,1,2,3,2,4,4,5,6,6,6])
np.bincount(x) # 0出現0次, 1出現2次, 2出現2次, 3出現1次,4出現2次,5出現1次,6出現3次

#> array([0, 2, 3, 0, 2, 1, 3], dtype=int64)

np.histogram函數統計數據落入bins的區間,不考慮bins兩側的區間(以下圖所示).

x = np.array([1,1,2,3,2,4,4,5,6,6,6])
counts, bins = np.histogram(x, [0, 2, 4, 6, 8])
print('Counts: ', counts)
print('Bins: ', bins)

#> Counts:  [2 3 3 3]
#> Bins:  [0 2 4 6 8]
相關文章
相關標籤/搜索