Python数据分析学习(一):Numpy

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 列表 ab 中,通常我们会这样写:

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.int32numpy.float64 等。
  • ndarray.itemsize:数组中每个元素的字节大小。例如,float64itemsize 为 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 += ba 是 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 提供了许多数学函数,如 sincosexpsqrt 等,它们被称为“通用函数”(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%以上的常用功能。可以说,掌握这张表的内容,就已经能非常从容地应对绝大多数数据分析、科学计算和面试场景了。

✅ 你已经覆盖的核心领域

从你的速查表分类来看,它已经完整包含了以下关键模块:

  1. 数组创建:从基础的arrayzeros,到序列生成arange/linspace,再到随机数rand/randint,一应俱全。
  2. 数组属性与操作shapedtype等属性,以及reshapeflatten、各种堆叠拼接(vstack/hstack),都是日常高频使用的。
  3. 数学与统计:逐元素运算、矩阵乘法@、统计函数(sum/mean/std)和基础线性代数(inv/det/solve)都已覆盖。
  4. 索引与切片:普通索引、切片、布尔索引、花式索引这些核心技巧都列出来了。
  5. 实用函数whereuniqueclip、文件读写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题):数组创建、属性、基本操作
  1. 导入 NumPy 库,并查看版本号。

  2. 创建一个长度为 10 的一维全零数组。

  3. 创建一个形状为 (3,4) 的全一数组,并指定数据类型为 int32。

  4. 创建一个 3x3 的单位矩阵。

  5. 创建一个从 10 到 49 的一维数组。

  6. 创建一个 2x5 的数组,元素为 0 到 9(按行填充)。

  7. 创建一个长度为 100 的等间隔数列,范围从 0 到 1(包含端点)。

  8. 创建一个 4x4 的随机数组(均匀分布),并打印其形状、维度和数据类型。

  9. 创建一个 5x5 的随机整数数组,取值范围在 [0, 10) 之间。

  10. 将上题生成的数组的所有元素转换为 float64 类型。

  11. 创建一个长度为 20 的一维数组,元素全为 0,然后将第 5 个元素(索引从0开始)改为 1。

  12. 创建一个 3x3 的数组,元素为 1 到 9,并求出所有元素的和。

  13. 创建一个 4x4 的对角矩阵,对角线元素为 1,2,3,4。

  14. 生成一个 3x3 的标准正态分布随机数组。

  15. 创建一个 5 元素的一维数组,并访问其最后三个元素。


索引与切片篇(16-25题)
  1. 创建一个 6x6 的随机整数数组,元素范围在 0-100,提取出第 2 行(索引从0开始)。

  2. 从上述数组中提取第 3 列的所有元素。

  3. 提取上述数组的左上角 3x3 子矩阵。

  4. 将上述数组的所有奇数行和偶数列的元素取出。

  5. 创建一个 4x4 的数组,将其第 1 行和第 3 行交换。

  6. 创建一个 8x8 的数组,用 0 和 1 填充成棋盘格样式(0 在 (0,0) 位置)。

  7. 创建一个一维数组 arr = np.array([1,2,3,4,5,6,7,8,9]),将其索引为奇数的元素替换为 -1。

  8. 创建一个 5x5 的随机数组,找出所有大于 0.5 的元素,并将它们赋值为 1。

  9. 创建一个 10x10 的随机数组,找到每一行的最大值位置(列索引)。

  10. 创建一个 3x4 的数组,使用花式索引提取第 0 行和第 2 行,以及第 1 列和第 3 列(结果应为 2x2 矩阵)。


形状操作与广播篇(26-35题)
  1. 创建一个 1x6 的一维数组,然后将其重塑为 2x3 的二维数组。

  2. 创建一个 2x3x4 的三维随机数组,将其展平为一维。

  3. 创建两个形状分别为 (3,1) 和 (1,4) 的数组,利用广播机制计算它们的和,结果形状为 (3,4)。

  4. 创建一个长度为 10 的一维数组,将其形状变为 (2,5),然后再转置。

  5. 创建一个 5x5 的数组,将第 1 行与第 2 行垂直堆叠(不修改原数组)。

  6. 创建两个 3x3 的随机数组 A 和 B,将它们水平拼接(列数增加)。

  7. 将数组 np.array([1,2,3]) 沿着新轴变成列向量(形状 (3,1))和行向量(形状 (1,3))。

  8. 创建一个 4x4 数组,使用 resize 将其变为 2x8(注意 resizereshape 的区别)。

  9. 创建两个一维数组 a 和 b,长度分别为 5 和 3,通过广播实现外积(结果形状 (5,3))。

  10. 创建一个 3x3 数组,将其每一行减去该行的平均值。


数学运算与统计篇(36-45题)
  1. 创建一个 4x4 随机整数数组,计算所有元素的均值、标准差和方差。

  2. 计算上述数组每列的和,以及每行的最大值。

  3. 创建一个 5x5 数组,计算其对角线元素的和(主对角线)。

  4. 计算数组 np.array([[1,2],[3,4]])np.array([[5,6],[7,8]]) 的矩阵乘积(点积)。

  5. 创建一个 3x3 的随机矩阵,求它的逆矩阵(假设可逆)。

  6. 解线性方程组:
    x + 2y = 5
    3
    x + 4*y = 6
    使用 NumPy 求解。

  7. 计算数组 np.array([1,2,3,4]) 的累积和。

  8. 创建一个 10x10 的随机数组,找到全局最小值的位置(索引)。

  9. 创建一个 3x4 的数组,计算每行的最大值与最小值之差(极差)。

  10. 对数组 np.array([[3,1,2],[6,4,5]]) 按列排序(升序)。


进阶与综合篇(46-50题)
  1. 创建一个 1000 个元素的一维随机数组,找出其中出现频率最高的值(众数)。如果有多个众数,返回最小的那个。

  2. 实现一个简单的移动平均函数,输入一维数组和窗口大小 k,返回移动平均值数组(长度与原数组相同,前 k-1 个元素可用 NaN 填充)。

  3. 创建一个 20x20 的随机数组,使用布尔索引将所有大于 0.5 的元素替换为 NaN,并计算剩余元素的均值。

  4. 生成一个 5x5 的随机整数矩阵,计算其特征值和特征向量。

  5. 模拟一个 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()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值