文章目录
基本介绍
NumPy(Numerical Python)
- 快速高效的多维数组对象ndarray
- 用于对数组执行 元素级计算 以及直接对数组执行 数学计算 的函数
- 用于读写硬盘上基于数组的数据集的工具
- 线性代数运算、傅里叶变换,以及随机数生成
- 用于将C、C++、Fortran代码集成到Python的工具
对于数值型数据,NumPy数组在存储和处理数据时要比内置的Python数据结构高效得多。此外,由低级语言(比如C和Fortran)编写的库可以直接操作NumPy数组中的数据,无需进行任何数据复制工作。
一、Numpy数据类型
ndarray的创建和变换
- ndarray创建
# 创建ndarray
np.array(d1)
np.array([1,2,3], dtype = np.float64)
np.asarray() # 将输入转换为ndarray,如果本身是ndarray则不进行转换
np.arange(n)
np.ones(shape); np.ones_like(a) # ones_like以另一个数组为参数,根据其形状和dtype创建一个全1数组
np.zeros(shape); np.zeros_like(a) # zero_like以另一个数组为参数,根据其形状和dtype创建一个全0数组
np.empty(shape); np.empty_like(a) # 创建新数组,只分配内存空间但不填充任何值
np.full(shape, val); np.full_like(a, val)
np.eye(n); np.identity() # 创建一个正方的NxN的单位矩阵,(对角线为1,其余为0)
- 属性的转换
.ndim, .shape, .size, .dtype, .itemsize
.reshape(shape)
.resize(shape)
.swapaxes(ax1, ax2)
.flatten()
- 将ndarray转换为列表
列表 是 Python中 最基础的一种类型,运算速度是没有ndarray快的,但是有时候需要与原生的python程序结合,需要转换成list
arr.tolist()
基础数据类型
类型 | 类型代码 | 说明 |
---|---|---|
int8, uint8 | i1,u1 | 有符号和无符号的8位(1个字节)整型 |
int 16, uint16 | i2, u2 | 有符号和无符号的16位(2个字节)整型 |
int32, uint32 | i4,u4 | 有符号和无符号的32位(4个字节)整型 |
int64, uint64 | i8, u8 | 有符号和无符号的64位(8个字节)整型 |
float16 | f2 | 半精度浮点数 |
float32 | f4或f | 标准的单精度浮点数,与C的float兼容 |
float64 | f8或d | 标准的双精度浮点数,与C的double和Python的float对象兼容 |
float128 | f16或g | 扩展精度浮点数 |
complex64, complex128, complex256 | c8、c16、c32 | 分别用32位、64位或128位浮点数表示的复数 |
bool | ? | 存储True和False值的布尔类型 |
object | O | Python对象类型 |
string_ | S | 固定长度的字符串类型(每个字符1个字节)。例如,哟啊创建一个长度为10的字符串,应使用S10 |
unicode_ | U | 固定长度的unicode类型(字节数由平台决定),跟字符串的定义方法一样(如U10) |
- 可以在创建numpy的时候显式地指定数据类型
arr1 = np.array([1,2,3], dtype=np.float64)
arr2 = np.array([1,2,3], dtype=np.int32)
arr1.dtype
arr2.dtype
- 可以通过 ndarray 的 astype 方法,显式地 转换其 dtype
使用astype一定会创建出一个新的数组(原数组的一个拷贝),即使新的dtype跟老的相同
arr2 = arr1.astype(np.float64)
- 或者可以用一个arr1的数据类型,去定义 另一个arr2
arr2.astype(arr1.dtype) ---> astype 会创建出一个新的数据(原始数据的一份拷贝)
广播运算介绍 broadcasting
数组很重要,因为它使你不用编写循环即可对数据执行批量运算
,这通常就叫作矢量化(vectorization)。
-
一般来说,矢量化的方法要比纯Python方式快上一两个数量级。(尤其是各种数值计算)
-
数据与标量、相同shape的数组之间的任何算数运算,都是
元素级的运算
-
shape不同的数组之间的运算 叫
广播(broadcasting)
数组的切片和索引
- ndarray 的索引和切片
与列表最重要的区别在于,数组切片是原始数组的视图。这意味着数据不会被复制,视图上的任何修改都会直接反映到原数组上。
由于NumPy的设计目的是处理大数据,所以你可以想象一下,如果NumPy坚持要将数据复制来复制去的话会产生何等的性能和内存问题。
如果你需要得到的是ndarray切片的一份副本而非视图,就需要显式地进行复制操作,例如arr[5:8].copy()
- 对 嵌套数组 的 索引
arr2[0][2] 等价于 arr2[0, 2]
- 布尔型索引
布尔型数组的长度必须跟被索引的轴的长度一致。
布尔型索引的数组本身由判断产生,判断条件可以用&(和)、|(或)之类的布尔算数运算符。
通过布尔型索引选取数组中的数据,将总是创建数据副本,即使返回一模一样的数组也是如此。
data[name == 'Bob']
data[(name == 'Bob') | (name == 'Will')]
data[~(name == 'Bob')] 取非
data[data<0]
- 花式索引 Fancy indexing
是一个Python术语,是指利用整数数组进行索引。花式索引选取的结果也是创建副本。
import numpy as np
arr = np.empty((8,4))
for i in range(8):
arr[i] = i
arr[[5,4,3,2]] # 花式索引
arr[[-2,-3,-1]] # 负数是从末尾开始索引
- 布尔型数组
(arr > 0).sum()
bools.any() # any用于测试数组中是否存在一个或多个True
bools.all() # all检查数组中所有值是否都是True
二、Numpy常用操作
数组转置和轴对换
转置(transpose)是重塑的一种特殊形式,它返回的是源数据的视图(不会进行任何的复制操作)
arr = np.arange(15).reshape((3,5))
arr.T
# 计算矩阵的内积
arr = np.random.randn(6,3)
np.dot(arr.T, arr)
对于高维数组,transpose需要得到一个由轴编号组成的元组,才能对这些轴进行转置。
arr = np.arange(16).reshape((2,2,4))
arr.transpose((1,0,2))
ndarray还有一个swapaxes方法(需要接受一对轴编号)
arr.swapaxes(1,2)
排序
arr.sort()
- sort可以传入一个轴编号参数,可以在任意一个轴上进行排序- np.sort()返回排序后的副本, arr.sort()直接修改原数组,将其排序
sort
arr.sort()
'''
多维数组 可以在任何一个轴上 进行排序,只需将 轴编号 传给 sort即可。
函数 np.sort()
注意:np.sort()返回的额是 数组的已排序副本,而sort()方法 会修改数组本身
'''
去除重复值
np.unique(arr) ---> 等价于 sorted(set(arr))
#查看独立值个数
np.nunique()
np.nunique()/np.size()
查看一个数组中的值 是否在另一个数组中
np.is1d(values, [2, 3, 5])
三、Numpy常用函数
3.1 数组操作函数
元素级函数(一元函数)
np.abs(x), np.fabs(x) # 绝对值
np.sqrt(x) # 平方根
np.square(x) # 平方
np.sign(x) # 符号值, 正数为1, 负数为-1, 0 为 0
np.exp(x) # 指数值
np.log(x), np.log10(x), np.log2(x) # 自然对数, 10底对数, 2底对数
np.log1p(x)
np.ceil(x) # 大于等于该值的 最小整数
np.floor(x) # 小于等于该值的 最大整数
np.rint(x) # 将各元素 四舍五入后 得到 最接近该值的整数,保留 dtype
np.modf(x) # 将各元素的小数和整数部分 以两个独立数组的形式返回
np.isnan() #是否是NaN的布尔型数组
np.isfinite(), np.isinf() #哪些元素是有穷的;哪些元素是无穷的
np.sin(x), np.sinh(x) # 普通型 和 双曲型 三角函数
np.cos(x), np.cosh(x) # 普通型 和 双曲型 三角函数
np.tan(x), np.tanh(x) # 普通型 和 双曲型 三角函数
np.arccos(), np.arccosh(), np.arcsin(), np.arcsinh(), np.arctanh() # 反三角函数
logical_not # 计算各元素 not x 的真值 相当于 -arr
#e.g.
np.modf(10.45) # 输出值为 (0.4499999999999993, 10.0)
二元函数
add, subtract, multiply, divide, floor_divide, power
+, -, *, /, ** # 两个数组各元素进行对应运算;其中power是 对第一个数组中的元素A,根据第二个数组中的相应元素B,计算A^B
np.maximum(x,y), np.fmax() # 元素及最大值计算,fmax将忽略NaN
np.minimum(x,y), np.fmin() # 元素及最小值计算,fmin将忽略NaN
np.mod(x,y) # 元素级的 求模计算(除法的余数)
np.copysign(x, y) #将 第二个数组中的值的符号赋值给 第一个数组中的值
greater, greater_equal, less, less_equal, equal, not_equal
>, <, >=, <=, ==, != # 算数比较, 产生布尔型数组
logical_and, logical_or, logical_xor #元素级的 与或非 ,相当于 & 、| 、 ^
- 示例
import numpy as np
x1 = np.arange(1,11,2)
x2 = np.linspace(1,9,5)
'''
array([1, 3, 5, 7, 9])
array([1., 3., 5., 7., 9.])
'''
print(np.add(x1, x2))
print(np.subtract(x1, x2))
print(np.multiply(x1, x2))
print(np.divide(x1, x2))
print(np.power(x1, x2))
print(np.remainder(x1, x2))
'''
[ 2. 6. 10. 14. 18.]
[0. 0. 0. 0. 0.]
[ 1. 9. 25. 49. 81.]
[1. 1. 1. 1. 1.]
[1.00000000e+00 2.70000000e+01 3.12500000e+03 8.23543000e+05
3.87420489e+08]
[0. 0. 0. 0. 0.]
'''
数组的集合运算
方法 | 说明 |
---|---|
unique(x) | 计算x中的唯一元素,并返回有序结果 |
intersect1d(x,y) | 计算x和y中的公共元素,并返回有序结果 |
union1d(x,y) | 计算x和y的并集,并返回有序结果 |
in1d(x,y) | 得到一个表示“x的元素是否包含于y”的布尔型数组 |
setdiff1d(x,y) | 集合的差,即元素在x中且不在y中 |
setxor1d(x,y) | 集合的对称差,即 存在于一个数组中但不同时存在于两个数组中的元素 |
3.2 统计函数(聚合)
基本的数组统计方法 (可以指定axis )
np.sum(), np.mean(), np.std(), np.var()
np.average() # 通过 np.average,可以指定平均数计算过程中的权重
np.median()
np.percentile() #百分位数
np.min(), np.max(), np.argmin(), np.argmax() # argmin, argmax --> 分别为最大和最小元素的索引
np.unravel_index()
np.ptp()
np.cumsum() #所有元素的累计和
np.sumprod() #所有元素的累计积
- 示例
a = np.array([[1,2,3], [4,5,6], [7,8,9]])
print(np.min(a))
print(np.min(a,0))
print(np.min(a,1))
print(np.max(a))
print(np.max(a,0))
print(np.max(a,1))
'''
1
[1 2 3]
[1 4 7]
9
[7 8 9]
[3 6 9]
'''
# 求中位数
print(np.median(a))
print(np.median(a, axis=0))
print(np.median(a, axis=1))
# 求平均数
print(np.mean(a))
print(np.mean(a, axis=0))
print(np.mean(a, axis=1))
'''
5.0
[4. 5. 6.]
[2. 5. 8.]
5.0
[4. 5. 6.]
[2. 5. 8.]
'''
#通过 np.average,可以指定平均数计算过程中的权重
a = np.array([1,2,3,4])
wts = np.array([1,2,3,4])
print(np.average(a))
print(np.average(a,weights=wts))
'''
2.5
3.0
'''
print(np.ptp(a))
print(np.ptp(a,0))
print(np.ptp(a,1))
'''
8
[6 6 6]
[2 2 2]
'''
print(np.percentile(a, 50))
print(np.percentile(a, 50, axis=0))
print(np.percentile(a, 50, axis=1))
'''
5.0
[4. 5. 6.]
[2. 5. 8.]
'''
3.3 数组的集合运算
unique(x)
intersect1d(x, y)
union1d(x, y)
in1d(x, y)
setdiff1d(x, y)
setxor1d(x, y)
3.4 线性代数计算 numpy.linalg
专门用于线性计算的库: numpy.linalg
numpy.linalg 汇总 有一组 标准的矩阵分解运算 以及 诸如求逆和行列式 之类的东西,它们跟 Matlab 和 R语言等 使用的是 相同行业标准级Fortran库
from numpy.linalg import inv, qr
x = randn(5, 5)
mat = x.T.dot(x) # x的转置 乘上 x x.dot: 点积
inv(mat) # 对矩阵 求逆
- 常用的 numpy.linalg 函数
函数 | 说明 |
---|---|
diag | 以一维数组的形式 返回方阵的对角线(或非对角线)元素;或将一维数组 转换为 方阵(非对角线元素为0) |
dot | 矩阵乘法 |
trace | 计算对角线元素的和 |
det | 计算矩阵行列式 |
eig | 计算方阵的 本征值 和 本证向量 |
inv | 计算方阵的逆 |
pinv | 计算矩阵的MOore-Penrose伪逆 |
qr | QR分解 |
svd | 奇异值分解 (SVD) |
solve | 解线性方程组 Ax = b,其中A为一个方阵 |
lstsq | 计算Ax = b的 最小二乘解 |
- 例子
from numpy.linalg import inv, qr
mat.dot(inv(mat)) #得到n阶斜对角单位矩阵
q, r = qr(mat) #将矩阵qr分解
三、Numpy查询
条件查询
# 列表生成式
[x if condition else y for x, y, condition in zip(xarr, yarr, cond)]
# np.where
result = np.where(cond, xarr, yarr)
(arr>0).sum() 等价于 np.where(arr>0, 1, 0).sum()
# np.where 还可以用于嵌套条件语句
# any() 和 all() 方法 ---> 返回的都是 True 和 False
arr.any()
arr.all()
Numpy随机数模块 numpy.random
numpy.random 模块对Python内置的random进行了补充,增加了一些用于高效生成【多种概率分布的样本值】的函数。
- 例如:产生大量(N个)标准正态分布的样本值
# Python内置的random
from random import normalvariate
samples = [normalvariate(0,1) for _ in xrange(N)] #Python内置的random模块一次只能生成一个样本值,需要利用循环多次调用;
# 调用numpy.random库
np.random.normal(size = N) #numpy的random模块可指定size参数,快了不只一个数量级
samples = np.random.normal(size = (4, 4)) #标准正态分布 的4x4样本数组
- 部分np.random函数
函数 | 说明 |
---|---|
seed(s) | 确定随机数生成器的种子 |
permutation | 返回一个序列的随机排列 或返回一个随机排列的范围 |
shuffle | 对一个序列就地随机排列 |
rand | 产生均匀分布 的样本值 |
randint | 从给定的上下限范围 内随机选取整数 |
randn | 产生正态分布(平均值为0, 标准差为1) 的样本值 |
binomial | 产生二项分布 的 样本值 |
normal | 产生正态(高斯)分布 的 样本值 |
beta | 产生Beta分布的样本值 |
chisquare | 产生卡方分布的样本值 |
gamma | 产生Gamma分布的样本值 |
uniform | 产生在 [0, 1) 中 均匀分布的 样本值 |
- 例子
np.random.seed(10)
np.random.randint(100, 200, (3, 4)) #生成随机数
np.random.seed(10) #再次调用 随机数种子
np.random.randint(100, 200, (3, 4)) # 生成的随机数组 与上一次是相同的
shuffle(a) # 根据数组a的第1轴 进行随机排列, 改变数据x
permutation(a) # 根据数组a的第1轴 产生一个新的乱序数组, 不改变数组x
choice(a[,size, replace, p]) # 从一维数组a中 以概率p 抽取元素, 形成size形状新数组, replace表示 是否可以重用元素, 默认为False