Numpy之ndarray基础篇
NumPy(Numerical Python) 是 Python 语言的一个扩展程序库,支持大量的维度数组与矩阵运算,此外也针对数组运算提供大量的数学函数库。是在学习机器学习、深度学习之前应该掌握的一个非常基本且实用的Python库。本文章将围绕ndarray这一重要数据结构介绍Numpy的各种使用方法。
ndarray基础
NumPy(Numerical Python) 是 Python 语言的一个扩展程序库,支持大量的维度数组与矩阵运算,此外也针对数组运算提供大量的数学函数库。是在学习机器学习、深度学习之前应该掌握的一个非常基本且实用的Python库。
初见ndarray对象
ndarray基本概念
ndarray是numpy库中的一个处于核心地位的数据结构,全称为N-Dimension Array
,从字面上就表明了它是一个N维数组。要注意的是,ndarray是同质的,就是说其中的元素都必须是同一种数据类型(PS: python中的list列表是异质的)
ndarray实例化后,包含一些基本属性,如shape、ndim、size、dtype等。例如现在有一个3行5列的矩阵(ndarray)如下:
array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14]])
那么该ndarray的shape值为(3,5)
(元组类型,表示3行5列)
ndim为2(表示矩阵维度为2)
size为15(矩阵总共有15个元素)
dtype为int32(因为矩阵中的元素都是32位整数)
# 导入numpy并取别名为np
import numpy as np
# 构造ndarray
a = np.arange(15).reshape(3, 5)
# 打印a的shape,ndim,size,dtype
print(a.shape)
print(a.ndim)
print(a.size)
print(a.dtype)
ndarray对象实例化的方法
实例化ndarray的最常用的方法就是使用array函数,用list对象作为参数传递,返回以list中的内容为初始值的ndarray对象:
import numpy as np
# 使用列表作为初始值,实例化ndarray对象a
a = np.array([2,3,4])
# 打印ndarray对象a
print(a)
除了array以外比较常用的实例化函数还有zeros、ones、empty,这三个函数的参数都是表示返回ndarray对象形状的元组
zeros返回一个全为0的ndarray对象:
import numpy as np
# 实例化ndarray对象a,a是一个3行4列的矩阵,矩阵中元素全为0
a = np.zeros((3, 4))
# 打印ndarray对象a
print(a)
ones与上类似,返回一个全为1的ndarray对象:
import numpy as np
# 实例化ndarray对象a,a是一个3行4列的矩阵,矩阵中元素全为1
a = np.ones((3, 4))
# 打印ndarray对象a
print(a)
empty则是返回一个元素的值没有经过初始化的ndarray:
import numpy as np
# 实例化ndarray对象a,a是一个2行3列的矩阵,矩阵中元素全为随机值
a = np.empty((2, 3))
# 打印ndarray对象a
print(a)
还有两个比较常用的生成一维数组的函数arange、linspace:
arange参数与range类似,只不过生成的是一维ndarray对象:
linspace用于生成等间隔的一组数,前两个参数是生成的区间,第三个参数是生成的数的个数
ndarray形状操作
ndarray的数组与一般的数组列表的一个不同之处就是它可以变换形状,这使得一些数据处理的操作变得尤为方便。最直接粗暴的变换方法就是修改shape属性的值
import numpy as np
a = np.zeros((3, 4))
# 直接修改shape属性
a.shape = [4, 3]
但这样做不符合编程规范,更优雅的方法是使用ndarray对象提供的方法reshape。该方法(及其他大部分方法都)有两种调用方式,一种是直接作为函数调用,参数为ndarray对象及形状元组;另一种是作为ndarray实例的成员函数来调用。
面向对象风格
import numpy as np
a = np.zeros((3, 4))
# 调用a的成员函数reshape将3行4列改成4行3列
a = a.reshape((4, 3))
面向过程风格
import numpy as np
a = np.zeros((3, 4))
# 调用reshape函数将a变形成4行3列
a = np.reshape(a, (4, 3))
另外,reshape有一个非常方便的功能就是可以自动判断某一维上的长度。例如要将一个6行8列的二维数组变化成2列,那么只要在未知的维上传入参数-1,reshape就会自动得出变化后的数组应为24行
import numpy as np
a = np.zeros((6, 8))
# 行的维度上填-1,会让numpy自己去推算出行的数量,很明显,行的数量应该是24
a = a.reshape((-1, 2))
不过最多只有一个维度能填-1,如果超过一个维度是-1就会抛出异常
PS:要注意reshape并不会改变原ndarray的形状,而只是返回变化后的ndarray对象,所以需要将其赋值给原变量。
如果想要直接改变原ndarray的形状,除了之前的直接修改shape属性,可以使用resize方法:
import numpy as np
a = np.zeros((3, 4))
# 将a从3行4列的二维数组变成一个有12个元素的一维数组
a.resize(12)
ndarray基础操作
作为数据处理的利器,ndarray自然提供了常用的数学的处理功能。
基本运算
ndarray可以直接和基本的数字类型变量运算,返回该运算作用到数组中所有元素上的结果。
import numpy as np
a = np.array([0, 1, 2, 3])
# a中的所有元素都加2,结果为[2, 3, 4, 5]
b = a + 2
# a中的所有元素都减2,结果为[-2, -1, 0, 1]
c = a - 2
# a中的所有元素都乘以2,结果为[0, 2, 4, 6]
d = a * 2
# a中的所有元素都平方,结果为[0, 1, 4, 9]
e = a ** 2
# a中的所有元素都除以2,结果为[0, 0.5, 1, 1.5]
f = a / 2
# a中的所有元素都与2比,结果为[True, True, False, False]
g = a < 2
ndarray与ndarray之间也可以运算,返回两个数组中对应位置元素相互作用的结果。
import numpy as np
a = np.array([[0, 1], [2, 3]])
b = np.array([[1, 1], [3, 2]])
# a与b逐个元素相加,结果为[[1, 2], [5, 5]]
c = a + b
# a与b逐个元素相减,结果为[[-1, 0], [-1, 1]]
d = a - b
# a与b逐个元素相乘,结果为[[0, 1], [6, 6]]
e = a * b
# a的逐个元素除以b的逐个元素,结果为[[0., 1.], [0.66666667, 1.5]]
f = a / b
# a与b逐个元素做幂运算,结果为[[0, 1], [8, 9]]
g = a ** b
# a与b逐个元素相比较,结果为[[True, False], [True, False]]
h = a < b
PS:当运算的两个ndarray形状不同时,会触发Numpy的广播(broadcasting)机制尝试将两个ndarray自动拓展成相同形状。关于广播机制将在下一篇文章中讲解。
上述运算都是逐个元素进行运算,如果想要进行数学中的矩阵乘这种运算,可以使用Numpy提供的运算符@或函数dot。
import numpy as np
A = np.array([[1, 1], [0, 1]])
B = np.array([[2, 0], [3, 4]])
# @表示矩阵乘法,矩阵A乘以矩阵B,结果为[[5, 4], [3, 4]]
print(A @ B)
# 面向对象风格,矩阵A乘以矩阵B,结果为[[5, 4], [3, 4]]
print(A.dot(B))
# 面向过程风格,矩阵A乘以矩阵B,结果为[[5, 4], [3, 4]]
print(np.dot(A, B))
简单统计
在一般的数组中进行统计需要手动用循环遍历整个数组,而ndarray为了解放程序员们的双手,提供了sum、min、max、argmax、argmin等方法实现简单的统计功能。
import numpy as np
a = np.array([[-1, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 13]])
# 计算a中所有元素的和,结果为67
print(a.sum())
# 找出a中最大的元素,结果为13
print(a.max())
# 找出a中最小的元素,结果为-1
print(a.min())
# 找出a中最大元素在a中的位置,由于a中有12个元素,位置从0开始计,所以结果为11
print(a.argmax())
# 找出a中最小元素在a中位置,结果为0
print(a.argmin())
当需要按某一个方向/轴来进行统计时,可以向这些方法传入axis参数。例如有一个学生成绩表如下,要统计出每一名学生的总分:
姓名 | 语文 | 数学 | 英语 | 物理 | 化学 | 政治 | 历史 |
---|---|---|---|---|---|---|---|
张三 | 90 | 112 | 104 | 84 | 89 | 77 | 80 |
李四 | 105 | 109 | 114 | 81 | 81 | 87 | 92 |
王五 | 93 | 103 | 97 | 79 | 75 | 80 | 79 |
用ndarray存储如下
a=np.array([[ 90, 112, 104, 84, 89, 77, 80],
[ 105, 109, 114, 81, 81, 87, 92],
[ 93, 103, 97, 79, 75, 80, 79]])
那么要做的就是统计每一行的和,沿着横轴把元素相加,axis为所沿轴的序号
其余方法以及更高维的数组同理。
PS:当没有修改axis时,axis的值默认为None。意思是在统计时会把ndarray对象中所有的元素都考虑在内。
随机数生成
简单随机数生成
NumPy的random模块下提供了许多生成随机数的函数,如果对于随机数的概率分布没有什么要求,则通常可以使用random_sample、choice、randint等函数来实现生成随机数的功能。这些函数的功能都和Python标准库random 中的类似,只不过是作用在ndarray对象上或返回ndarray。
random_sample:用于生成区间为 [ 0 , 1 ] [0,1] [0,1]的随机数,参数size为生成ndarray的形状。
import numpy as np
'''
结果可能为[[0.32343809, 0.38736262, 0.42413616]
[0.86190206, 0.27183736, 0.12824812]]
'''
print(np.random.random_sample(size=[2, 3]))
choice:从给定范围的数字中随机挑选生成ndarray。参数a是一维数组或整数,给定一维数组时生成ndarray中的元素将从中随机选取,给定整数时则从np.arange(a)中随机选取;参数size为生成ndarray形状;参数replace决定是否能有重复元素,默认值为True即允许重复。
import numpy as np
'''
模拟掷5次骰子
掷骰子时可能出现的点数为1, 2, 3, 4, 5, 6,所以a=[1,2,3,4,5,6]
模拟5次掷骰子所以size=5
骰子点数可以重复出现所以replace=True
结果可能为 [4 3 1 4 3]
'''
print(np.random.choice(a=[1, 2, 3, 4, 5, 6], size=5,replace=True))
PS:当生成ndarray中元素数量多于a且replace=False时会抛出异常ValueError: Cannot take a larger sample than population when ‘replace=False’
randint:生成选定区间内的整数随机选取产生的ndarray。参数low、high为区间的上下限,区间为半开半闭区间 [ l o w , h i g h ) [low,high) [low,high);参数size为生成数组形状。
import numpy as np
'''
模拟掷5次骰子
掷骰子时可能出现的点数为1, 2, 3, 4, 5, 6,所以low=1,high=7
模拟5此掷骰子所以size=5
结果可能为 [6, 4, 3, 1, 3]
'''
print(np.random.randint(low=1, high=7, size=5)
概率分布随机数生成
如果对于产生的随机数的概率分布有特别要求,NumPy同样提供了从指定的概率分布中采样得到的随机值的接口。在这里主要介绍正态分布。
正态分布又称为高斯分布,其分布图形如下:
要根据正态分布产生随机数,可以使用normal函数。该函数的参数有loc、scale、size,分别是正态分布的均值、方差和生成数组的形状。默认情况下loc=0,scale=1,即标准正态分布。
随机种子
众所周知计算机无法产生真正的随机数,所有计算机产生的随机数本质都是伪随机数,其结果由随机种子决定。Numpy中手动设定随机种子的方法就是使用seed函数,其参数为seed。
import numpy as np
# 设置随机种子为233
np.random.seed(seed=233)
data = [1, 2, 3, 4]
# 随机从data中挑选数字,结果为4
print(np.random.choice(data))
# 随机从data中挑选数字,结果为4
print(np.random.choice(data))
更多推荐
所有评论(0)