Python数据分析学习(一):Numpy
是 Python 科学计算的基础包。它提供了一个强大的多维数组对象(ndarray),以及各种派生对象(如掩码数组、矩阵)和一系列用于快速操作数组的函数,涵盖了数学、逻辑、形状操作、排序、选择、I/O、离散傅里叶变换、线性代数、统计、随机模拟等方方面面。NumPy 的核心是 ndarray对象,它是一个由同质数据元素组成的 n 维数组。为了提高性能,许多操作都是在经过高度优化的编译代码(C/C++
NumPy 快速入门教程
什么是 NumPy?
NumPy 是 Python 科学计算的基础包。它提供了一个强大的多维数组对象(ndarray),以及各种派生对象(如掩码数组、矩阵)和一系列用于快速操作数组的函数,涵盖了数学、逻辑、形状操作、排序、选择、I/O、离散傅里叶变换、线性代数、统计、随机模拟等方方面面。
NumPy 的核心是 ndarray 对象,它是一个由同质数据元素组成的 n 维数组。为了提高性能,许多操作都是在经过高度优化的编译代码(C/C++)中执行的。
NumPy 数组与 Python 列表(List)的重要区别
| 特性 | NumPy 数组 (ndarray) |
Python 列表 (list) |
|---|---|---|
| 大小 | 创建时固定,改变大小会创建新数组并删除原数组 | 可以动态增长 |
| 数据类型 | 所有元素类型必须相同(同质) | 可以包含不同类型元素 |
| 运算效率 | 高度优化的预编译代码,执行速度快 | Python 循环,速度慢 |
| 语法简洁性 | 向量化操作,代码简洁 | 通常需要显式循环 |
越来越多的科学/数学 Python 包都基于 NumPy 数组构建,因此掌握 NumPy 是高效使用这些工具的前提。
数组大小与速度:为什么科学计算离不开 NumPy?
考虑一个简单的任务:将两个一维序列的对应元素相乘。
如果数据存储在 Python 列表 a 和 b 中,通常我们会这样写:
c = []
for i in range(len(a)):
c.append(a[i] * b[i])
当数据量达到数百万时,Python 循环的低效就会成为瓶颈。同样的计算在 C 语言中可以这样写:
for (i = 0; i < rows; i++) {
c[i] = a[i] * b[i];
}
C 代码速度快,但编写繁琐。对于二维数组,C 代码会变成双重循环,复杂度进一步增加。
NumPy 给出了两全其美的解决方案:通过向量化操作,我们可以用一行简洁的 Python 代码实现 C 语言级别的速度:
c = a * b
这行代码背后,NumPy 在预编译的 C 代码中执行了逐元素乘法,既保持了 Python 的简洁,又获得了接近 C 的性能。
这个例子展示了 NumPy 的两个核心特性:向量化(Vectorization)和广播(Broadcasting)。
为什么 NumPy 这么快?
向量化(Vectorization)
向量化指的是代码中没有显式的循环、索引等操作,所有的循环都在后台由优化的 C 代码完成。其优点包括:
- 代码更简洁、更易读
- 更少出错(行数越少,bug 越少)
- 更贴近数学表达
- 更符合 Pythonic 风格
广播(Broadcasting)
广播是 NumPy 在执行操作时,自动扩展较小数组以匹配较大数组形状的机制。它不仅适用于算术运算,还适用于逻辑、位运算、函数调用等所有操作。
例如,标量 3 可以和一个数组相加,NumPy 会自动将 3 广播到数组的每个元素:
a = np.array([1, 2, 3])
print(a + 3) # 输出 [4 5 6]
广播也适用于不同形状的数组,只要它们在某些维度上兼容。
谁在使用 NumPy?
NumPy 的 ndarray 已经成为 Python 中多维数据交换的事实标准。它支持面向对象(通过 ndarray 的方法)和函数式(通过 NumPy 顶层函数)两种编程风格,灵活强大。
NumPy 基础知识
ndarray 的核心属性
ndarray.ndim:数组轴(维度)的数量。ndarray.shape:数组的维度,是一个表示每个轴大小的元组。例如,一个 n 行 m 列的矩阵,shape为(n, m)。ndarray.size:数组中元素的总个数,等于shape中各元素的乘积。ndarray.dtype:描述数组元素类型的对象。可以是 Python 内置类型,也可以是 NumPy 提供的类型,如numpy.int32、numpy.float64等。ndarray.itemsize:数组中每个元素的字节大小。例如,float64的itemsize为 8。ndarray.data:包含数组实际元素的缓冲区。通常我们通过索引访问元素,很少直接使用这个属性。
示例
import numpy as np
# 创建一个 0~14 的数组,并重塑为 3 行 5 列
a = np.arange(15).reshape(3, 5)
print(a)
# [[ 0 1 2 3 4]
# [ 5 6 7 8 9]
# [10 11 12 13 14]]
print(a.shape) # (3, 5)
print(a.ndim) # 2
print(a.dtype.name) # 'int64' (可能因平台而异)
print(a.itemsize) # 8
print(a.size) # 15
print(type(a)) # <class 'numpy.ndarray'>
# 一维数组
b = np.array([6, 7, 8])
print(b) # [6 7 8]
数组创建
1. 从 Python 序列转换(np.array)
a = np.array([2, 3, 4]) # 从列表创建,dtype 自动推断为 int64
b = np.array([1.2, 3.5, 5.1]) # 自动推断为 float64
c = np.array([(1.5, 2, 3), (4, 5, 6)]) # 二维数组
d = np.array([[1, 2], [3, 4]], dtype=complex) # 指定数据类型
常见错误:np.array(1,2,3,4) 是错误的,应该传入一个列表:np.array([1,2,3,4])。
2. 使用占位符创建
当数组大小已知但元素未知时,可以用以下函数创建初始占位符数组:
np.zeros(shape):全 0 数组(默认float64)np.ones(shape):全 1 数组np.empty(shape):内容随机的数组(取决于内存状态)
np.zeros((3, 4)) # 3行4列的全0数组
np.ones((2, 3, 4), dtype=np.int16) # 2x3x4 的三维数组,int16 类型
np.empty((2, 3)) # 未初始化的 2x3 数组
3. 创建数值序列
np.arange(start, stop, step):类似于 Python 的range,但返回数组。当使用浮点数步长时,推荐用linspace。np.linspace(start, stop, num):在指定区间内生成固定数量的点。
np.arange(10, 30, 5) # array([10, 15, 20, 25])
np.arange(0, 2, 0.3) # 浮点数步长可能产生不可预测的个数
np.linspace(0, 2, 9) # 在0到2之间生成9个数
打印数组
NumPy 打印数组时,会按照以下规则布局:
- 最后一个轴从左到右打印
- 倒数第二个轴从上到下打印
- 其余轴从上到下打印,每个切片之间用空行隔开
# 一维数组
a = np.arange(6)
print(a) # [0 1 2 3 4 5]
# 二维数组
b = np.arange(12).reshape(4, 3)
print(b)
# [[ 0 1 2]
# [ 3 4 5]
# [ 6 7 8]
# [ 9 10 11]]
# 三维数组
c = np.arange(24).reshape(2, 3, 4)
print(c)
# [[[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]
#
# [[12 13 14 15]
# [16 17 18 19]
# [20 21 22 23]]]
当数组太大时,NumPy 会自动省略中间部分:
print(np.arange(10000)) # 显示 [ 0 1 2 ... 9997 9998 9999]
若要强制打印整个数组,可以设置打印选项:
import sys
np.set_printoptions(threshold=sys.maxsize)
基本运算
逐元素运算
算术运算符(+、-、*、/、** 等)默认对数组执行逐元素操作。
a = np.array([20, 30, 40, 50])
b = np.arange(4) # array([0, 1, 2, 3])
c = a - b # array([20, 29, 38, 47])
print(b ** 2) # array([0, 1, 4, 9])
print(10 * np.sin(a)) # 逐元素应用正弦函数
print(a < 35) # array([ True, True, False, False])
矩阵乘法
乘法运算符 * 是逐元素乘法,矩阵乘法使用 @ 运算符或 dot() 方法。
A = np.array([[1, 1], [0, 1]])
B = np.array([[2, 0], [3, 4]])
print(A * B) # 逐元素乘法:[[2, 0], [0, 4]]
print(A @ B) # 矩阵乘法:[[5, 4], [3, 4]]
print(A.dot(B)) # 同上
原地操作
运算符 +=、*= 等会直接修改原数组,不会创建新数组。
rg = np.random.default_rng(1)
a = np.ones((2, 3), dtype=int)
b = rg.random((2, 3))
a *= 3 # a 的每个元素乘以 3
b += a # 将 a 加到 b 上(需要类型兼容)
注意:类型向下转换是不允许的。例如,a += b(a 是 int,b 是 float)会报错。
类型提升
对不同类型的数组进行操作时,结果类型会自动提升到更通用的类型。
a = np.ones(3, dtype=np.int32)
b = np.linspace(0, np.pi, 3) # float64
c = a + b
print(c.dtype) # float64
d = np.exp(c * 1j)
print(d.dtype) # complex128
一元操作
许多一元操作(如求和、最小值、最大值)是 ndarray 的方法。
a = rg.random((2, 3))
print(a.sum()) # 所有元素之和
print(a.min()) # 最小值
print(a.max()) # 最大值
通过 axis 参数可以沿指定轴操作:
axis=0:沿纵向(跨行),结果中列数不变,行数变为 1(或消失)axis=1:沿横向(跨列),结果中行数不变,列数变为 1(或消失)
b = np.arange(12).reshape(3, 4)
print(b.sum(axis=0)) # 每列之和:[12 15 18 21]
print(b.min(axis=1)) # 每行最小值:[0 4 8]
print(b.cumsum(axis=1)) # 每行的累加和
通用函数(ufunc)
NumPy 提供了许多数学函数,如 sin、cos、exp、sqrt 等,它们被称为“通用函数”(ufunc),对数组进行逐元素运算。
B = np.arange(3)
np.exp(B) # e^0, e^1, e^2
np.sqrt(B) # 开方
C = np.array([2., -1., 4.])
np.add(B, C) # 相当于 B + C
常用 ufunc 可分为以下几类:
- 数学处理:
floor,ceil,round,clip,conj - 统计分析:
sum,mean,median,std,var,average - 排序搜索:
sort,argsort,argmax,argmin,where,nonzero - 线性代数:
dot,vdot,trace,transpose,outer,cross - 逻辑判定:
all,any
索引、切片和迭代
一维数组
与 Python 列表类似,支持索引、切片和迭代。
a = np.arange(10) ** 3
print(a[2]) # 8
print(a[2:5]) # [8, 27, 64]
a[:6:2] = 1000 # 从开头到第6个元素,每隔2个元素赋值为1000
print(a[::-1]) # 反转数组
多维数组
每个轴用一个索引,索引之间用逗号分隔。
def f(x, y):
return 10 * x + y
b = np.fromfunction(f, (5, 4), dtype=int)
print(b[2, 3]) # 第3行第4列
print(b[0:5, 1]) # 所有行的第2列
print(b[1:3, :]) # 第2到3行的所有列
省略号(...) 表示多个完整的切片:
x[1, 2, ...]等价于x[1, 2, :, :, :]x[..., 3]等价于x[:, :, :, :, 3]
迭代
多维数组默认按第一个轴(行)迭代:
for row in b:
print(row) # 逐行打印
使用 flat 属性可以获取一个遍历所有元素的迭代器:
for element in b.flat:
print(element) # 遍历每个元素
形状操纵
改变数组形状
ravel():将数组展平为一维(返回视图,除非必要)。reshape():改变形状,返回新数组(不修改原数组)。resize():就地修改形状。T:转置。
a = np.floor(10 * rg.random((3, 4)))
a.ravel() # 展平
a.reshape(6, 2) # 重塑为 6x2
a.T # 转置
a.resize((2, 6)) # 就地改变形状
使用 -1 自动推断维度:
a.reshape(3, -1) # 自动计算列数
堆叠数组
vstack():垂直堆叠(沿行)hstack():水平堆叠(沿列)column_stack():将一维数组作为列堆叠row_stack():等价于vstack
a = np.floor(10 * rg.random((2, 2)))
b = np.floor(10 * rg.random((2, 2)))
np.vstack((a, b))
np.hstack((a, b))
# column_stack 示例
from numpy import newaxis
a = np.array([4., 2.])
b = np.array([3., 8.])
np.column_stack((a, b)) # 返回 2x2 数组
a[:, newaxis] # 将一维数组转换为列向量
np.r_ 和 np.c_ 提供了更灵活的堆叠方式:
np.r_[1:4, 0, 4] # array([1, 2, 3, 0, 4])
拆分数组
hsplit():水平拆分vsplit():垂直拆分array_split():可指定轴
a = np.floor(10 * rg.random((2, 12)))
np.hsplit(a, 3) # 平均拆分为3份
np.hsplit(a, (3, 4)) # 在第3列和第4列之后拆分
拷贝与视图
1. 完全不拷贝(No Copy)
简单赋值不会创建新对象,只是给原数组加了一个新名字。
a = np.array([[1,2],[3,4]])
b = a
print(b is a) # True
函数传递也是引用,不会发生拷贝。
2. 视图或浅拷贝(View/Shallow Copy)
view():创建一个新数组对象,但共享底层数据。- 切片:返回的也是视图。
c = a.view()
print(c is a) # False
print(c.base is a) # True(c 是 a 的视图)
s = a[:, 1:3]
s[:] = 10 # 修改 s 会同时修改 a
3. 深拷贝(Deep Copy)
copy():创建完全独立的数组副本,不共享数据。
d = a.copy()
d[0,0] = 999 # 修改 d 不影响 a
内存提示:如果从一个巨大的数组中切片一小部分并希望释放大数组,务必使用 copy()。例如:
b = a[:100].copy() # 独立的小数组,原数组 a 可被释放
del a # 释放内存
常用函数与方法速查
数组创建
arange, array, copy, empty, empty_like, eye, fromfile, fromfunction, identity, linspace, logspace, mgrid, ogrid, ones, ones_like, r_, c_, zeros, zeros_like
类型转换
ndarray.astype, atleast_1d, atleast_2d, atleast_3d, mat
形状操作
array_split, column_stack, concatenate, diagonal, dsplit, dstack, hsplit, hstack, ndarray.item, newaxis, ravel, repeat, reshape, resize, squeeze, swapaxes, take, transpose, vsplit, vstack
逻辑判断
all, any, nonzero, where
排序与搜索
argmax, argmin, argsort, max, min, ptp, searchsorted, sort
运算
choose, compress, cumprod, cumsum, inner, ndarray.fill, imag, prod, put, putmask, real, sum
统计与线性代数
- 统计:
cov,mean,std,var - 线性代数:
cross,dot,outer,linalg.svd,vdot
NumPy 常用函数速查表
按功能分类,附简洁示例,方便你随时查阅。
1. 数组创建
| 函数 | 说明 | 示例 |
|---|---|---|
np.array([1,2,3]) |
从列表或元组创建数组 | a = np.array([1,2,3]) |
np.zeros((3,4)) |
创建全0数组,参数为形状 | np.zeros((2,3)) → 2行3列的全0矩阵 |
np.ones((2,2)) |
创建全1数组 | np.ones((2,2)) |
np.empty((2,3)) |
创建未初始化数组(值随机) | 性能高,但值不确定 |
np.arange(0,10,2) |
类似Python range,生成等差数列 | np.arange(0,10,2) → [0,2,4,6,8] |
np.linspace(0,1,5) |
生成指定间隔内的等间隔数 | np.linspace(0,1,5) → [0. , 0.25, 0.5 , 0.75, 1. ] |
np.random.rand(3,2) |
生成[0,1)均匀分布的随机数 | 3行2列 |
np.random.randn(3,2) |
生成标准正态分布的随机数 | 均值为0,方差为1 |
np.random.randint(0,10,(3,3)) |
生成随机整数 | 范围[0,10),形状3x3 |
np.eye(4) |
创建单位矩阵 | 4x4对角线上为1 |
2. 数组属性
| 属性 | 说明 | 示例 |
|---|---|---|
arr.shape |
返回数组形状元组 | (3,4) |
arr.dtype |
返回元素数据类型 | int64, float32 |
arr.size |
返回元素总数 | 等于各维度乘积 |
arr.ndim |
返回数组维度数 | 1维、2维等 |
arr.T |
转置(仅对2维有效) | 相当于 arr.transpose() |
3. 数组操作
| 函数 | 说明 | 示例 |
|---|---|---|
arr.reshape(2,3) |
改变形状,不改变数据 | 原数组必须大小匹配 |
arr.resize(2,3) |
改变形状,会修改原数组 | 与reshape不同,直接修改 |
arr.flatten() |
展平为一维数组(返回副本) | 按行优先 |
arr.ravel() |
展平为一维数组(返回视图,节省内存) | 修改视图可能影响原数组 |
np.concatenate([a,b], axis=0) |
沿指定轴拼接数组 | axis=0按行堆叠,axis=1按列 |
np.vstack((a,b)) |
垂直堆叠(行增加) | 等价于axis=0的concatenate |
np.hstack((a,b)) |
水平堆叠(列增加) | 等价于axis=1的concatenate |
np.split(arr, 3, axis=0) |
将数组分割成子数组 | 指定份数或分割位置 |
np.transpose(arr, axes) |
转置或重排轴 | 对于高维数组有用 |
4. 数学运算
| 函数/操作 | 说明 | 示例 |
|---|---|---|
+ - * / |
逐元素运算(广播机制) | a + b 对应元素相加 |
np.sqrt(arr) |
开平方 | 也可用 arr**0.5 |
np.exp(arr) |
指数e^x | |
np.log(arr) |
自然对数 | np.log10(arr) 以10为底 |
np.sin(arr) |
三角函数 | cos, tan 等 |
@ 或 np.dot(a,b) |
矩阵乘法(不是逐元素乘) | a @ b |
np.power(arr, 3) |
幂运算 | 也可用 arr**3 |
np.abs(arr) |
绝对值 |
5. 统计函数
| 函数 | 说明 | 示例 |
|---|---|---|
np.sum(arr) |
求和 | axis参数指定维度,如 np.sum(arr, axis=0) 按列求和 |
np.mean(arr) |
平均值 | |
np.median(arr) |
中位数 | |
np.min(arr) |
最小值 | np.max 最大值 |
np.std(arr) |
标准差 | np.var 方差 |
np.argmin(arr) |
最小值索引 | np.argmax 最大值索引 |
np.cumsum(arr) |
累积和 | 返回数组 |
np.percentile(arr, 75) |
计算百分位数 | 75%分位数 |
6. 索引与切片
| 语法 | 说明 | 示例 |
|---|---|---|
arr[i] |
取第i行(对二维数组) | |
arr[i, j] |
取第i行第j列元素 | |
arr[1:3, :] |
切片:行1到2,所有列 | 左闭右开 |
arr[arr > 5] |
布尔索引:选取大于5的元素 | 返回一维数组 |
arr[[0,2], :] |
花式索引:取第0行和第2行 | 可指定行列表 |
arr[:, [1,3]] |
取所有行的第1列和第3列 |
7. 线性代数(np.linalg)
| 函数 | 说明 | 示例 |
|---|---|---|
np.linalg.inv(a) |
矩阵求逆 | a必须为方阵且可逆 |
np.linalg.det(a) |
行列式 | |
np.linalg.eig(a) |
特征值和特征向量 | 返回元组 (特征值, 特征向量) |
np.linalg.solve(a, b) |
解线性方程组 a x = b | |
np.linalg.qr(a) |
QR分解 | |
np.linalg.svd(a) |
奇异值分解 |
8. 其他实用函数
| 函数 | 说明 | 示例 |
|---|---|---|
np.where(condition, x, y) |
根据条件从x或y中取值 | np.where(arr>0, arr, 0) 将负数变0 |
np.unique(arr) |
去重并排序 | 返回唯一值数组 |
np.sort(arr) |
排序 | axis指定轴,np.argsort返回排序索引 |
np.clip(arr, a_min, a_max) |
将值限制在[a_min, a_max]之间 | 小于a_min的变a_min,大于a_max的变a_max |
np.save('file.npy', arr) |
保存数组到二进制文件 | np.load('file.npy') 读取 |
np.savetxt('file.csv', arr, delimiter=',') |
保存为文本文件 | np.loadtxt('file.csv', delimiter=',') 读取 |
小贴士:
- 想查看函数的完整文档?在Jupyter里输入
np.mean?或help(np.mean)即可。- 多用
axis参数,它控制操作沿着哪个维度进行,是NumPy的精髓。- 遇到“广播”不理解?记住:NumPy会自动将小数组扩展到大数组的形状,只要维度兼容。
这份速查表涵盖了日常使用频率最高的NumPy函数。建议你把这些示例在Jupyter Notebook里敲一遍,边敲边体会。当你用Pandas处理数据时,很多底层操作仍然依赖NumPy,扎实的基础会让你的数据分析之路越走越顺。
接下来你可以尝试用NumPy做一些小练习,比如生成随机矩阵并计算统计量、模拟简单线性回归等。
你这份NumPy速查表整理得非常全面,涵盖了日常工作中95%以上的常用功能。可以说,掌握这张表的内容,就已经能非常从容地应对绝大多数数据分析、科学计算和面试场景了。
✅ 你已经覆盖的核心领域
从你的速查表分类来看,它已经完整包含了以下关键模块:
- 数组创建:从基础的
array、zeros,到序列生成arange/linspace,再到随机数rand/randint,一应俱全。 - 数组属性与操作:
shape、dtype等属性,以及reshape、flatten、各种堆叠拼接(vstack/hstack),都是日常高频使用的。 - 数学与统计:逐元素运算、矩阵乘法
@、统计函数(sum/mean/std)和基础线性代数(inv/det/solve)都已覆盖。 - 索引与切片:普通索引、切片、布尔索引、花式索引这些核心技巧都列出来了。
- 实用函数:
where、unique、clip、文件读写save/loadtxt等,都是非常实用的工具。
🔍 查漏补缺:可能还需要了解的一些补充点
| 类别 | 补充函数/概念 | 说明与示例 |
|---|---|---|
| 高级索引 | np.take(a, indices) |
沿轴取元素,类似花式索引,但某些场景下性能更好。np.take(arr, [0,2], axis=1) |
np.ix_ |
构造开放网格,用于组合多个索引数组进行花式索引。arr[np.ix_([0,2], [1,3])] |
|
| 数组操作 | np.roll(a, shift) |
循环移动数组元素。np.roll([1,2,3,4], 1) → [4,1,2,3] |
np.flip(a, axis) |
沿指定轴翻转数组顺序。np.flip(arr, axis=0) 上下翻转行。 |
|
np.repeat(a, repeats) |
重复数组元素。np.repeat([1,2], 3) → [1,1,1,2,2,2] |
|
np.tile(a, reps) |
平铺数组来构造更大的数组。np.tile([1,2], (2,2)) 生成2x2的平铺矩阵。 |
|
| 数学运算 | np.cross(a, b) |
计算两个向量的叉积。 |
np.outer(a, b) |
计算两个向量的外积。 | |
np.angle(z) / np.real / np.imag |
复数操作:计算辐角、实部、虚部。 | |
| 逻辑与集合 | np.isin(a, b) |
判断a的元素是否在b中,返回布尔数组。np.isin([1,2,3], [2,4]) → [False, True, False] |
np.intersect1d / union1d / setdiff1d |
集合操作(虽然unique常用,但专门集合函数也很方便)。 |
|
| 随机数 | np.random.choice(a, size, p) |
从一维数组中随机抽取元素,可指定概率p。np.random.choice(['A','B'], 10, p=[0.3,0.7]) |
np.random.shuffle(a) |
就地随机打乱数组顺序。 | |
| 底层与性能 | np.einsum(subscripts, *operands) |
爱因斯坦求和约定,是一种极其强大(但稍复杂)的方式来表达各种数组运算(如矩阵乘法、转置、求和等)。np.einsum('ij,jk->ik', A, B) 等价于 A @ B。 |
np.may_share_memory(a, b) |
检查两个数组是否共享内存(即是否是视图关系)。 |
NumPy 练习题(共50题)
说明:以下练习题旨在帮助你掌握 NumPy 的核心功能。请尽量在不查答案的情况下独立完成,每道题建议在 Jupyter Notebook 中实际运行验证。题目难度逐渐增加,部分题目可能需要结合多个知识点。
基础篇(1-15题):数组创建、属性、基本操作
-
导入 NumPy 库,并查看版本号。
-
创建一个长度为 10 的一维全零数组。
-
创建一个形状为 (3,4) 的全一数组,并指定数据类型为 int32。
-
创建一个 3x3 的单位矩阵。
-
创建一个从 10 到 49 的一维数组。
-
创建一个 2x5 的数组,元素为 0 到 9(按行填充)。
-
创建一个长度为 100 的等间隔数列,范围从 0 到 1(包含端点)。
-
创建一个 4x4 的随机数组(均匀分布),并打印其形状、维度和数据类型。
-
创建一个 5x5 的随机整数数组,取值范围在 [0, 10) 之间。
-
将上题生成的数组的所有元素转换为 float64 类型。
-
创建一个长度为 20 的一维数组,元素全为 0,然后将第 5 个元素(索引从0开始)改为 1。
-
创建一个 3x3 的数组,元素为 1 到 9,并求出所有元素的和。
-
创建一个 4x4 的对角矩阵,对角线元素为 1,2,3,4。
-
生成一个 3x3 的标准正态分布随机数组。
-
创建一个 5 元素的一维数组,并访问其最后三个元素。
索引与切片篇(16-25题)
-
创建一个 6x6 的随机整数数组,元素范围在 0-100,提取出第 2 行(索引从0开始)。
-
从上述数组中提取第 3 列的所有元素。
-
提取上述数组的左上角 3x3 子矩阵。
-
将上述数组的所有奇数行和偶数列的元素取出。
-
创建一个 4x4 的数组,将其第 1 行和第 3 行交换。
-
创建一个 8x8 的数组,用 0 和 1 填充成棋盘格样式(0 在 (0,0) 位置)。
-
创建一个一维数组
arr = np.array([1,2,3,4,5,6,7,8,9]),将其索引为奇数的元素替换为 -1。 -
创建一个 5x5 的随机数组,找出所有大于 0.5 的元素,并将它们赋值为 1。
-
创建一个 10x10 的随机数组,找到每一行的最大值位置(列索引)。
-
创建一个 3x4 的数组,使用花式索引提取第 0 行和第 2 行,以及第 1 列和第 3 列(结果应为 2x2 矩阵)。
形状操作与广播篇(26-35题)
-
创建一个 1x6 的一维数组,然后将其重塑为 2x3 的二维数组。
-
创建一个 2x3x4 的三维随机数组,将其展平为一维。
-
创建两个形状分别为 (3,1) 和 (1,4) 的数组,利用广播机制计算它们的和,结果形状为 (3,4)。
-
创建一个长度为 10 的一维数组,将其形状变为 (2,5),然后再转置。
-
创建一个 5x5 的数组,将第 1 行与第 2 行垂直堆叠(不修改原数组)。
-
创建两个 3x3 的随机数组 A 和 B,将它们水平拼接(列数增加)。
-
将数组
np.array([1,2,3])沿着新轴变成列向量(形状 (3,1))和行向量(形状 (1,3))。 -
创建一个 4x4 数组,使用
resize将其变为 2x8(注意resize与reshape的区别)。 -
创建两个一维数组 a 和 b,长度分别为 5 和 3,通过广播实现外积(结果形状 (5,3))。
-
创建一个 3x3 数组,将其每一行减去该行的平均值。
数学运算与统计篇(36-45题)
-
创建一个 4x4 随机整数数组,计算所有元素的均值、标准差和方差。
-
计算上述数组每列的和,以及每行的最大值。
-
创建一个 5x5 数组,计算其对角线元素的和(主对角线)。
-
计算数组
np.array([[1,2],[3,4]])与np.array([[5,6],[7,8]])的矩阵乘积(点积)。 -
创建一个 3x3 的随机矩阵,求它的逆矩阵(假设可逆)。
-
解线性方程组:
x + 2y = 5
3x + 4*y = 6
使用 NumPy 求解。 -
计算数组
np.array([1,2,3,4])的累积和。 -
创建一个 10x10 的随机数组,找到全局最小值的位置(索引)。
-
创建一个 3x4 的数组,计算每行的最大值与最小值之差(极差)。
-
对数组
np.array([[3,1,2],[6,4,5]])按列排序(升序)。
进阶与综合篇(46-50题)
-
创建一个 1000 个元素的一维随机数组,找出其中出现频率最高的值(众数)。如果有多个众数,返回最小的那个。
-
实现一个简单的移动平均函数,输入一维数组和窗口大小 k,返回移动平均值数组(长度与原数组相同,前 k-1 个元素可用 NaN 填充)。
-
创建一个 20x20 的随机数组,使用布尔索引将所有大于 0.5 的元素替换为 NaN,并计算剩余元素的均值。
-
生成一个 5x5 的随机整数矩阵,计算其特征值和特征向量。
-
模拟一个 1000 次投掷两枚骰子的实验,统计点数之和的分布(直方图),并找出最可能出现的和。
答案部分
1. 导入 NumPy 并查看版本号
import numpy as np
print(np.__version__)
2. 长度为 10 的全零数组
arr = np.zeros(10)
print(arr)
3. 形状 (3,4) 的全一数组,int32 类型
arr = np.ones((3,4), dtype=np.int32)
print(arr)
4. 3x3 单位矩阵
arr = np.eye(3)
print(arr)
5. 从 10 到 49 的一维数组
arr = np.arange(10, 50)
print(arr)
6. 2x5 数组,元素 0-9 按行填充
arr = np.arange(10).reshape(2,5)
print(arr)
7. 从 0 到 1 的等间隔数列,长度 100
arr = np.linspace(0, 1, 100)
print(arr)
8. 4x4 均匀分布随机数组,打印属性
arr = np.random.rand(4,4)
print("形状:", arr.shape)
print("维度:", arr.ndim)
print("数据类型:", arr.dtype)
9. 5x5 随机整数数组 [0,10)
arr = np.random.randint(0, 10, size=(5,5))
print(arr)
10. 将上题数组转换为 float64
arr_float = arr.astype(np.float64)
print(arr_float.dtype)
11. 长度为 20 的零数组,将第 5 个元素改为 1
arr = np.zeros(20)
arr[5] = 1
print(arr)
12. 3x3 数组 1-9,求和
arr = np.arange(1,10).reshape(3,3)
total = np.sum(arr)
print(total)
13. 4x4 对角矩阵,对角线元素 1,2,3,4
arr = np.diag([1,2,3,4])
print(arr)
14. 3x3 标准正态分布随机数组
arr = np.random.randn(3,3)
print(arr)
15. 一维数组,访问最后三个元素
arr = np.array([10,20,30,40,50])
print(arr[-3:])
16. 提取第 2 行(索引从0开始)
arr = np.random.randint(0,100,size=(6,6))
row2 = arr[2,:]
print(row2)
17. 提取第 3 列
col3 = arr[:,3]
print(col3)
18. 左上角 3x3 子矩阵
sub = arr[:3, :3]
print(sub)
19. 奇数行和偶数列
# 奇数行:索引1,3,5...;偶数列:索引0,2,4...
result = arr[1::2, ::2]
print(result)
20. 交换第 1 行和第 3 行
arr = np.random.randint(0,10,size=(4,4))
arr[[0,2]] = arr[[2,0]] # 索引0和2对应第1行和第3行
print(arr)
21. 8x8 棋盘格
arr = np.zeros((8,8), dtype=int)
arr[1::2, ::2] = 1
arr[::2, 1::2] = 1
print(arr)
22. 将奇数索引元素替换为 -1
arr = np.array([1,2,3,4,5,6,7,8,9])
arr[1::2] = -1
print(arr)
23. 大于 0.5 的元素赋值为 1
arr = np.random.rand(5,5)
arr[arr > 0.5] = 1
print(arr)
24. 每行最大值的位置
arr = np.random.rand(10,10)
max_pos = np.argmax(arr, axis=1)
print(max_pos)
25. 花式索引提取子矩阵
arr = np.random.randint(0,10,size=(3,4))
result = arr[[0,2]][:, [1,3]] # 先取行,再取列
# 或者用 np.ix_: result = arr[np.ix_([0,2],[1,3])]
print(result)
26. 重塑为 2x3
a = np.arange(6).reshape(1,6)
b = a.reshape(2,3)
print(b)
27. 展平三维数组
arr = np.random.rand(2,3,4)
flat = arr.flatten() # 或 arr.ravel()
print(flat.shape)
28. 广播求和
a = np.array([[1],[2],[3]]) # 形状(3,1)
b = np.array([[1,2,3,4]]) # 形状(1,4)
c = a + b # 广播后形状(3,4)
print(c)
29. 变形状再转置
a = np.arange(10)
a_2x5 = a.reshape(2,5)
a_T = a_2x5.T
print(a_T)
30. 垂直堆叠两行
arr = np.random.randint(0,10,size=(5,5))
stacked = np.vstack((arr[1,:], arr[2,:]))
print(stacked)
31. 水平拼接两个数组
A = np.random.randint(0,10,(3,3))
B = np.random.randint(0,10,(3,3))
C = np.hstack((A,B))
print(C.shape)
32. 变成列向量和行向量
a = np.array([1,2,3])
col = a[:, np.newaxis] # 形状(3,1)
row = a[np.newaxis, :] # 形状(1,3)
print(col.shape, row.shape)
33. resize 变为 2x8
arr = np.arange(16).reshape(4,4)
arr_resized = np.resize(arr, (2,8)) # resize 会重复填充
print(arr_resized)
34. 外积
a = np.array([1,2,3,4,5])
b = np.array([2,3,4])
outer = a[:, np.newaxis] * b[np.newaxis, :]
print(outer)
35. 每行减去行平均值
arr = np.random.randint(0,10,(3,3))
row_means = arr.mean(axis=1, keepdims=True) # 保持维度以便广播
centered = arr - row_means
print(centered)
36. 均值、标准差、方差
arr = np.random.randint(0,100,(4,4))
mean = np.mean(arr)
std = np.std(arr)
var = np.var(arr)
print(mean, std, var)
37. 每列和、每行最大值
col_sum = np.sum(arr, axis=0)
row_max = np.max(arr, axis=1)
print(col_sum, row_max)
38. 对角线元素和
arr = np.random.randint(0,10,(5,5))
trace = np.trace(arr)
print(trace)
39. 矩阵乘积
A = np.array([[1,2],[3,4]])
B = np.array([[5,6],[7,8]])
C = np.dot(A, B) # 或 A @ B
print(C)
40. 求逆矩阵
A = np.random.rand(3,3)
A_inv = np.linalg.inv(A)
print(A_inv)
41. 解线性方程组
# x + 2y = 5, 3x + 4y = 6
A = np.array([[1,2],[3,4]])
b = np.array([5,6])
x = np.linalg.solve(A, b)
print(x)
42. 累积和
a = np.array([1,2,3,4])
cum = np.cumsum(a)
print(cum)
43. 全局最小值位置
arr = np.random.rand(10,10)
min_idx = np.unravel_index(np.argmin(arr), arr.shape)
print(min_idx)
44. 每行的极差
arr = np.random.randint(0,50,(3,4))
row_range = np.ptp(arr, axis=1) # peak to peak
print(row_range)
45. 按列排序
arr = np.array([[3,1,2],[6,4,5]])
sorted_arr = np.sort(arr, axis=0)
print(sorted_arr)
46. 找出众数(频率最高的值)
arr = np.random.randint(0,10,1000)
values, counts = np.unique(arr, return_counts=True)
mode = values[np.argmax(counts)]
print(mode)
47. 移动平均
def moving_average(a, k=3):
ret = np.cumsum(a, dtype=float)
ret[k:] = ret[k:] - ret[:-k]
ret[:k-1] = np.nan
ret[k-1:] = ret[k-1:] / k
return ret
a = np.arange(10)
print(moving_average(a, 3))
48. 大于 0.5 替换为 NaN,并计算剩余均值
arr = np.random.rand(20,20)
arr[arr > 0.5] = np.nan
mean_without_nan = np.nanmean(arr)
print(mean_without_nan)
49. 特征值和特征向量
arr = np.random.randint(1,10,(5,5))
eigenvalues, eigenvectors = np.linalg.eig(arr)
print(eigenvalues)
print(eigenvectors)
50. 两枚骰子点数之和分布
results = np.random.randint(1,7,size=(1000,2)) # 1000次,每次两枚
sums = results.sum(axis=1)
unique, counts = np.unique(sums, return_counts=True)
most_common_sum = unique[np.argmax(counts)]
print("最可能出现的和:", most_common_sum)
# 可选:绘制直方图(需 matplotlib)
import matplotlib.pyplot as plt
plt.hist(sums, bins=range(2,14), align='left', rwidth=0.8)
plt.show()
更多推荐
所有评论(0)