NumPy Ndarray 对象

在 NumPy 中,`ndarray`(N-dimensional array,N 维数组)是核心数据结构,用于存储和操作多维、同类型的数据。它是 NumPy 高性能科学计算的基础,广泛应用于数据分析、机器学习和科学计算。以下是对 NumPy `ndarray` 对象的详细中文讲解,涵盖定义、创建、属性、操作、常见用法、注意事项及最佳实践,帮助你全面掌握 `ndarray` 的使用。



## 一、NumPy `ndarray` 概述

### 1. 什么是 `ndarray`?
– **定义**:`ndarray` 是 NumPy 的多维数组对象,用于存储固定类型的元素,支持高效的数学运算和数组操作。
– **特点**:
– **多维性**:支持任意维度的数组(1D、2D、3D 等)。
– **同类型**:所有元素必须是同一数据类型(如 `int32`、`float64`)。
– **连续内存**:数据存储在连续内存块中,访问效率高。
– **向量化操作**:支持元素级运算和广播机制,避免显式循环。
– **优势**:
– 比 Python 列表更快(C 实现,内存高效)。
– 提供丰富的数学函数和操作(如矩阵运算、统计分析)。
– 与 Pandas、SciPy 等库无缝集成。

### 2. 与 Python 列表的区别
| 特性 | `ndarray` | Python 列表 |
|——|———–|————-|
| **数据类型** | 固定类型(如 `float64`) | 混合类型 |
| **内存** | 连续存储,高效 | 非连续,指针存储 |
| **性能** | 向量化运算,速度快 | 循环操作,较慢 |
| **功能** | 数学运算、广播 | 基础操作,功能有限 |



## 二、创建 `ndarray`

NumPy 提供了多种方式创建 `ndarray` 对象。

### 1. 从 Python 列表或元组创建
“`python
import numpy as np

# 一维数组
arr1 = np.array([1, 2, 3])
print(arr1) # 输出:[1 2 3]

# 二维数组
arr2 = np.array([[1, 2], [3, 4]])
print(arr2) # 输出:
# [[1 2]
# [3 4]]

# 指定数据类型
arr3 = np.array([1, 2, 3], dtype=np.float64)
print(arr3) # 输出:[1. 2. 3.]
“`

### 2. 使用 NumPy 内置函数
– **全零数组**:
“`python
zeros = np.zeros((2, 3)) # 2×3 零矩阵
print(zeros) # 输出:
# [[0. 0. 0.]
# [0. 0. 0.]]
“`

– **全一数组**:
“`python
ones = np.ones((2, 3)) # 2×3 单位矩阵
print(ones) # 输出:
# [[1. 1. 1.]
# [1. 1. 1.]]
“`

– **指定值填充**:
“`python
full = np.full((2, 2), 5) # 2×2 填充 5
print(full) # 输出:
# [[5 5]
# [5 5]]
“`

– **单位矩阵**:
“`python
eye = np.eye(3) # 3×3 单位矩阵
print(eye) # 输出:
# [[1. 0. 0.]
# [0. 1. 0.]
# [0. 0. 1.]]
“`

– **等差序列**:
“`python
arange = np.arange(0, 10, 2) # 从 0 到 10,步长 2
print(arange) # 输出:[0 2 4 6 8]
“`

– **均匀分布**:
“`python
linspace = np.linspace(0, 1, 5) # 从 0 到 1,生成 5 个点
print(linspace) # 输出:[0. 0.25 0.5 0.75 1. ]
“`

– **随机数数组**:
“`python
random = np.random.rand(2, 3) # 2×3 随机数(0-1)
print(random) # 输出:随机值
“`

### 3. 从文件加载
“`python
# 保存数组
arr = np.array([1, 2, 3])
np.save(“array.npy”, arr)

# 加载数组
loaded = np.load(“array.npy”)
print(loaded) # 输出:[1 2 3]
“`



## 三、`ndarray` 的核心属性

`ndarray` 提供了多个属性,用于描述数组结构和数据。

| 属性 | 描述 | 示例(`arr = np.array([[1, 2], [3, 4]])`) |
|——|——|——————————————|
| `shape` | 数组形状(元组) | `arr.shape` → `(2, 2)` |
| `ndim` | 数组维数 | `arr.ndim` → `2` |
| `size` | 元素总数 | `arr.size` → `4` |
| `dtype` | 元素数据类型 | `arr.dtype` → `int64` |
| `itemsize` | 每个元素字节大小 | `arr.itemsize` → `8`(int64) |
| `nbytes` | 总字节大小 | `arr.nbytes` → `32`(4×8) |

– **示例**:
“`python
arr = np.array([[1, 2], [3, 4]])
print(arr.shape) # 输出:(2, 2)
print(arr.ndim) # 输出:2
print(arr.size) # 输出:4
print(arr.dtype) # 输出:int64
“`



## 四、数组操作

### 1. 索引与切片
– **一维数组**:
“`python
arr = np.array([1, 2, 3, 4])
print(arr[0]) # 输出:1
print(arr[1:3]) # 输出:[2 3]
“`

– **二维数组**:
“`python
arr2d = np.array([[1, 2], [3, 4], [5, 6]])
print(arr2d[0, 1]) # 输出:2
print(arr2d[:, 0]) # 输出:[1 3 5](第一列)
“`

– **布尔索引**:
“`python
arr = np.array([1, 2, 3, 4])
print(arr[arr > 2]) # 输出:[3 4]
“`

### 2. 形状操作
– **改变形状**:
“`python
arr = np.array([1, 2, 3, 4])
reshaped = arr.reshape(2, 2)
print(reshaped) # 输出:
# [[1 2]
# [3 4]]
“`

– **展平数组**:
“`python
flattened = arr2d.flatten()
print(flattened) # 输出:[1 2 3 4 5 6]
“`

– **转置**:
“`python
arr2d = np.array([[1, 2], [3, 4]])
print(arr2d.T) # 输出:
# [[1 3]
# [2 4]]
“`

### 3. 数学运算
– **元素级运算**:
“`python
arr = np.array([1, 2, 3])
print(arr + 2) # 输出:[3 4 5]
print(arr * 2) # 输出:[2 4 6]
“`

– **数组间运算**:
“`python
arr1 = np.array([1, 2])
arr2 = np.array([3, 4])
print(arr1 + arr2) # 输出:[4 6]
“`

– **矩阵运算**:
“`python
arr = np.array([[1, 2], [3, 4]])
print(np.dot(arr, arr)) # 输出:
# [[ 7 10]
# [15 22]]
“`

### 4. 统计函数
– **均值、标准差**:
“`python
arr = np.array([1, 2, 3, 4])
print(np.mean(arr)) # 输出:2.5
print(np.std(arr)) # 输出:1.118…
“`

– **最大/最小值**:
“`python
print(np.max(arr)) # 输出:4
print(np.min(arr)) # 输出:1
“`

– **求和**:
“`python
print(np.sum(arr)) # 输出:10
“`

### 5. 广播机制
广播允许不同形状的数组运算:
“`python
arr = np.array([[1, 2], [3, 4]])
scalar = 2
print(arr + scalar) # 输出:
# [[3 4]
# [5 6]]
“`



## 五、常见用法示例

### 1. 数据标准化
“`python
data = np.array([1, 2, 3, 4, 5])
standardized = (data – np.mean(data)) / np.std(data)
print(standardized) # 输出:[-1.414… -0.707… 0. 0.707… 1.414…]
“`

### 2. 矩阵运算
“`python
matrix = np.array([[1, 2], [3, 4]])
inverse = np.linalg.inv(matrix)
print(inverse) # 输出:
# [[-2. 1. ]
# [ 1.5 -0.5]]
“`

### 3. 随机数生成
“`python
random_ints = np.random.randint(0, 10, size=(2, 3))
print(random_ints) # 输出:2×3 随机整数矩阵
“`

### 4. 数据筛选
“`python
arr = np.array([1, 2, 3, 4, 5])
print(arr[arr % 2 == 0]) # 输出:[2 4]
“`



## 六、注意事项

1. **数据类型(dtype)**:
– `ndarray` 元素类型固定,创建时可指定(如 `dtype=np.float32`)。
– 错误类型可能导致精度丢失:
“`python
arr = np.array([1.5, 2.7], dtype=np.int32) # 输出:[1 2]
“`

2. **内存效率**:
– `ndarray` 比 Python 列表内存占用少,但大数组需注意内存管理。

3. **广播限制**:
– 形状不兼容会抛出 `ValueError`:
“`python
arr1 = np.array([1, 2])
arr2 = np.array([1, 2, 3])
# arr1 + arr2 # 报错:形状不匹配
“`

4. **视图 vs 副本**:
– 切片操作返回视图(修改会影响原数组):
“`python
arr = np.array([1, 2, 3])
view = arr[1:3]
view[0] = 10
print(arr) # 输出:[ 1 10 3]
“`
– 使用 `copy()` 创建副本:
“`python
copy = arr[1:3].copy()
“`

5. **性能优化**:
– 优先使用向量化操作,避免 Python 循环:
“`python
# 慢:循环
for i in range(len(arr)):
arr[i] += 1
# 快:向量化
arr += 1
“`



## 七、最佳实践

1. **指定数据类型**:
– 根据需求选择类型(如 `int16`、`float32`)节省内存:
“`python
arr = np.array([1, 2, 3], dtype=np.int16)
“`

2. **使用向量化操作**:
– 避免循环,利用 NumPy 内置函数:
“`python
arr = np.array([1, 2, 3])
arr = np.sin(arr) # 高效
“`

3. **检查数组形状**:
– 操作前确认 `shape` 和 `ndim`:
“`python
print(arr.shape, arr.ndim)
“`

4. **管理大数组**:
– 保存/加载大数组以减少内存占用:
“`python
np.save(“large_array.npy”, arr)
“`

5. **结合其他库**:
– 与 Pandas、Matplotlib 集成:
“`python
import pandas as pd
df = pd.DataFrame(np.array([[1, 2], [3, 4]]))
“`

6. **调试技巧**:
– 使用 `np.set_printoptions` 控制输出:
“`python
np.set_printoptions(precision=2) # 保留 2 位小数
“`



## 八、总结

NumPy 的 `ndarray` 是高效的多维数组对象,支持快速的数学运算、索引、切片和广播机制。掌握其创建方法(列表、内置函数)、属性(`shape`、`dtype`)、操作(索引、运算、统计)及常见用法,能显著提升数据处理效率。遵循最佳实践(如向量化、指定类型),并注意视图与副本、广播限制等细节,可确保高效开发。

如果你需要更复杂的 `ndarray` 示例(如高级矩阵运算、性能优化)或特定场景的代码,请告诉我!

类似文章

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注