Numpy从入门到精通

  numpy是机器学习里面基础数字算法库,补充了python语言缺乏的数字计算能力,Numpy底层由C语言实现,运行效率充分优化。2006年,Numpy脱离Scipy成为独立的项目。

ndarry数组

np.array()  传入数组参数,可以是一维的也可以是二维三维的,数组会将其转变成ndarray结构。

import numpy as np
a = np.array([1, 2, 3, 4])
# [1 2 3 4]
b = np.array([[1, 2, 3], [1, 2, 3]])    # 创建维度为2的数组
# [[1 2 3]
#  [1 2 3]]
print(type(a))          # <class 'numpy.ndarray'>

ndarray.ndim  数组的维数

print(a.ndim)   # 1
print(b.ndim)   # 2

ndarray.size  数组的元素数量

print(b.size)   # 6

len(ndarray)  查看数组的第一维度

print(len(b))  # 2

ndarray.dtype    查看数组类型

print(type(b))      # <class 'numpy.ndarray'>
print(b.dtype)      # int32
b = a.astype("float32")
print(b.dtype)          # float32

ndarray对象属性dtype

布尔型:bool

有符号整型:int8(-128~127)/int16/int32/int64

无符号整型:unit(-128~127)/unit16/unit32/unit64

浮点型:float16/float32/float64

复数型:complex64/complex128

字串型:str,每个字符用32位Unicode编码表示

创建数组

np.arange(起始值,终止值,步长),指定范围和数值间的间隔 生成数组,取值范围左闭右开。

np.arange(0, 10, 2)
# [0, 2, 4, 6, 8, 10]

np.zero((a,b), dtype=):生成一个全为0的array,通过dtype指定类型

np.ones():生成一个全为1的array,通过dtype指定类型

np.zeros_like():创造相同结构的全零数组

ary = np.array([1, 2, 3, 4, 5])
print(np.zeros_like(ary))   # [0 0 0 0 0]

np.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None)

在指定间隔[start, stop]之间返回均匀num个数字,如果endpoint是True,则不会取最后一个端点stop

np.linspace(2.0, 3.0, num=5)
# array([ 2.  ,  2.25,  2.5 ,  2.75,  3.  ])
np.linspace(2.0, 3.0, num=5, endpoint=False)
# array([ 2. ,  2.2,  2.4,  2.6,  2.8])

维度操作

维度变换

reshape()和 ravel():维度变换

import numpy as np
a = np.arange(1, 9)     # [1 2 3 4 5 6 7 8]
b = a.reshape(2, 4)     # 视图变维    变为2行4列的二维数组
c = b.reshape(2, 2, 2)  # 视图变维    变为2页2行2列的三维数组
d = c.ravel()           # 视图变维   变为1维数组

np.transpose():维度转置

a = np.random.randn(3,2,1)      # (3, 2, 1)
b = a.transpose((1,0,2))        # 将原来的维度按照(1,0,2)的顺序排序。(2, 3, 1)

增减维度

flatten():压缩成一维数组

print(c.shape)      # (2, 2, 2)
e = c.flatten()     # 压缩成一维数组
print(e.shape)      # (8,)

使用None来增加维度

# a.shape (5,5)
a[:,:,None].shape    # (5,5,1)

np.squeeze  去除维度 1 

# a.shape (5,1)
np.squeeze(arr).shape   # (15,)

数组组合

np.hstack(a,b)  横向拼接

a = np.arange(1, 7).reshape(2, 3)
b = np.arange(7, 13).reshape(2, 3)
# 水平方向完成组合操作,生成新数组
c = np.hstack((a, b))       # (2, 6)

np.vstack(a,b)  纵向拼接

a = np.arange(1, 7).reshape(2, 3)
b = np.arange(7, 13).reshape(2, 3)
# 垂直方向完成组合操作,生成新数组
c = np.vstack((a, b))       # (4, 3)

np.stack(a,b)   在一个新的维度进行拼接

a = np.arange(1, 7).reshape(2, 3)
b = np.arange(7, 13).reshape(2, 3)
# 在一个新的维度axis上拼接,生成新数组
c = np.stack((a, b),axis=0)       # (2, 2, 3)

np.hsplit(a,2)  矩阵横向切割  把a横 竖切成2分

# a.shape (2, 6)
# 水平方向完成拆分操作,生成两个数组
d, e = np.hsplit(c, 2)
# d.shape      (2, 3)
# e.shape      (2, 3)

np.vsplit(a,2)  矩阵纵向切割  把a纵 横切2分

# a.shape (4,3)
# 垂直方向完成拆分操作,生成两个数组
d, e = np.vsplit(a, 2)
# d.shape   (2, 3)
# e.shape   (2, 3)

深度方向(3维)

import numpy as np
a = np.arange(1, 7).reshape(2, 3)
b = np.arange(7, 13).reshape(2, 3)
# 深度方向(3维)完成组合操作,生成新数组
i = np.dstack((a, b))   # (2, 3, 2)
print(i.shape)
# 深度方向(3维)完成拆分操作,生成两个数组
k, l = np.dsplit(i, 2)
# k.shape  # (2, 3, 1)
# l.shape  # (2, 3, 1)

通过axis方法进行数组拼接

np.concatenate((a1, a2, ...), axis=0)

axis的取值

  • 0: 第一个维度方向,垂直方向
  • 1: 第二个维度方向,水平方向
  • 2: 第三个维度方向

注意:拼接的数组,除了需要拼接的维度可以不同,其他维度必须相同

import numpy as np

a = np.array([[1, 2], [3, 4]])      # (2, 2)
b = np.array([[5, 6]])              # (1, 2)

c=np.concatenate((a, b), axis=0)        # (3, 2)
d=np.concatenate((a, b.T), axis=1)        # (2, 3)

数组拆分

np.split(c, 2, axis=0):axis的取值同上

切片索引

一维切片索引

vector = numpy.array([5, 10, 15, 20])
print(vector[0:3])  # 切片索引取值# [ 5 10 15]

利用返回值获取元素

import numpy
vector = numpy.array([5, 10, 15, 20])
print(vector == 10)   # [False  True False False]
# 利用返回值获取元素
print(vector[vector == 10])# [10]

二维切片索引

多维的切片是按照各个维度分别取的

import numpy as np 

a = np.arange(25).reshape(5, 5)
print(a)
# [[ 0  1  2  3  4]
#  [ 5  6  7  8  9]
#  [10 11 12 13 14]
#  [15 16 17 18 19]
#  [20 21 22 23 24]]

# 取第1、2行,第2、3、4列
print(a[1:3, 2:5])        # 多维的切片是按照各个维度分别取
print(a[:, 2:5])          # 行取全部,列取第3-5

有时候数组的一个维度上是三个点,它是用省略号代替所有冒号,a[:, :, None]和a[…, None]的输出是一样的,就是因为…代替了前面两个冒号

print(a[..., None].shape)        # (5, 5, 1)
print(a[:, :, None].shape)        # (5, 5, 1)

数组掩码

import numpy as np

# 输出10以内3的倍数
a = np.arange(1, 10)
mask = a % 3 == 0
print(mask) # [False False  True False False  True False False  True]
print(a[mask])  # [3 6 9]

mask = [2, 2, 6, 6, 4, 4]
print(a)        # [1 2 3 4 5 6 7 8 9]
print(a[mask])  # [3 3 7 7 5 5]

常用函数

向下取整 np.floor()

向下取整 np.ceil()

a = np.random.random((2,2))
# [[0.74892422 0.7665049 ]
#  [0.29296727 0.74230182]]
b = np.floor(10*a)
# [[7. 7.]
#  [2. 7.]]
b = np.ceil(a)
# [[1. 1.]
#  [1. 1.]]

a.T  转置(行列变换)

数组元素 裁剪  np.clip(a, a_min, a_max, out=None) 

把数组a中小于a_min的值都化为a_min,大于a_max的值都化为a_max

import numpy as np

x=np.array([1,2,3,5,6,7,8,9])

print(np.clip(x,3,8))
# [3 3 3 5 6 7 8 8]

pad函数的用法

ndarray = numpy.pad(array, pad_width, mode, **kwargs)

参数:

  • array要填补的数组
  • pad_width在各维度的各个方向上想要填补的长度
    • 如((1, 1),(2, 2)),表示:第一维度前面填充1行,最后一行填充1行;第二维度前面填充2列,最后面填充2列。
    • 如果直接输入一个整数,则说明各个维度和各个方向所填补的长度都一样。
  • mode填补类型,即怎样去填补,有“constant”,“edge”等模式,如果为constant模式,就得指定填补的值,如果不指定,则默认填充0。

对一维数组填充

import numpy as np
array = np.array([1, 1])

# (1,2)表示在一维数组array前面填充1位,最后面填充2位
#  constant_values=(0,2) 表示前面填充0,后面填充2
ndarray=np.pad(array,(1,2),'constant', constant_values=(0,2)) 

print(array)        # [1 1]
print(ndarray)        # [0 1 1 2 2]

对二维数组填充

import numpy as np
array = np.array([[1, 1],[2,2]])
"""
((1,1),(2,2))
在二维数组array第一维(此处便是行)前面填充1行,最后面填充1行;
在二维数组array第二维(此处便是列)前面填充2列,最后面填充2列
constant_values=(0,3) 表示第一维填充0,第二维填充3
"""
ndarray=np.pad(array,((1,1),(2,2)),'constant', constant_values=(0,3)) 

print(array)
# [[1 1]
#  [2 2]]

print(ndarray)
# [[0 0 0 0 3 3]
#  [0 0 1 1 3 3]
#  [0 0 2 2 3 3]
#  [0 0 3 3 3 3]]

矩阵运算

column是列,row是行。

A*B \ A.dot(B)   \ np.dot(A,B):矩阵乘法

np.abs():取绝对值

array**2:数组平方

np.square():数组平方

np.sqrt():开根号

np.exp():以e为底的指数

np.log():以e为底的对数

np.log10():以10为底的对数

np.sum() \ array.sum(axis=):求和,axis=0按每列求和,axis=1按每行求和

np.mean(a,axis=) \ array.mean(axis=):求均值,axis = 0:压缩行,垂直方向,对各列求均值,返回 1* n 矩阵

  • axis 不设置值,对 m*n 个数求均值,返回一个实数
  • axis = 0:压缩行,垂直方向,对各列求均值,返回 1* n 矩阵
  • axis =1 :压缩列,水平方向,对各行求均值,返回 m *1 矩阵
a = np.array([[1, 2], [3, 4]])
print(a)
# array([[1, 2],
#        [3, 4]])
print(np.mean(a))   # 2.5
print(np.mean(a, axis=0))  # axis=0,计算每一列的均值
# array([ 2.,  3.])
print(np.mean(a, axis=1))  # 计算每一行的均值 
# array([ 1.5,  3.5])

np.max() np.min() np.ptp():返回一个数组中最大值/最小值/极差

np.argmax() np.argmin():返回一个数组中最大/最小元素的下标

np.maximum() np.minimum():将两个同维数组中对应元素中最大/最小元素构成一个新的数组

np.median(array):中位数,如果为偶数,返回中间两个元素的平均值。

np.std(array):标准差

随机模块

随机模块 np.random,主要和python官方库random模块类似

np.random.random(D0, d1,....dN)

生成[0, 1)之间指定结构的随机数

np.random.random((2, 3))

# [[ 0.86166627,  0.37756207,  0.94265883],
#  [ 0.9768257 ,  0.96915312,  0.33495431]]

np.random.rand(D0, d1, ..., DN)

给定形状的数组,并在[0,1)之间

np.random.rand(3,2)
# array([[ 0.14022471,  0.96360618],  #random
#        [ 0.37601032,  0.25528411],  #random
#        [ 0.49313049,  0.94909878]]) #random

np.random.randn(D0, d1, ..., DN)

从“标准正态分布”返回一个或多个样本

a = np.random.randn(2, 4)
# [[-0.9115162  -1.32887292 -1.02910152  0.8023337 ]
#  [-1.14456771 -0.53251834 -1.75465906 -1.25668335]]

np.random.normal(loc = 0.0,scale = 1.0,size = None)

从正态分布中抽取随机样本,其中均值为loc,方差为scale,size是形状

s = np.random.normal(0,1, 1000)
print(s.shape)  # (1000,)

np.random.randint(low, high=None, size=None, dtype='l')

生成[low,high)的随机整数,取数范围:若high不为None时,取[low,high)之间随机整数,否则取值[0,low)之间随机整数。

a = np.random.randint(5, size=(2, 4))
# array([[4, 0, 2, 1],
#        [3, 2, 2, 0]])

b = np.random.randint(5,10,size=(2, 4))
# [[6 9 8 5]
#  [8 8 6 8]]

np.random.uniform(low=0.0, high=1.0, size=None)

功能:从一个均匀分布[low,high)中随机采样,注意定义域是左闭右开,即包含low,不包含high.

参数: 

  • low: 采样下界,float类型,默认值为0;
  • high: 采样上界,float类型,默认值为1;
  • size: 输出样本数目,为int或元组(tuple)类型,例如,size=(m,n,k), 则输出m*n*k个样本,缺省时输出1个值。

np.random.choice(a, size=None, replace=True, p=None)

从序列中获取元素,若a为整数,元素取值为np.range(a)中随机数;若a为数组,取值为a数组元素中随机元素。

  • size:表示从a中随机选取size个数
  • replace: 抽样之后是否放回,False不放回抽样,True放回抽样。
  • p:表示每个元素被抽取的概率,如果没有指定,a中所有元素被选取的概率是相等的。

np.ranodm.sample(list, num)  # 从list中随机获取num个元素

np.random.shuffle(x)

对X进行重排序,如果X为多维数组,只沿第一条轴洗牌(横轴),输出为None。

arr = np.arange(9).reshape((3, 3))
# [[0 1 2]
#  [3 4 5]
#  [6 7 8]]
np.random.shuffle(arr)
# [[3 4 5]
#  [0 1 2]
#  [6 7 8]]

np.random.seed(seed=None)    # 种下随机种子,使得生成的随机数相同

卷积

a = [1 2 3 4 5]  原数组
b = [8 7 6]    卷积核数组 kernel

使用b作为卷积核对a数组做一维卷积运算的过程如下:

            44 65 86         有效卷积 (valid)
         23 44 65 86 59      同维卷积 (same)
      8  23 44 65 86 59 30   完全卷积 (full)
0  0  1  2  3  4  5  0  0
6  7  8
   6  7  8
      6  7  8
         6  7  8
            6  7  8
               6  7  8
                  6  7  8

c = np.convolve(a, b, '卷积类型')

使用卷积函数numpy.convolve(a, b, 卷积类型)实现5日均线

sma52 = np.convolve( closing_prices, np.ones(5) / 5, 'valid')
mp.plot(dates[4:], sma52, c='limegreen', alpha=0.5, linewidth=6, label='SMA-5(2)')

加权卷积

使用卷积函数numpy.convolve(a, b, 卷积类型)实现加权5日均线

# 实现加权卷积
# 通过指数函数,寻求一组卷积核 
kernel = np.exp(np.linspace(-1, 0, 5))
kernel = kernel[::-1]
kernel /= kernel.sum()
print(kernel)
sma53 = np.convolve(closing_prices, kernel, 'valid')
mp.plot(dates[4:], sma53, label='SMA-5(3)', linewidth=1, color='violet', linestyle='-')

时间数据处理

import numpy as np
import datetime as dt

# 转换器函数:将日-月-年格式的日期字符串转换为星期
def dmy2wdays(dmy):
    dmy = str(dmy, encoding='utf-8')
    d = dt.datetime.strptime(dmy, '%d-%m-%Y').date()
    wday = d.weekday()
    return wday


# 加载文件,第一列 wdays时间数据
wdays, closing_prices = np.loadtxt('./aapl.csv', delimiter=',', usecols=(1), unpack=True, converters={1: dmy2wdays})
print(wdays)
# [4. 0. 1. 2. 3. 4. 0. 1. 2. 3. 4. 0. 1. 2. 3. 4. 1. 2. 3. 4. 0. 1. 2. 3. 4. 0. 1. 2. 3. 4.]

日月年转年月日

def dmy2ymd(dmy):
    # 把日月年字符串转为年月日字符串
    print(dmy)      # b'11-03-2011'
    dmy = str(dmy, encoding='utf-8')
    d = dt.datetime.strptime(dmy, '%d-%m-%Y').date()
    ymd = d.strftime('%Y-%m-%d')
    print(ymd)      # 2011-03-11
    return ymd

复制的区别

地址复制:通过 b = a 复制 a 的值,b 与 a 指向同一地址,改变 b 同时也改变 a。

a = np.arange(12)
b = a
print(a is b)

print(a.shape)
print(b.shape)
b.shape = (3,4)
print(a.shape)
print(b.shape)

# True
# (12,)
# (12,)
# (3, 4)
# (3, 4)
View Code

复制值:通过 a.view() 仅复制值,当对 c 值进行改变会改变 a 的对应的值,而改变 c 的 shape 不改变 a 的 shape,只有值会变,矩阵结构不变

a = np.arange(12)# [ 0  1  2  3  4  5  6  7  8  9 10 11]
c = a.view()
print(c is a)

c.shape = (2,6)
c[0,0] = 9999

print(a)
print(c)

# False
# [9999    1    2    3    4    5    6    7    8    9   10   11]
# [[9999    1    2    3    4    5]
# [   6    7    8    9   10   11]]
View Code

完全拷贝:a.copy() 进行的完整的拷贝,产生一份完全相同的独立的复制

a = np.arange(12)
c = a.copy()
print(c is a)

c.shape = 2,6
c[0,0] = 9999

print(a)
print(c)

# False
# [ 0  1  2  3  4  5  6  7  8  9 10 11]
# [[9999    1    2    3    4    5]
# [   6    7    8    9   10   11]]
View Code

 

 

参考文献

参考博客

NumPy官方文档

CSDN博客Numpy之random学习

numpy中pad函数的常用方法

posted @ 2019-01-16 11:25  凌逆战  阅读(911)  评论(1编辑  收藏  举报