Python之numpy详细教程

Numpy学习笔记

Numpy介绍

Python之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”的集合。

Python之numpy详细教程
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列表可以存储一维数组,通过列表的嵌套可以实现多维数组,那么为什么还需要使用Numpyndarray呢?

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也在机器学习领域达不到好的效果。

Python之numpy详细教程
Numpy专门针对ndarray的操作和运算进行了设计,所以数组的存储效率和输入输出性能远优于Python中的嵌套列表,数组越大,Numpy的优势就越明显。

ndarray为什么可以这么快?

ndarray的优势

内存块风格

ndarray到底跟原生python列表有什么不同呢,请看一张图:

Python之numpy详细教程
从图中我们可以看出ndarray在存储数据的时候,数据与数据的地址都是连续的,这样就给使得批量操作数组元素时速度更快。

这是因为ndarray中的所有元素的类型都是相同的,而Python列表中的元素类型是任意的,所以ndarray在存储元素时内存可以连续,而python原生list就只能通过寻址方式找到下一个元素,这虽然也导致了在通用性能方面Numpyndarray不及Python原生list,但在科学计算中,Numpyndarray就可以省掉很多循环语句,代码使用方面比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)

Python之numpy详细教程
在上面的程序中只涉及 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 开始。

语法格式如下:

Python之numpy详细教程Python之numpy详细教程
ndmin 参数的使用

import numpy as np 
a=np.array([1,2,3,4,5,6],ndmin=3) 
print(a)

Python之numpy详细教程

dtype 参数的使用

a=np.array([1,2,3,4,5,6],dtype=complex) 
print(a)

Python之numpy详细教程

ndarray的属性

数组属性反映了数组本身固有的信息。

Python之numpy详细教程

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) # 三维数组

如何理解数组的形状?

二维数组:

Python之numpy详细教程
三维数组:

Python之numpy详细教程

ndarray的类型

>>> type(score.dtype) 
<type 'numpy.dtype'>

dtypenumpy.dtype类型,先看看对于数组来说都有哪些类型:

Python之numpy详细教程
创建数组的时候指定类型

>>> 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

总结

数组的基本属性

Python之numpy详细教程

基本操作

生成数组的方法

生成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')

Python之numpy详细教程
empty 创建

x=np.empty([3,2],dtype=int) 
print(x)

Python之numpy详细教程

从现有数组生成

生成方式

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的不同

Python之numpy详细教程Python之numpy详细教程

生成固定范围的数组

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])

Python之numpy详细教程

np.logspace(start,stop, num)

  • 创建等比数列
  • 参数:
    • num:要生成的等比数列数量,默认为50
# 生成10^x 
np.logspace(0, 2, 3)

返回结果:

array([ 1., 10., 100.])

生成随机数组

使用模块介绍np.random模块

正态分布

什么是正态分布?

正态分布是一种概率分布。正态分布是具有两个参数μ和σ的连续型随机变量的分布,第一参数μ是服从正态分布的随机变量的均值,第二个参 数σ是此随机变量的标准差,所以正态分布记作N(μ,σ )。

Python之numpy详细教程
正态分布的应用

生活、生产与科学实验中很多随机变量的概率分布都可以近似地用正态分布来描述。

正态分布特点

μ决定了其位置,其标准差σ决定了分布的幅度。当μ = 0,σ = 1时的正态分布是标准正态分布。

标准差如何来?

  • 方差
    是在概率论和统计方差衡量一组数据时离散程度的度量
    Python之numpy详细教程
    其中M为平均值,n为数据总个数,σ 为标准差,σ ^2可以理解一个整体为方差

Python之numpy详细教程

  • 标准差与方差的意义
    可以理解成数据的一个离散程度的衡量

Python之numpy详细教程
正态分布创建方式

  • 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()

Python之numpy详细教程
例如:我们可以模拟生成一组股票的涨跌幅的数据

举例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()

Python之numpy详细教程

均匀分布

  • 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()

Python之numpy详细教程

数组的索引、切片

ndarray 对象的内容可以通过索引或切片来访问和修改,与 Pythonlist 的切片操作 一样。

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])

Python之numpy详细教程

形状修改

处理数组的一项重要工作就是改变数组的维度,包含提高数组的维度和降低数组的维度,还包括数组的转置。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_andnp.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)

统计运算

如果想要知道学生成绩最大的分数,或者做小分数应该怎么做?

统计指标

在数据挖掘/机器学习领域,统计指标的值也是我们分析问题的一种方式。常用的指标如下:

Python之numpy详细教程

案例:学生成绩统计运算

进行统计的时候,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)

Python之numpy详细教程

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

Python之numpy详细教程
现在将数组 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)

Python之numpy详细教程

垂直分隔数组

垂直分隔数组是垂直组合数组的逆过程。垂直组合数组是将两个或多个数组垂直进行首尾相接,而垂直分隔数组是将已经垂直组合到一起的数组再分开。

使用 vsplit 函数可以垂直分隔数组,该函数有两个参数,第 1 个参数表示待分隔的数组, 第 2 个参数表示将数组垂直分隔成几个小数组。

示例如下,一个 4*3 的二维数组 X。

Python之numpy详细教程Python之numpy详细教程

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()函数返回指定数字的四舍五入值。

Python之numpy详细教程

聚合函数

NumPy 提供了很多统计函数,用于从数组中查找最小元素,最大元素,百分位标准差 和方差等。 具体如下:

Python之numpy详细教程Python之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列。

Python之numpy详细教程
这句话乃是理解广播的核心。广播主要发生在两种情况,一种是两个数组的维数不相等,但是它们的后缘维度的轴长相符,另外一种是有一方的长度为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。

Python之numpy详细教程
可以看到,数组 A 和数组 B 在水平方向首尾连接了起来,形成了一个新的数组。这就是数组的水平组合。多个数组进行水平组合的效果类似。但数组水平组合必须要满足一个条件,就是所有参与水平组合的数组的行数必须相同,否则进行水平组合会抛出异常。

垂直数组组合

通过 vstack 函数可以将两个或多个数组垂直组合起来形成一个数组,那么什么叫数组的垂直组合呢?

现在以两个 2*3 的数组 A 和 B 为例

Python之numpy详细教程
Python之numpy详细教程

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))

Python之numpy详细教程

hstack&vstack

numpy.hstack 它通过水平堆叠来生成数组。
numpy.vstack 它通过垂直堆叠来生成数组。

vstack 与 hstack 实现数组的拼接

print('x 轴方向及垂直堆叠') 
print(np.vstack([a,b])) 
print('y 轴方向及水平堆叠') 
print(np.hstack([a,b]))

Python之numpy详细教程
注意如果拼接的行和列数目不同,则会报错

三维数组的拼接

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
Python之numpy详细教程
矩阵的维数即行数×列数

矩阵元素(矩阵项):

Python之numpy详细教程
Aij 指第 i 行,第 j 列的元素。

向量

向量是一种特殊的矩阵,讲义中的向量一般都是列向量,下面展示的就是三维列向量(3×1)。

Python之numpy详细教程

加法和标量乘法

Python之numpy详细教程

矩阵向量乘法

矩阵和向量的乘法如图:m×n 的矩阵乘以 n×1 的向量,得到的是 m×1 的向量

例:

Python之numpy详细教程

1 * 1+3 * 5 = 16
4 * 1+0 * 5 = 4
2 * 1+1 * 5 = 7

矩阵乘法遵循准则:

(M行, N列)*(N行, L列) = (M行, L列)

矩阵乘法

Python之numpy详细教程
Python之numpy详细教程

矩阵乘法的性质

Python之numpy详细教程

逆&转置

Python之numpy详细教程Python之numpy详细教程

矩阵乘法

Python之numpy详细教程

  • np.matmul
  • np.dot

Python之numpy详细教程
np.matmulnp.dot的区别:

二者都是矩阵乘法。 np.matmul中禁止矩阵与标量的乘法。 在矢量乘矢量的內积运算中,np.matmunp.dot没有区别。

内容有点多,整理了很久,小累。

加油!

感谢!

努力!

上一篇:【TPC-DS】每条querySql释义


下一篇:虾米音乐爬虫