Numpy学习笔记
- Numpy介绍
- Numpy安装
- N维数组-ndarray
- 基本操作
- ndarray运算
- 数组间运算
- 数学:矩阵
Numpy介绍
NumPy(Numerical Python) 是科学计算基础库,提供大量科学计算相关功能,比如数据 统计,随机数生成等。其提供最核心类型为多维数组类型(ndarray),支持大量的维度数组 与矩阵运算,Numpy 支持向量处理 ndarray 对象,提高程序运算速度。
Numpy(Numerical Python)是一个开源的Python科学计算库,用于快速处理任意维度的数组。
Numpy支持常见的数组和矩阵操作。对于同样的数值计算任务,使用Numpy比直接使用Python要简洁的多。
Numpy使用ndarray对象来处理多维数组,该对象是一个快速而灵活的大数据容器。
ndarray介绍
NumPy provides an N-dimensional array type, the ndarray,
which describes a collection of “items” of the same type.
NumPy提供了一个N维数组类型ndarray,它描述了相同类型的“items”的集合。
用ndarray进行存储:
import numpy as np
# 创建ndarray
score = np.array(
[[80, 89, 86, 67, 79],
[78, 97, 89, 67, 81],
[90, 94, 78, 67, 74],
[91, 91, 90, 67, 69],
[76, 87, 75, 67, 86],
[70, 79, 84, 67, 84],
[94, 92, 93, 67, 64],
[86, 85, 83, 67, 80]])
score
返回结果:
array([[80, 89, 86, 67, 79],
[78, 97, 89, 67, 81],
[90, 94, 78, 67, 74],
[91, 91, 90, 67, 69],
[76, 87, 75, 67, 86],
[70, 79, 84, 67, 84],
[94, 92, 93, 67, 64],
[86, 85, 83, 67, 80]])
提问:
使用Python列表可以存储一维数组,通过列表的嵌套可以实现多维数组,那么为什么还需要使用Numpy的ndarray呢?
ndarray与Python原生list运算效率对比
在这里我们通过一段代码运行来体会到ndarray的好处
import random
import time
import numpy as np
a = [] for i in range(100000000):
a.append(random.random())
# 通过%time魔法方法, 查看当前行的代码运行一次所花费的时间
%time sum1=sum(a)
b=np.array(a)
%time sum2=np.sum(b)
其中第一个时间显示的是使用原生Python计算时间,第二个内容是使用numpy计算时间:
CPU times: user 852 ms, sys: 262 ms, total: 1.11 s
Wall time: 1.13 s
CPU times: user 133 ms, sys: 653 µs, total: 133 ms
Wall time: 134 ms
从中我们看到ndarray的计算速度要快很多,节约了时间。
机器学习的最大特点就是大量的数据运算,那么如果没有一个快速的解决方案,那可能现在python也在机器学习领域达不到好的效果。
Numpy专门针对ndarray的操作和运算进行了设计,所以数组的存储效率和输入输出性能远优于Python中的嵌套列表,数组越大,Numpy的优势就越明显。
ndarray为什么可以这么快?
ndarray的优势
内存块风格
ndarray到底跟原生python列表有什么不同呢,请看一张图:
从图中我们可以看出ndarray在存储数据的时候,数据与数据的地址都是连续的,这样就给使得批量操作数组元素时速度更快。
这是因为ndarray中的所有元素的类型都是相同的,而Python列表中的元素类型是任意的,所以ndarray在存储元素时内存可以连续,而python原生list就只能通过寻址方式找到下一个元素,这虽然也导致了在通用性能方面Numpy的ndarray不及Python原生list,但在科学计算中,Numpy的ndarray就可以省掉很多循环语句,代码使用方面比Python原生list简单的多。
ndarray支持并行化运算(向量化运算)
numpy内置了并行运算功能,当系统有多个核心时,做某种计算时,numpy会自动做并行计算
效率远高于纯Python代码
Numpy底层使用C语言编写,内部解除了GIL(全局解释器锁),其对数组的操作速度不受Python解释器的限制,所以,其效率远高于纯 Python代码。
Numpy安装
安装 NumPy 最简单的方法就是使用 pip 工具,语法格式如下:
pip install numpy
arange 函数测试环境安装
import numpy as np
a=np.arange(10)
print(a)
在上面的程序中只涉及 numpy 模块中的一个 arange 函数,该函数可以传入一个整数类型的参数 n,函数返回值看着像一个列表,其实返回值类型是 numpy.ndarray。这是 Numpy 中特有的数组类型。如果传入 arange 函数的参数值是 n,那么 arange 函数会返回 0 到 n-1 的 ndarray 类型的数组。
N维数组-ndarray
array 创建
numpy 模块的 array 函数可以生成多维数组。例如,如果要生成一个二维数组,需要向 array 函数传递一个列表类型的参数。每一个列表元素是一维的 ndarray 类型数组,作为二维数组的行。另外,通过 ndarray 类的 shape 属性可以获得数组每一维的元素个数(元组形式), 也可以通过 shape[n]形式获得每一维的元素个数,其中 n 是维度,从 0 开始。
语法格式如下:
ndmin 参数的使用
import numpy as np
a=np.array([1,2,3,4,5,6],ndmin=3)
print(a)
dtype 参数的使用
a=np.array([1,2,3,4,5,6],dtype=complex)
print(a)
ndarray的属性
数组属性反映了数组本身固有的信息。
ndarray的形状
首先创建一些数组。
# 创建不同形状的数组
>>> a = np.array([[1,2,3],[4,5,6]])
>>> b = np.array([1,2,3,4])
>>> c = np.array([[[1,2,3],[4,5,6]],[[1,2,3],[4,5,6]]])
分别打印出形状
>>> a.shape
>>> b.shape
>>> c.shape
(2, 3) # 二维数组
(4,) # 一维数组
(2, 2, 3) # 三维数组
如何理解数组的形状?
二维数组:
三维数组:
ndarray的类型
>>> type(score.dtype)
<type 'numpy.dtype'>
dtype是numpy.dtype类型,先看看对于数组来说都有哪些类型:
创建数组的时候指定类型
>>> a = np.array([[1, 2, 3],[4, 5, 6]], dtype=np.float32) >>> a.dtype
dtype('float32')
>>> arr = np.array(['python', 'tensorflow', 'scikit-learn', 'numpy'], dtype = np.string_)
>>> arr
array([b'python', b'tensorflow', b'scikit-learn', b'numpy'], dtype='|S12')
注意:若不指定,整数默认int64,小数默认float64
总结
数组的基本属性
基本操作
生成数组的方法
生成0和1的数组
np.ones(shape, dtype)
np.ones_like(a, dtype)
np.zeros(shape, dtype)
np.zeros_like(a, dtype)
ones = np.ones([4, 8])
ones
array([[1., 1., 1., 1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1., 1., 1., 1.]])
np.zeros_like(ones)
array([[0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0.]])
np.empy()
numpy.empty
方法用来创建一个指定形状(shape)、数据类型(dtype)且未初始化的 数组,里面的元素的值是之前内存的值:
numpy.empty(shape, dtype = float, order = 'C')
empty 创建
x=np.empty([3,2],dtype=int)
print(x)
从现有数组生成
生成方式
np.array(object, dtype)
np.asarray(a, dtype)
a = np.array([[1,2,3],[4,5,6]])
# 从现有的数组当中创建
a1 = np.array(a)
# 相当于索引的形式,并没有真正的创建一个新的
a2 = np.asarray(a)
关于array和asarray的不同
生成固定范围的数组
np.linspace (start, stop, num, endpoint)
np.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None)
- 创建等差数组 — 指定数量
-
参数:
- start:序列的起始值
- stop:序列的终止值
- num:要生成的等间隔样例数量,默认为50
- endpoint:序列中是否包含stop值,默认为ture
- retstep:如果为 True 时,生成的数组中会显示间距,反之不显示。
- dtype:ndarray 的数据类型
# 生成等间隔的数组
np.linspace(0, 100, 11)
返回结果:
array([ 0., 10., 20., 30., 40., 50., 60., 70., 80., 90., 100.])
np.arange(start,stop, step, dtype)
- 创建等差数组 — 指定步长
- 参数
- step:步长,默认值为1
np.arange(10, 50, 2)
返回结果:
array([10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48])
np.logspace(start,stop, num)
- 创建等比数列
- 参数:
- num:要生成的等比数列数量,默认为50
# 生成10^x
np.logspace(0, 2, 3)
返回结果:
array([ 1., 10., 100.])
生成随机数组
使用模块介绍:np.random
模块
正态分布
什么是正态分布?
正态分布是一种概率分布。正态分布是具有两个参数μ和σ的连续型随机变量的分布,第一参数μ是服从正态分布的随机变量的均值,第二个参 数σ是此随机变量的标准差,所以正态分布记作N(μ,σ )。
正态分布的应用
生活、生产与科学实验中很多随机变量的概率分布都可以近似地用正态分布来描述。
正态分布特点
μ决定了其位置,其标准差σ决定了分布的幅度。当μ = 0,σ = 1时的正态分布是标准正态分布。
标准差如何来?
-
方差
是在概率论和统计方差衡量一组数据时离散程度的度量
其中M为平均值,n为数据总个数,σ 为标准差,σ ^2可以理解一个整体为方差
-
标准差与方差的意义
可以理解成数据的一个离散程度的衡量
正态分布创建方式
-
np.random.randn(d0, d1, …, dn)
功能:从标准正态分布中返回一个或多个样本值 - np.random.normal(loc=0.0, scale=1.0, size=None)
loc:float
此概率分布的均值(对应着整个分布的中心centre)
scale:float
此概率分布的标准差(对应于分布的宽度,scale越大越矮胖,scale越小,越瘦高)
size:int or tuple of ints
输出的shape,默认为None,只输出一个值
np.random.standard_normal(size=None)
返回指定形状的标准正态分布的数组。
举例1:生成均值为1.75,标准差为1的正态分布数据,100000000个
x1 = np.random.normal(1.75, 1, 100000000)
返回结果:
array([2.90646763, 1.46737886, 2.21799024, ..., 1.56047411, 1.87969135, 0.9028096 ])
# 1.创建画布
plt.figure(figsize=(20, 8), dpi=100)
# 2.绘制图像
plt.hist(x1, 1000) # 1000组
# 3. 显示图像
plt.show()
例如:我们可以模拟生成一组股票的涨跌幅的数据
举例2:随机生成4支股票1周的交易日涨幅数据
4支股票,一周(5天)的涨跌幅数据,如何获取?
- 随机生成涨跌幅在某个正态分布内,比如均值0,方差1
股票涨跌幅数据的创建
# 创建符合正态分布的4只股票5天的涨跌幅数据
stock_change = np.random.normal(0, 1, (4, 5))
stock_change
array([[-0.90442265, -1.17400313, -0.25891122, -0.60057691, 0.19973249],
[-0.23449971, -1.01396609, -0.08161324, -1.61459823, -2.05132145],
[ 0.0700032 , 1.28480273, -1.17703456, 0.0929877 , -0.42675005],
[ 1.14477016, -1.16018108, 0.76815853, -0.15971892, -1.79386421]])
# 1.创建画布
plt.figure(figsize=(20, 8), dpi=100)
days = ['one', 'two', ]
# 2.绘制图像,绘制多图
for i in range(len(stock_change)):
plt.plot(stock_change[i], label='Stock'+str(i))
# 2.1.设置x轴刻度
days = ['第{}天'.format(i+1) for i in range(0, 4)]
plt.xticks(range(0, 4), days)
# 2.2.设置x,y轴标签
plt.xlabel('天数')
plt.ylabel('股价情况')
# 2.3 设置图例
plt.legend(loc=0)
# 3.显示图像
plt.show()
均匀分布
-
np.random.rand(d0, d1, …, dn)
- 返回[0.0,1.0)内的一组均匀分布的数。
-
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), 则输出mnk个样本,缺省时输出1个值。
- 返回值:ndarray类型,其形状和参数size中描述一致。
-
np.random.randint(low, high=None, size=None, dtype=‘l’)
- 从一个均匀分布中随机采样,生成一个整数或N维整数数组,
- 取数范围:若high不为None时,取[low,high)之间随机整数,否则取值[0,low)之间随机整数。
# 生成均匀分布的随机数
x2 = np.random.uniform(-1, 1, 100000000)
返回结果:
array([ 0.22411206, 0.31414671, 0.85655613, ..., -0.92972446, 0.95985223, 0.23197723])
画图看分布状况:
# 1.创建画布
plt.figure(figsize=(20, 8), dpi=100)
# 2.绘制图像
plt.hist(x2, 1000) # 1000组
# 3. 显示图像
plt.show()
数组的索引、切片
ndarray 对象的内容可以通过索引或切片来访问和修改,与 Python 中 list 的切片操作 一样。
ndarray 数组可以基于 0 - n 的下标进行索引,并设置 start, stop 及 step 参数进行,从原数组中切割出一个新数组。
一维、二维、三维的数组如何索引?
- 直接进行索引,切片
- 对象[:, :] – 先行后列
二维数组索引方式:
- 举例:获取第一个股票的前3个交易日的涨跌幅数据
# 二维的数组,两个维度
stock_change[0, 0:3]
返回结果:
array([-0.03862668, -1.46128096, -0.75596237])
三维数组索引方式:
# 三维
a1 = np.array([ [[1,2,3],[4,5,6]], [[12,3,34],[5,6,7]]])
# 返回结果
array([[[ 1, 2, 3], [ 4, 5, 6]],
[[12, 3, 34], [ 5, 6, 7]]])
# 索引、切片
>>> a1[0, 0, 1] # 输出: 2
索引为负数来获取、
print('获取最后一行')
print(a[-1])
print('行进行倒序')
print(a[::-1])
print('行列都倒序')
print(a[::-1,::-1])
形状修改
处理数组的一项重要工作就是改变数组的维度,包含提高数组的维度和降低数组的维度,还包括数组的转置。Numpy 提供的大量 API 可以很轻松地完成这些数组的操作。例如, 通过 reshape 方法可以将一维数组变成二维、三维或者多维数组。通过 ravel 方法或 flatten 方法可以将多维数组变成一维数组。改变数组的维度还可以直接设置 Numpy 数组的 shape 属性(元组类型),通过 resize 方法也可以改变数组的维度。
ndarray.reshape(shape, order)
- 返回一个具有相同数据域,但shape不一样的视图
- 行、列不进行互换
# 在转换形状的时候,一定要注意数组的元素匹配
stock_change.reshape([5, 4])
stock_change.reshape([-1,10]) # 数组的形状被修改为: (2, 10), -1: 表示通过待计算
ndarray.resize(new_shape)
- 修改数组本身的形状(需要保持元素个数前后相同)
- 行、列不进行互换
stock_change.resize([5, 4])
# 查看修改后结果
stock_change.shape
(5, 4)
ndarray.T
- 数组的转置
- 将数组的行、列进行互换
stock_change.T.shape
(4, 5)
ndarray.ravel
#使用 ravel 函数将三维的 b 变成一维的数组
a1=b.ravel()
print(a1)
print(’-’*30)
ndarray.flatten
#使用 flatten 函数将二维的 c 变成一维的数组
a2=c.flatten()
print(a2)
print('-'*30)
类型修改
ndarray.astype(type)
- 返回修改了类型之后的数组\
stock_change.astype(np.int32)
ndarray.tostring([order])或者ndarray.tobytes([order])
构造包含数组中原始数据字节的Python字节
arr = np.array([[[1, 2, 3], [4, 5, 6]], [[12, 3, 34], [5, 6, 7]]])
arr.tostring()
jupyter输出太大可能导致崩溃问题
如果遇到
IOPub data rate exceeded. The notebook server will temporarily stop sending output to the client in order to avoid crashing it. To change this limit, set the config variable
--NotebookApp.iopub_data_rate_limit
.
这个问题是在jupyer当中对输出的字节数有限制,需要去修改配置文件:
创建配置文件
jupyter notebook --generate-config
vi ~/.jupyter/jupyter_notebook_config.py
取消注释,多增加
## (bytes/sec) Maximum rate at which messages can be sent on iopub before they
# are limited.
c.NotebookApp.iopub_data_rate_limit = 10000000
但是不建议这样去修改,jupyter输出太大会崩溃
数组的去重
np.unique()
temp = np.array([[1, 2, 3, 4],[3, 4, 5, 6]])
>>> np.unique(temp)
array([1, 2, 3, 4, 5, 6])
ndarray运算
逻辑运算
# 生成10名同学,5门功课的数据
>>> score = np.random.randint(40, 100, (10, 5))
# 取出最后4名同学的成绩,用于逻辑判断
>>> test_score = score[6:, 0:5]
# 逻辑判断, 如果成绩大于60就标记为True 否则为False
>>> test_score > 60
array([[ True, True, True, False, True], [ True, True, True, False, True], [ True, True, False, False, True], [False, True, True, True, True]])
# BOOL赋值, 将满足条件的设置为指定的值-布尔索引
>>> test_score[test_score > 60] = 1
>>> test_score
array([[ 1, 1, 1, 52, 1],
[ 1, 1, 1, 59, 1],
[ 1, 1, 44, 44, 1],
[59, 1, 1, 1, 1]])
通用判断函数
np.all()
# 判断前两名同学的成绩[0:2, :]是否全及格
>>> np.all(score[0:2, :] > 60)
False
np.any()
# 判断前两名同学的成绩[0:2, :]是否有大于90分的
>>> np.any(score[0:2, :] > 80)
True
np.where(三元运算符)
通过使用np.where
能够进行更加复杂的运算
# 判断前四名学生,前四门课程中,成绩中大于60的置为1,否则为0
temp = score[:4, :4]
np.where(temp > 60, 1, 0)
复合逻辑需要结合np.logical_and
和np.logical_or
使用
# 判断前四名学生,前四门课程中,成绩中大于60且小于90的换为1,否则为0
np.where(np.logical_and(temp > 60, temp < 90), 1, 0)
# 判断前四名学生,前四门课程中,成绩中大于90或小于60的换为1,否则为0
np.where(np.logical_or(temp > 90, temp < 60), 1, 0)
统计运算
如果想要知道学生成绩最大的分数,或者做小分数应该怎么做?
统计指标
在数据挖掘/机器学习领域,统计指标的值也是我们分析问题的一种方式。常用的指标如下:
案例:学生成绩统计运算
进行统计的时候,axis 轴的取值并不一定,Numpy中不同的API轴的值都不一样,在这里,axis 0代表列, axis 1代表行去进行统计
# 接下来对于前四名学生,进行一些统计运算
# 指定列 去统计
temp = score[:4, 0:5]
print("前四名学生,各科成绩的最大分:{}".format(np.max(temp, axis=0)))
print("前四名学生,各科成绩的最小分:{}".format(np.min(temp, axis=0)))
print("前四名学生,各科成绩波动情况:{}".format(np.std(temp, axis=0)))
print("前四名学生,各科成绩的平均分:{}".format(np.mean(temp, axis=0)))
结果:
前四名学生,各科成绩的最大分:[96 97 72 98 89]
前四名学生,各科成绩的最小分:[55 57 45 76 77]
前四名学生,各科成绩波动情况:[16.25576821 14.92271758 10.40432602 8.0311892 4.32290412]
前四名学生,各科成绩的平均分:[78.5 75.75 62.5 85. 82.25]
如果需要统计出某科最高分对应的是哪个同学?
- np.argmax(temp, axis=)
- np.argmin(temp, axis=)
print("前四名学生,各科成绩最高分对应的学生下标:{}".format(np.argmax(temp, axis=0)))
结果:
前四名学生,各科成绩最高分对应的学生下标:[0 2 0 0 1]
数组的分隔
split 分隔
numpy.split
函数沿特定的轴将数组分割为子数组,格式如下:
numpy.split(ary, indices_or_sections, axis)
参数说明:
ary
:被分割的数组indices_or_sections
:如果是一个整数,就用该数平均切分,如果是一个数组,为沿轴切分的 位置。axis
:沿着哪个维度进行切向,默认为 0,横向切分。为 1 时,纵向切分。
split 分隔一维数组
import numpy as np
x=np.arange(1,9)
a=np.split(x,4)
print(a)
print(a[0])
print(a[1])
print(a[2])
print(a[3])
#传递数组进行分隔
b=np.split(x,[3,5])
print(b)
split 分隔二维数组
#导入 numpy
import numpy as np
#创建两个数组
a=np.array([[1,2,3],[4,5,6],[11,12,13],[14,15,16]])
print('axis=0 垂直方向 平均分隔')
r=np.split(a,2,axis=0)
print(r[0])
print(r[1])
print('axis=1 水平方向 按位置分隔')
r=np.split(a,[2],axis=1)
print(r)
水平分隔数组
分隔数组是组合数组的逆过程,与组合数组一样,分隔数组也分为水平分隔数组和垂直分隔数组。水平分隔数组与水平组合数组对应。水平组合数组是将两个或多个数组水平进行收尾相接,而水平分隔数组是将已经水平组合到一起的数组再分开。
使用 hsplit
函数可以水平分隔数组,该函数有两个参数,第 1 个参数表示待分隔的数组, 第 2 个参数表示要将数组水平分隔成几个小数组,现在先来看一个例子。
下面是一个 2*6 的二维数组 X
现在将数组 X 分隔成了 3 个列数都为 2 的数组,但要是使用 hsplit(X,4)
分隔数组 X 就会 抛出异常,这是因为数组 X 是没有办法被分隔成列数相同的 4 个数组的,所以使用 hsplit
函数分隔数组的一个规则就是第 2 个参数值必须可以整除待分隔数组的列数。
hsplit
grid=np.arange(16).reshape(4,4)
a,b=np.hsplit(grid,2)
print(a)
print(b)
垂直分隔数组
垂直分隔数组是垂直组合数组的逆过程。垂直组合数组是将两个或多个数组垂直进行首尾相接,而垂直分隔数组是将已经垂直组合到一起的数组再分开。
使用 vsplit
函数可以垂直分隔数组,该函数有两个参数,第 1 个参数表示待分隔的数组, 第 2 个参数表示将数组垂直分隔成几个小数组。
示例如下,一个 4*3 的二维数组 X。
vsplit
grid=np.arange(16).reshape(4,4)
a,b=np.vsplit(grid,[3])
print(a)
print(b)
print('三部分'*10)
a,b,c=np.vsplit(grid,[1,3])
print(a)
print(b)
print(c)
transpose进行转置
#transpose 进行转置
#二维转置
a=np.arange(1,13).reshape(2,6)
print('原数组 a')
print(a)
print('转置后的数组')
print(a.transpose())
#多维数组转置
aaa=np.arange(1,37).reshape(1,3,3,4)
#将 1,3,3,4 转换为 3,3,4,1
print(np.transpose(aaa,[1,2,3,0]).shape)
数组间运算
算术函数
如果参与运算的两个对象都是 ndarray,并且形状相同,那么会对位彼此之间进行(+ - * /)运算。NumPy 算术函数包含简单的加减乘除: add(),subtract(),multiply() 和 divide()
。
数学函数
NumPy
提供了标准的三角函数:sin()、cos()、tan()
。
numpy.around()
函数返回指定数字的四舍五入值。
聚合函数
NumPy
提供了很多统计函数,用于从数组中查找最小元素,最大元素,百分位标准差 和方差等。 具体如下:
numpy.mean()
函数返回数组中元素的算术平均值。 如果提供了轴,则沿其计算算术平均值是沿轴的元素的总和除以元素的数量。
numpy.power()
函数将第一个输入数组中的元素作为底数,计算它与第二个输入数组中相应元素的幂。
参考代码:
# 导入numpy模块
import numpy as np
a = np.arange(9).reshape(3, 3)
b = np.array([10, 10, 10])
print('加法')
print(np.add(a, b))
print((a+b))
print('减法')
print(np.subtract(b, a))
print(b-a)
# out参数的使用
y = np.empty((3, 3), dtype=np.int)
np.multiply(a, 10, out=y)
print(y)
# 数学函数
a = np.array([0, 30, 60, 90])
print(np.sin(a))
# around ceil floor
a = np.array([1.0, 4.55, 123, 0.567, 25.532])
print('around:', np.round(a))
print('ceil:', np.ceil(a))
print('floor', np.floor(a))
# 统计函数
# power
a = np.arange(1, 13).reshape(3, 4)
print('原函数a')
print(a)
print('power', np.power(a, 2))
# power中out的使用
x = np.arange(5)
y = np.zeros(10)
np.power(2, x, out=y[:5])
print(y)
# median()
# 一维数组的中位数
a = np.array([4, 3, 2, 5, 2, 1]) # 对数组排序 [1,2,2,3,4,5] 数组中元素个数为偶数 中位数指:中间两个数的平均值
print(np.median(a))
a=np.array([4, 3, 2, 5, 2]) # 对数组排序 [2,2,3,4,5] 数组中元素个数为奇数 中位数指:中间的数
print(np.median(a))
# 二维数组 要通过axis指定轴
a = np.arange(1, 13).reshape(3, 4)
print(a)
print('垂直方向', np.median(a, axis=0))
print('水平方向', np.median(a, axis=1))
# mean 求平均值
# 一维数组
a = np.array([4, 3, 2, 5, 2])
print(np.mean(a))
# 二维数组 axis指定轴的平均
a = np.arange(13).reshape(3, 4)
print(a)
print('axis=0 垂直方向', np.mean(a, axis=0))
print('axis=1 水平方向', np.mean(a, axis=1))
# sum() max() min()
a = np.array([4, 3, 2, 5, 2])
print('max:', np.max(a))
print('sum:', np.sum(a))
print('min:', np.min(a))
# argmax argmin : 获取最值的索引
print('argmin:', np.argmin(a))
print('argmax:', np.argmax(a))
数组与数的运算
arr = np.array([[1, 2, 3, 2, 1, 4], [5, 6, 1, 2, 3, 1]])
arr + 1
arr / 2
# 可以对比python列表的运算,看出区别
a = [1, 2, 3, 4, 5]
a * 3
数组与数组的运算
arr1 = np.array([[1, 2, 3, 2, 1, 4], [5, 6, 1, 2, 3, 1]])
arr2 = np.array([[1, 2, 3, 4], [3, 4, 5, 6]])
广播机制
数组在进行矢量化运算时,要求数组的形状是相等的。当形状不相等的数组执行算术运算的时候,就会出现广播机制,该机制会对数组进行扩展,使数组的shape属性值一样,这样,就可以进行矢量化运算了。下面通过一个例子进行说明:
arr1 = np.array([[0],[1],[2],[3]])
arr1.shape
# (4, 1)
arr2 = np.array([1,2,3])
arr2.shape
# (3,)
arr1+arr2
# 结果是:
array([[1, 2, 3],
[2, 3, 4],
[3, 4, 5],
[4, 5, 6]])
上述代码中,数组arr1是4行1列,arr2是1行3列。这两个数组要进行相加,按照广播机制会对数组arr1和arr2都进行扩展,使得数组arr1和arr2都变成4行3列。
这句话乃是理解广播的核心。广播主要发生在两种情况,一种是两个数组的维数不相等,但是它们的后缘维度的轴长相符,另外一种是有一方的长度为1。
广播机制实现了时两个或两个以上数组的运算,即使这些数组的shape不是完全相同的,只需要满足如下任意一个条件即可。
- 如果两个数组的后缘维度(trailing dimension,即从末尾开始算起的维度)的轴长度相符,
- 或其中的一方的长度为1。
广播机制会在缺失和(或)长度为1的维度上进行。
广播机制需要扩展维度小的数组,使得它与维度最大的数组的shape值相同,以便使用元素级函数或者运算符进行运算。
如果是下面这样,则不匹配:
A (1d array): 10
B (1d array): 12
A (2d array): 2 x 1
B (3d array): 8 x 4 x 3
这俩可以
arr1 = np.array([[1, 2, 3, 2, 1, 4], [5, 6, 1, 2, 3, 1]])
arr2 = np.array([[1], [3]])
数组的拼接
水平数组组合
通过 hstack 函数可以将两个或多个数组水平组合起来形成一个数组,那么什么叫做数组的水平组合。
现在有两个 2*3 的数组 A 和 B。
可以看到,数组 A 和数组 B 在水平方向首尾连接了起来,形成了一个新的数组。这就是数组的水平组合。多个数组进行水平组合的效果类似。但数组水平组合必须要满足一个条件,就是所有参与水平组合的数组的行数必须相同,否则进行水平组合会抛出异常。
垂直数组组合
通过 vstack 函数可以将两个或多个数组垂直组合起来形成一个数组,那么什么叫数组的垂直组合呢?
现在以两个 2*3 的数组 A 和 B 为例
concatenate
numpy.concatenate
函数用于沿指定轴连接相同形状的两个或多个数组,格式如下:
numpy.concatenate((a1, a2, …), axis)
参数说明:a1, a2, ...
:相同类型的数组axis
:沿着它连接数组的轴,默认为 0
concatenate 实现数组的拼接
a=np.array([[1,2,3],[4,5,6]])
print(a)
b=np.array([['a','b','c'],['d','e','f']])
print(b)
print(np.concatenate([a,b]))
print('垂直方向拼接 相当于 vstack')
print(np.concatenate([a,b],axis=0))
print('水平方向拼接 相当于 hstack')
print(np.concatenate([a,b],axis=1))
hstack&vstack
numpy.hstack
它通过水平堆叠来生成数组。numpy.vstack
它通过垂直堆叠来生成数组。
vstack 与 hstack 实现数组的拼接
print('x 轴方向及垂直堆叠')
print(np.vstack([a,b]))
print('y 轴方向及水平堆叠')
print(np.hstack([a,b]))
注意如果拼接的行和列数目不同,则会报错
三维数组的拼接
aa=np.arange(1,37).reshape(3,4,3)
print(aa)
bb=np.arange(101,137).reshape(3,4,3)
print(bb)
print('axis=0'*10)
print(np.concatenate((aa,bb),axis=0)) #6 4 3
print('axis=1'*10)
print(np.concatenate((aa,bb),axis=1)) #3,8,3
print('axis=2'*10)
print(np.concatenate((aa,bb),axis=2)) #3,4,6
axis=0 可以使用 vstack 替换
axis=1 可以使用 hstack 替换
axis=2 可以使用 dstack 替换
数学:矩阵
矩阵
矩阵,英文matrix,和array的区别矩阵必须是2维的,但是array可以是多维的。
如图:这个是 3×2 矩阵,即 3 行 2 列,如 m 为行,n 为列,那么 m×n 即 3×2
矩阵的维数即行数×列数
矩阵元素(矩阵项):
Aij 指第 i 行,第 j 列的元素。
向量
向量是一种特殊的矩阵,讲义中的向量一般都是列向量,下面展示的就是三维列向量(3×1)。
加法和标量乘法
矩阵向量乘法
矩阵和向量的乘法如图:m×n 的矩阵乘以 n×1 的向量,得到的是 m×1 的向量
例:
1 * 1+3 * 5 = 16
4 * 1+0 * 5 = 4
2 * 1+1 * 5 = 7
矩阵乘法遵循准则:
(M行, N列)*(N行, L列) = (M行, L列)
矩阵乘法
矩阵乘法的性质
逆&转置
矩阵乘法
- np.matmul
- np.dot
np.matmul
和np.dot
的区别:
二者都是矩阵乘法。 np.matmul
中禁止矩阵与标量的乘法。 在矢量乘矢量的內积运算中,np.matmu
与np.dot
没有区别。
内容有点多,整理了很久,小累。
加油!
感谢!
努力!