数据处理与统计分析之NumPy详解
1 简介
1.1 概述
NumPy(Numerical Python)是Python数据分析必不可少的第三方库
NumPy的出现一定程度上解决了Python运算性能不佳的问题,同时提供了更加精确的数据类型,使其具备了构造复杂数据类型的能力。
本身是由C语言开发,是个很基础的扩展,NumPy被Python其它科学计算包作为基础包,因此理解np的数据类型对python数据分析十分重要。
NumPy重在数值计算,主要用于多维数组(矩阵)处理的库。用来存储和处理大型矩阵,比Python自身的嵌套列表结构要高效的多
1.2 NumPy 与Python 原生列表的核心差异
| 特性 | Python 列表 | NumPy ndarray |
|---|---|---|
| 元素类型 | 可混合类型(如[1, "a"]) | 强制统一类型 |
| 内存布局 | 分散存储,内存开销大 | 连续存储,内存利用率高 |
| 运算效率 | 需循环,速度慢(Python 解释器) | 向量化运算,C 底层,速度快 |
| 维度支持 | 嵌套列表模拟多维,操作繁琐 | 原生支持多维,内置多维操作 |
| 数学函数 | 需手动实现 / 调用 math 模块 | 内置丰富的向量化数学函数 |
| 切片 | 会创建一个新的列表,可以理解成副本 | 切片是视图,不是副本! |
| 大小修改 | 动态增删 | 固定大小,修改创建新数组 |
2 主要功能
NumPy重要功能如下:
高性能科学计算和数据分析的基础包
ndarray,多维数组,具有矢量运算能力,快速、节省空间
矩阵运算,无需循环,可完成类似Matlab中的矢量运算
用于读写磁盘数据的工具以及用于操作内存映射文件的工具
3 属性
3.1 概述
- ndarray.ndim
定义:数组的维度(秩),返回整数
通俗理解:数组有几个维度 → 一维是线、二维是面、三维是体
示例:一维数组ndim=1,二维矩阵ndim=2,三维数组ndim=3 - ndarray.shape
定义:数组每个维度的大小,返回整数元组
通俗理解:描述数组的「形状」,直观表示几行几列 / 几层几行几列
一维数组:(元素个数,)
二维数组:(行数, 列数)
三维数组:(层数, 行数, 列数) - ndarray.size
定义:数组中总元素的个数,返回整数
通俗理解:数组里一共有多少个数据
关键关联:size = shape 中所有数字的乘积 - ndarray.dtype
定义:数组中元素的数据类型,返回 dtype 对象
通俗理解:数组所有元素的统一类型(ndarray 强制要求所有元素类型一致)
常见类型:int32/int64(整数)、float32/float64(浮点数)、bool(布尔值) - ndarray.itemsize
定义:数组单个元素占用的字节数,返回整数(单位:字节)
通俗理解:每个数据占用的内存空间大小
关键关联:itemsize 由 dtype 决定
int32/float32 → 4 字节
int64/float64 → 8 字节
bool → 1 字节
3.2 代码演示
importnumpyasnp# 创建 2行3列 的二维数组(指定数据类型为32位整数)arr=np.array([[1,2,3],[4,5,6]],dtype=np.int32)# 打印所有核心属性print("数组维度(ndim):",arr.ndim)# 2print("数组形状(shape):",arr.shape)# (2, 3)print(len(arr.shape))print("总元素数(size):",arr.size)# 6print("元素类型(dtype):",arr.dtype)# int32print("单元素字节(itemsize):",arr.itemsize)# 43.3 属性核心关联
维度关系:len(arr.shape) = arr.ndim
arr.shape 是一个元组,元组里有几个数字,就代表数组有几个维度;而 arr.ndim 就是数组的维度数量。
所以:元组的长度 = 维度数 → len(arr.shape) = arr.ndim
总数关系:arr.size = arr.shape[0] × arr.shape[1] × ...
内存关系:数组总字节数 = arr.size × arr.itemsize
(总字节数可直接用拓展属性arr.nbytes获取)
ndarray.nbytes:数组所有元素占用的总字节数(= size × itemsize)
3.4 axis 参数的可视化解释
| axis 值 | 对应 shape 位置 | 官方叫法 | 通俗理解 | 操作效果 |
|---|---|---|---|---|
| axis=0 | shape [0](行数) | 行维度 | 纵向 / 上下 | 压缩行,保留列 |
| axis=1 | shape [1](列数) | 列维度 | 横向 / 左右 | 压缩列,保留行 |
如果实在迷糊 就记忆 axis=N 就是沿着第 N 个维度压扁 / 聚合 / 切割,这个维度会消失!
importnumpyasnp arr=np.array([[1,2,3],# 第0行[4,5,6]# 第1行])# shape = (2行, 3列) → (axis=0, axis=1)axis=0纵向(行方向) 列0列1列2↓ ↓ ↓[1,2,3]→ 行0[4,5,6]→ 行1↑ ↑ ↑ axis=0是**上下垂直**方向,把行压掉,算每列的结果 axis=1横向(列方向) 行0→[1→2→3]行1→[4→5→6]←→ axis=1是**左右水平**方向,把列压掉,算每行的结果arr=np.array([[1,2,3],[4,5,6]])# axis=0:按列求和(纵向加,压掉行)print(arr.sum(axis=0))# [1+4, 2+5, 3+6] → [5,7,9]# axis=1:按行求和(横向加,压掉列)print(arr.sum(axis=1))# [1+2+3, 4+5+6] → [6,15]4 创建ndarray
4.1 概述
NumPy数组是一个多维的数组对象(矩阵),称为ndarray,具有矢量算术运算能力和复杂的广播能力,并具有执行速度快和节省空间的特点。注意:ndarray的下标从0开始,且数组里的所有元素必须是相同类型。
4.2 代码实现
4.2.1 写法1: array()函数
可以把Python列表转成ndarray对象.
importnumpyasnp# 1. 创建Python的列表.my_list=[1,2,3,4,5]# 2. 把上述的列表转成ndarray对象.arr1=np.array(my_list)# 等价于: arr1 = np.array([1, 2, 3, 4, 5])# 3. 打印arr1的类型, 和其元素类型.print(f'arr1的数据类型是:{type(arr1)}')print(f'arr1中元素的类型是:{arr1.dtype}')4.2.2 写法2: arange(起始值,结束值,步长)函数
类似于Python的range()函数
importnumpyasnp# 1. 创建1个ndarray数组, 存放1到10的数字.arr2=np.arange(1,10,2,dtype=np.float64)# 左闭右开# 2. 打印arr2的类型, 和其元素类型.print(f'arr2的数据类型是:{type(arr2)}')print(f'arr2中元素的类型是:{arr2.dtype}')print(f'arr2的元素是:{arr2}')4.2.3 写法3: 获取随机的数组
即: rand(), randint(), uniform()
importnumpyasnp# 演示rand()函数# 1. 创建1个3行4列, 范围是0.0 ~ 1.0之间的随机数组.arr3=np.random.rand(3,4)print(f'arr3的元素是:{arr3}')print(f'arr3的数据类型是:{type(arr3)}')print(f'arr3中元素的类型是:{arr3.dtype}')# float64# 演示randint()函数, 获取一个指定范围内的随机整数.# 1. 创建1个3行4列, 范围是-3 ~ 10之间的随机数组.arr4=np.random.randint(-3,10,size=(3,4))# 包左不包右print(f'arr4的元素是:{arr4}')print(f'arr4的数据类型是:{type(arr4)}')print(f'arr4中元素的类型是:{arr4.dtype}')# int32# 演示uniform()函数, 获取一个指定范围内的随机小数.# 1. 创建1个3行4列, 范围是-2.0 ~ 5.0之间的随机数组.arr5=np.random.uniform(-2.0,5.0,(3,4))print(f'arr5的元素是:{arr5}')print(f'arr5的数据类型是:{type(arr5)}')print(f'arr5中元素的类型是:{arr5.dtype}')# float644.2.4 写法4: zeros(), ones(), empty()
importnumpyasnp#演示zeros()函数, 创建一个全为0的数组.# 1. 创建1个3行4列, 全为0的数组.arr6=np.zeros(shape=(3,4),dtype=np.int16)print(f'arr6的元素是:{arr6}')print(f'arr6的数据类型是:{type(arr6)}')print(f'arr6中元素的类型是:{arr6.dtype}')# 演示ones()函数, 创建一个全为1的数组.# 1. 创建1个3行4列, 全为1的数组.arr7=np.ones(shape=(3,4),dtype=np.int32)print(f'arr7的元素是:{arr7}')print(f'arr7的数据类型是:{type(arr7)}')print(f'arr7中元素的类型是:{arr7.dtype}')# 演示empty()函数, 创建指定形状的数组,仅分配内存空间但不初始化元素值,元素为内存中残留的垃圾值(非主动 “随机分配”,是内存原有残留值)# 1. 创建1个3行4列, 随机分配的数组.arr8=np.empty(shape=(3,4),dtype=np.int32)print(f'arr8的元素是:{arr8}')print(f'arr8的数据类型是:{type(arr8)}')print(f'arr8中元素的类型是:{arr8.dtype}')4.2.5 写法5: 等比和等差数列
#演示logspace(), 创建一个等比数列.importnumpyasnp# 1. 创建1个1 ~ 1000之间的等比数列, 元素长度为: 5arr1=np.logspace(0,3,5)# 参1: 起始值,10的0次幂, 参2:结束值,10的3次幂, 参3:元素个数#注意:包左包右 np.logspace(0, 3, 5) 等价于 10^0, 10^0.75, 10^1.5, 10^2.25, 10^3# 2. 打印上述数组的信息.print(f'arr1的元素是:{arr1}')print