numpy概述
目录
ndarray
概念性
代码性
构造数组
调整数据类型
保留小数位数
数组形状
深浅拷贝
运算
聚合操作
读取数据
索引与切片
数字索引
布尔索引
三元运算符
裁剪操作
数组的拼接
数组的行列交换
常用统计函数
最大值与最小值
随机
nan
NumPy
NumPy是一个开源的Python科学计算基础库。
-
一个强大的N维数组对象 ndarray
-
广播功能函数
-
整合C/C++/Fortran代码的工具
-
线性代数、傅里叶变换、随机数生成等功能
NumPy是SciPy、Pandas等数据处理或科学计算库的基础。
ndarray
N维数组对象:ndarray
例:a = [2,5,9,6] , b = [8,9,5,4] , 计算a*2 + b**3
两个列表计算需要单个运算并循环
数组对象可以去掉元素运算间的循环,将一组数据看作单个数据单元来对待,在同一维度上直接计算,而且ndarray的底层语言是C,计算起来更快
概念性
-
ndarray是一个多维数组对象,由两部分构成 1)实际的数据 2)描述这些数据的元数据(数据维度、数据类型)等
-
ndarray数组一般要求所有元素类型相同(同质),数组下标从0开始。
-
ndarray在程序中的别名是array
-
np.array()输出成[]形式,元素间用空格分隔
-
ndarray的两个基本概念:
轴:保存数据的维度,数组的维度
一维数组:1个轴,axis=0,沿着这个轴就是从左到右。 二维数组:2个轴 axis=0:沿着行的方向(垂直,从上到下) axis=1:沿着列的方向(水平,从左到右) 三维数组:3个轴 axis=0:沿着块的方向 axis=1:沿着行的方向 axis=2:沿着列的方向秩:轴的数量
-
ndarray的基本属性
属性 说明 .ndim秩,即轴的数量或维度的数量 .shapendarray对象的尺度,对于矩阵,n行m列 .sizendarray对象元素的个数,相当于.shape中n*m的值 .dtypendarray对象的元素类型 .itemsizendarray对象中每个元素的大小,以字节为单位 -
ndarray中的元素类型
类型 类型代码 说明 int8、uint8 i1、u1 有符号和无符号的8位(1个字节)整型 int16、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值的布尔类型 U10、U80 字符串类型 最长十个字符、最长80个字符(自己定义)
代码性
构造数组
arange(start,stop,step,dtype=None),其中起始值和步长以及最后的指定类型可以省略
构造全 0 数组:np.zeros():a = np.zeros((3, 4)),括号内传入形状元组
构造全 1 数组:np.ones(),同上
构造任意常数数组:np.full():c = np.full((2, 3), 7),传入形状和数值
构造单位矩阵(对角线为 1):np.eye(),传入边长
np.eye(3, k=1) # 对角线往上偏移1行
生成“与已有数组形状相同”的 0、1 数组
| 函数 | 含义 |
|---|---|
np.zeros_like(a) | 生成与 a 形状、类型相同的全 0 数组 |
np.ones_like(a) | 同上,全 1 数组 |
np.full_like(a, 7) | 同上,全 7 数组 |
调整数据类型
格式:a2 = a1.astype("int8")
保留小数位数
通过np.round()
数组形状
查看数组形状:a.shape结果为(2,6)说明该数组为二元数组,有两行六列
改变数组形状:a.reshape((3,4))表示将该数组改为三行四列
自动转换成一维:a.reshape(-1) (自动识别元素个数并展平)
a.flatten()
手动转换成一维:a.reshape(12) (手动指定元素个数)(如果不知道元素个数可以采用行数乘以列数来计算,即a.shape[0] * a.shape[1])
调用rehsape方法并没有改变原来的a的值(除非赋值,如a = a.reshape()),但这里的没有改变指的是没有改变视图,即a看起来还是原来的行数和列数。但假如b = a.reshape(),此时改变b[0]的值,由于原视图和新视图共享一块内存空间,a[0]的值也会被改变。有关视图的操作都需要注意这点,比如切片。所以可以使用.copy()方法来避免数据修改混乱。
import numpy as np a = np.array([1, 2, 3]) b = a # 引用 c = a.view() # 浅拷贝(共享数据) d = a.copy() # 深拷贝(独立) b[0] = 99 print(a) # [99 2 3] print(c) # [99 2 3] print(d) # [1 2 3]
而b = a.flatten()的用法,创建了新的副本,独自占有一块内存空间,改变b的值并不影响a
深浅拷贝
插入一下Python 内存模型的关键概念
| 操作 | 复制层级 | 内部嵌套是否共享 | 修改是否互相影响 |
|---|---|---|---|
b = a | 不复制 | 全部共享 | 会互相影响 |
b = copy.copy(a) | 仅最外层 | 内部共享 | 改内层会影响 |
b = copy.deepcopy(a) | 所有层 | 不共享 | 完全独立 |
运算
数组和数字的运算:叫作广播,即数组中的每个元素都和该数字运算
除零运算:在numpy中,0/0结果为nan(not a number,不是数字),非零/0结果为inf(infinity,无穷,分为inf正无穷和-inf负无穷)
数组和数组的运算:
当两个数组形状一样时,对应位置进行计算
两个数组形状不一致时,同一维度进行运算
比如
a = array([0, 1, 2, 3, 4, 5, 6, 7]) #一维数组,形状为(8,) a2 = array([[0, 1, 2, 3, 4, 5, 6, 7]]) #这样就是二维数组了,形状为(1,8),不过这不影响广播 b = array([[ 0, 1, 2, 3, 4, 5, 6, 7], [ 8, 9, 10, 11, 12, 13, 14, 15], [16, 17, 18, 19, 20, 21, 22, 23]]) c = array([[0], [1], [2]]) a*b就让b的每一行都与a的对应位置相乘,结果为 array([[ 0, 1, 4, 9, 16, 25, 36, 49], [ 0, 9, 20, 33, 48, 65, 84, 105], [ 0, 17, 36, 57, 80, 105, 132, 161]]) b*c就让b的每一列都与c的对应位置相乘,结果为 array([[ 0, 0, 0, 0, 0, 0, 0, 0], [ 8, 9, 10, 11, 12, 13, 14, 15], [32, 34, 36, 38, 40, 42, 44, 46]])
如果行和列都不能对应,那就不能计算
广播三规则:
1)右边对齐维度
2)缺失左边补1
3)大小为1的维度扩展
聚合操作
axis= 表示沿着这个方向计算,计算后这个维度会消失。
a = np.array([[1, 2, 3],
[4, 5, 6]])
axis=0:沿着行的方向(垂直)计算,即对每一列进行计算(沿着行方向压缩)
a.sum(axis=0)) # [1+4, 2+5, 3+6] = [5 7 9]
axis=1:沿着列的方向(水平)计算,即对每一行进行计算(沿着列方向压缩)
a.sum(axis=1)) # [1+2+3, 4+5+6] = [6 15]
读取数据
np.loadtxt() - 读取简单的文本数据,适用于格式规整的文本数据
常用参数
# 读取CSV文件(逗号分隔)
data = np.loadtxt('data.csv', delimiter=',')
# 跳过第一行表头
data = np.loadtxt('data.txt', skiprows=1)
# 只读取前3列
data = np.loadtxt('data.txt', usecols=(0, 1, 2))
# 指定数据类型
data = np.loadtxt('data.txt', dtype=np.float32)
# 结合使用多个参数
data = np.loadtxt('data.csv', delimiter=',', skiprows=1, usecols=(0, 2))
#将读取的数据转置
unpack = True/Flase
np.genfromtxt(),支持缺失值处理、混合数据类型等复杂情况。
基本读取与np.loadtxt()类似
1.处理缺失值
# 自动将缺失值(空值)填充为nan
data = np.genfromtxt('data.csv', delimiter=',', filling_values=np.nan)
# 指定缺失值的标记
data = np.genfromtxt('data.csv', delimiter=',', missing_values='NULL', filling_values=0)
2.读取有列名的数据
# 读取列名
data = np.genfromtxt('data.csv', delimiter=',', names=True)
# 访问特定列(通过列名)
print(data['column1']) # 访问名为'column1'的列
3.指定数据类型
# 为不同列指定不同数据类型
data = np.genfromtxt('data.csv', delimiter=',',
dtype=[('name', 'U10'), ('age', 'i4'), ('score', 'f8')])
索引与切片
(除了xpath,目前接触到的索引都是从0开始)
数字索引
取第三行:a[2]
取连续的多行:a[2:]
取不连续的多行:a[[2,4,6]]
取列:a[:,0]表示所有行的第一列,逗号前为行,后为列
取连续的多列:a[:,2:]表示第二行之后的所有列
取不连续的多列:a[:,[0,2]]表示第一列和第三列
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 25 26 27 28 29] [30 31 32 33 34 35 36 37 38 39] [40 41 42 43 44 45 46 47 48 49] [50 51 52 53 54 55 56 57 58 59] [60 61 62 63 64 65 66 67 68 69] [70 71 72 73 74 75 76 77 78 79] [80 81 82 83 84 85 86 87 88 89] [90 91 92 93 94 95 96 97 98 99]]
取多行和多列:a[2:5,1:4],取了一块出来
取不相邻的多个点:a[[2,4,6],[2,4,6]]取的是第3行的第三个,第四行的第四个和第六行的第六个
取同一行的多个不相邻点:a[0,[2,4,6]]取的是第1行的第2,4,6个
取同一列的多个不相邻点:a[[2,4,6],3]取的是第2,4,6行的第三个
布尔索引
a<55的结果为 array([[ True, True, True, True, True, True, True, True, True, True], [ True, True, True, True, True, True, True, True, True, True], [ True, True, True, True, True, True, True, True, True, True], [ True, True, True, True, True, True, True, True, True, True], [ True, True, True, True, True, True, True, True, True, True], [ True, True, True, True, True, False, False, False, False, False], [False, False, False, False, False, False, False, False, False, False], [False, False, False, False, False, False, False, False, False, False], [False, False, False, False, False, False, False, False, False, False], [False, False, False, False, False, False, False, False, False, False]]) a[a<55]的结果为 array([ 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, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54]) a[a<55] = 3后a变成了 array([[ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3], [ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3], [ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3], [ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3], [ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3], [ 3, 3, 3, 3, 3, 55, 56, 57, 58, 59], [60, 61, 62, 63, 64, 65, 66, 67, 68, 69], [70, 71, 72, 73, 74, 75, 76, 77, 78, 79], [80, 81, 82, 83, 84, 85, 86, 87, 88, 89], [90, 91, 92, 93, 94, 95, 96, 97, 98, 99]])
三元运算符
np.where(a<70,0,10)意思是满足a<10的就赋值为0,其余就赋值为10
裁剪操作
a.clip(10,18)意为小于10的就替换为10,大于18的就替换为18
数组的拼接
np.vstack((t1,t2))为竖直拼接,传入的是一个元组
np.hstack((t1,t2))为水平拼接
数组的行列交换
交换第 0 行和第 2 行: a[[0, 2]] = a[[2, 0]] 交换第 0 列和第 2 列: a[:, [0, 2]] = a[:, [2, 0]] 行列顺序任意重排 假如a = np.array([ [1, 2, 3], [4, 5, 6], [7, 8, 9] ]) a = a[[2, 0, 1]] # 按新顺序排列行 a = a[:, [1, 2, 0]] # 按新顺序排列列 快速逆序 a = a[::-1] # 行逆序 a = a[:, ::-1] # 列逆序 转置 a.tranpose() a.T a.swapaxes(1,0) 交换零轴和一轴的位置
常用统计函数
| 函数 | 功能 | 示例 |
|---|---|---|
np.sum() | 求和 | np.sum(a) |
np.mean() | 平均值 | np.mean(a) |
np.median() | 中位数 | np.median(a) |
np.var() | 方差 | np.var(a) |
np.std() | 标准差(数据波动i情况) | np.std(a) |
np.min() / np.max() | 最小/最大值 | np.max(a, axis=0) |
np.ptp() | 极差(max-min) | np.ptp(a) |
np.percentile() | 百分位数 | np.percentile(a, 75) |
np.argmin() / np.argmax() | 最小/最大值的索引 | np.argmax(a) |
np.cumsum() | 累加和 | np.cumsum(a) |
np.cumprod() | 累乘积 | np.cumprod(a) |
np.dot() | 点积(两个向量对应元素相乘后求和) | np.dot(a, b) |
最大值与最小值
| 目标 | 函数 |
|---|---|
| 整体最大值 | np.max(a) |
| 整体最小值 | np.min(a) |
| 每行最大 | np.max(a, axis=1) |
| 每列最小 | np.min(a, axis=0) |
| 最大值索引(扁平) | np.argmax(a) |
| 最小值索引(扁平) | np.argmin(a) |
| 最大值位置(行,列) | np.unravel_index(np.argmax(a), a.shape) |
| 极差 | np.ptp(a) |
随机
| 功能 | 旧接口 | 新接口(推荐) | 参数含义 |
|---|---|---|---|
| [0,1) 随机浮点 | np.random.rand(2,3) | rng.random((2,3)) | rand(行数, 列数, ...)和random(形状元组) |
| 随机整数 | np.random.randint(1,10,(2,3)) | rng.integers(1,10,(2,3)) | (起始, 结束, 形状) |
| 正态分布 | np.random.normal(50,20,5) | rng.normal(50,20,5) | (均值,标准差,个数) |
| 均匀分布 | np.random.uniform(0,5,(2,3)) | rng.uniform(0,5,(2,3)) | (最小值, 最大值, 形状) |
| 抽样 | np.random.choice(a,3) | rng.choice(a,3) | (数组, 抽样数量, 是否放回, 概率)默认不放回抽样 |
| 固定种子 | np.random.seed(0) | rng = np.random.default_rng(0) | (种子值) |
| 指数分布 | np.random.exponential(30, 1000) | rng.exponential(30, 1000) | (均值,个数) |
| 泊松分布 | np.random.poisson(3, 1000) | rng.poisson(3, 1000) | (均值,个数) |
| 二项分布 | np.random.binomial(n, p) | (n次试验,每次概率p) |
nan
注:如果a里面都是整型,a[2,2] = np.nan会报错,因为nan是浮点型,要赋值nan需要先转成浮点型
np.count_nonzero(a!=a)可以统计出a数组中值为nan的个数
np.isnana(a)可以判断a数组每个值是否为nan
任何值与nan进行任何运算,结果都是nan
NaN(Not a Number)常用于表示缺失值, 我们通常希望 把每列的 NaN 替换为该列的平均值。
法一
# 1. 计算每列均值(忽略 NaN) col_means = np.nanmean(a, axis=0) # 2. 找到 NaN 的位置 inds = np.where(np.isnan(a)) # 3. 替换对应位置 a[inds] = np.take(col_means, inds[1])
法二:一行简洁写法
np.where(np.isnan(a), np.nanmean(a, axis=0), a) #np.where(条件, 条件为True时取x, 条件为False时取y) 结果大概是这样的形式 np.where( [[False, False, True], [False, True, False], [False, False, False]], [[4. , 5. , 7.5], [4. , 5. , 7.5], [4. , 5. , 7.5]], [[1., 2., nan], [4., nan, 6.], [7., 8., 9.]] )








