5. Numpy 简介#
Numpy (Numerical Python) 是 Python 语言一个重要的扩展库,支持大量的数组与矩阵运算,此外也提供大量的数学函数库,用于模仿数学软件 MatLab 的功能。Numpy 通常与其他库 SciPy(Scientific Python)和 Matplotlib(绘图库)一起使用。
Numpy 的主要特点是:
一个强大的 N 维数组对象 ndarray
矩阵运算、傅里叶变换、生成随机数功能等
使用 numpy 需要首先导入 numpy 包:
import numpy as np
5.1. 创建数组#
用 Numpy 创建数组有多种方法。首先,Numpy 中的array
函数可以直接将 Python 的 list 类型转化为 Numpy 的数组类型 ndarray。例如,一个一维数组:
a = np.array([1, 2, 3, 4])
a
array([1, 2, 3, 4])
一个二维数组:
b = [[1, 2], [3, 4]]
a = np.array(b)
a
array([[1, 2],
[3, 4]])
注意,array
函数中的小括号中要包括一个用中括号括起来的 list,不能直接写成 np.array(1, 2, 3, 4)。
Numpy 中的zeros
函数可以创建元素值全为 0 的矩阵,ones
函数可以创建元素值全为 1 的矩阵,而empty
函数可以创建一个元素值任意的一个空矩阵。例如:
np.zeros((3, 4)) # 3 行 4 列的零矩阵
array([[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]])
np.ones((3, 4)) # 3 行 4 列的一个矩阵
array([[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.]])
np.empty((2, 3)) # 2 行 3 列的空矩阵
array([[0., 0., 0.],
[0., 0., 0.]])
Numpy 中的arange
函数可以生成一个等差数列的数组,例如:
np.arange(10) # 生成一个从 0 到 9 之间的数组,默认步长为 1
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
np.arange(5, 10) # 生成一个从 5 到 9 之间的数组,默认步长为 1
array([5, 6, 7, 8, 9])
np.arange(5, 10, 2) # 生成一个从 5 到 9 之间的数组,且步长为 2
array([5, 7, 9])
另外一个类似的函数为linespace
,不同的地方在于:arange
函数中第三个参数表示等差数组的步长,而linespace
函数第三个参数表示一共生成的元素个数。若生成一系列等差的浮点数,则用linespace
更好些。
np.linspace(0, 2, 9) # 生成从 0 到 2 之间共 9 个数
array([0. , 0.25, 0.5 , 0.75, 1. , 1.25, 1.5 , 1.75, 2. ])
Python 的 list 类型可以与 Numpy 的数组类型 ndarray 互换,例如:
a = np.arange(10)
list(a)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
numpy 库中常见的数组创建函数如下表所示:
函数 |
描述 |
---|---|
np.arrange(x, y, i) |
创建一个由 x 到 y,以 i 为步长的数组 |
np.linspace(x, y, n) |
创建一个由 x 到 y,等分为 n 个元素的数组 |
np.ones((m,n)) |
创建一个 m 行 n 列全是 1 的数组 |
np.empty((m,n)) |
创建一个 m 行 n 列全是 0 的数组 |
numpy 创建的数组类型为 ndarray类型,它的常用属性如下表所示:
函数 |
描述 |
---|---|
ndarray.ndim |
数组的行数 |
ndarray.shape |
数组在每个维度上大小的整数元组 |
ndarray.size |
数组中元素的个数 |
ndarray.dtype |
数组中元素的数据类型 |
a = np.ones((2, 3))
a.ndim
2
a.shape
(2, 3)
a.size
6
a.dtype
dtype('float64')
5.2. 数组索引和切片#
对于一维数组,numpy 的索引切片类似 Python list 类型的索引切片,例如:
a = np.arange(4, 10) # 生成一个从 4 到 9 之间的数组
a
array([4, 5, 6, 7, 8, 9])
a[2] # 数组 a 的第 3 个元素
6
a[2:4] # 数组 a 的第 3 与第 4 个元素
array([6, 7])
a[-1] # 数组 a 的最后一个元素
9
a[::-1] # 数组 a 倒序
array([9, 8, 7, 6, 5, 4])
对于多维数组,Numpy 数组的索引和切片在一个中括号里面用逗号分隔不同维度,例如:
b = np.arange(12).reshape(3, 4) # 创建一个 3 行 4 列的二维数组,reshape函数不改变数值,将原数组重组为一个指定行数列数的数组
b
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
b[1, 2] # 二维数组第 2 行第 3 列中的元素
6
b[1:3, 2] # 二维数组第 3 列中, 第 2 行到第 3 行的元素
array([ 6, 10])
b[2, :] # 第 3 行的全部元素
array([ 8, 9, 10, 11])
list(b)
[array([0, 1, 2, 3]), array([4, 5, 6, 7]), array([ 8, 9, 10, 11])]
5.3. 数组拼接#
Numpy 中拼接两个数组用append
函数。
a = np.arange(5)
a
array([0, 1, 2, 3, 4])
b = np.arange(3)
b
array([0, 1, 2])
np.append(a, b)
array([0, 1, 2, 3, 4, 0, 1, 2])
多个数组拼接,可以用concatenate
。
c = np.arange(4)
c
array([0, 1, 2, 3])
np.concatenate((a, b, c)) # 注意里面还有一对小括号
array([0, 1, 2, 3, 4, 0, 1, 2, 0, 1, 2, 3])
5.4. 数组运算#
Numpy 可以对数组进行多种代数运算,例如:
a = np.arange(4)
a
array([0, 1, 2, 3])
b = np.arange(3, 7)
b
array([3, 4, 5, 6])
a - b # 两数组相减
array([-3, -3, -3, -3])
a + b # 两数组相加
array([3, 5, 7, 9])
a * 2 # 数组每个元素乘以一个数值
array([0, 2, 4, 6])
a**2 # 数组每个元素都平方
array([0, 1, 4, 9])
a > 2 # 数组每个元素与一个数值比较大小
array([False, False, False, True])
c = np.array([[4.0, 5.0], [6.0, 7.0]])
c
array([[4., 5.],
[6., 7.]])
c.transpose() # c 的转置矩阵
array([[4., 6.],
[5., 7.]])
np.linalg.inv(c) # c 的逆矩阵
array([[-3.5, 2.5],
[ 3. , -2. ]])
eigenvalues, eigenvectors = np.linalg.eig(c) # c 的特征值与特征向量
print("eigenvalues are ", eigenvalues)
print("eigenvectors are", eigenvectors)
eigenvalues are [-0.17890835 11.17890835]
eigenvectors are [[-0.76729658 -0.57152478]
[ 0.64129241 -0.82058481]]
d = np.array([[1.0, 2.0], [3.0, 4.0]])
d
array([[1., 2.],
[3., 4.]])
np.dot(c, d) # 矩阵 c 和 d 的乘积
array([[19., 28.],
[27., 40.]])
np.multiply(c, d) # 矩阵 c 和 d 对应元素相乘
array([[ 4., 10.],
[18., 28.]])
numpy 库还有一些其他常用的函数,如下表所示:
函数 |
描述 |
---|---|
np.abs(x) |
计算每个元素的绝对值 |
np.sqrt(x) |
计算每个元素的平方根 |
np.squre(x) |
计算每个元素的平方 |
np.sign(x) |
计算每个元素的正负号 |
np.ceil(x) |
计算每个元素向上取整的数值 |
np.floor(x) |
计算每个元素向下取整的数值 |
np.exp(x) |
计算每个元素的指数值 |
np.log(x),np.log10(x),np.log2(x) |
计算每个元素的自然对数值,基于10、2的对数值 |
另外,Numpy 还有专门的二维数组的类型 Matrix,可以更方便地进行一些矩阵运算,感兴趣的读者可以参见官网。
5.5. 生成随机数#
numpy 包的random
方法基本支持所有分布,并且能够一次生成多行多列的随机数, 例如:
import numpy as np
np.random.uniform(1, 10, [2, 2]) # 生成 [1, 10] 内的均匀分布随机数, 2 行 2 列
array([[7.09263517, 5.89191539],
[1.93501512, 9.28497785]])
np.random.uniform(1, 10, 5) # 生成 5 个 [1, 10] 内的均匀分布随机数
array([9.75077397, 2.43118187, 1.98607369, 1.07047913, 2.07363988])
np.random.randint(1, 10, [2, 2]) # 生成 [1, 10] 内的随机整数, 2 行 2 列
array([[4, 2],
[2, 9]])
np.random.normal(5, 1, [2, 2]) # 生成一个正态分布的随机数,均值为 5, 标准差为 1, 2 行 2 列
array([[5.69060984, 5.15048724],
[3.51455947, 5.03125812]])
np.random.poisson(5, [2, 2]) # 生成一个泊松分布的随机数,均值为 5, 2 行 2 列
array([[7, 1],
[3, 0]])
numpy 还可以通过random.seed()
参数设定随机数生成器的种子,同样的种子生成的随机数应该是相同的。
np.random.seed(500)
np.random.normal(5, 1, 6) # 生成 6 个正态分布的随机数,均值为 5, 标准差为 1
array([4.62263642, 5.16675892, 5.68280238, 6.92137877, 4.8029632 ,
4.24012124])
另外 numpy 还可以通过RandomState()
来定义一个随机数生成器对象,小括号里面的参数为随机数种子,然后用这个对象调用具体的各个随机分布生成器函数。例如:
rvs = np.random.RandomState(500)
rvs.normal(5, 1, 6) # 生成 6 个正态分布的随机数,均值为 5, 标准差为 1
array([4.62263642, 5.16675892, 5.68280238, 6.92137877, 4.8029632 ,
4.24012124])
5.6. Numpy 数组与列表 list 运算速度的对比#
Numpy 对于数值型数据的运算速度远快于 Python 自带的 list 列表。对于大规模的数学计算,优先使用 Numpy 处理。
import numpy as np
import time
# 使用 Python 原生 list
size = 1_000_000
py_list = list(range(size))
start = time.time()
py_list_squared = [x ** 2 for x in py_list] # 普通 Python 列表计算
print("Python List 耗时:", time.time() - start)
# 使用 NumPy 数组
np_array = np.arange(size)
start = time.time()
np_array_squared = np_array ** 2 # NumPy 直接进行向量化运算
print("NumPy 耗时:", time.time() - start)
Python List 耗时: 0.029808998107910156
NumPy 耗时: 0.001039266586303711
5.7. time
, datatime
模块#
5.7.1. time
模块#
time
模块提供了许多与时间相关的函数,如获取当前时间、暂停程序、测量执行时间等。
获取当前时间
import time
# 获取当前时间戳
timestamp = time.time()
print(timestamp)
1747833729.3150542
# 获取当前时间的结构化格式
current_time = time.localtime()
print(current_time)
time.struct_time(tm_year=2025, tm_mon=5, tm_mday=21, tm_hour=14, tm_min=22, tm_sec=9, tm_wday=2, tm_yday=141, tm_isdst=1)
# 格式化时间
formatted_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
print(formatted_time)
2025-05-21 14:22:09
时间转换
# 时间戳转时间字符串
timestamp = 1708193257
time_str = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(timestamp))
print(time_str)
2024-02-17 18:07:37
常见的 strftime 格式:
代码 |
含义 |
---|---|
%Y |
4 位数年份(如 2025) |
%m |
2 位数月份(01-12) |
%d |
2 位数日期(01-31) |
%H |
24 小时制小时(00-23) |
%M |
分钟(00-59) |
%S |
秒(00-59) |
# 时间字符串转时间戳
time_string = "2025-02-17 10:30:57"
time_tuple = time.strptime(time_string, "%Y-%m-%d %H:%M:%S")
timestamp = time.mktime(time_tuple)
print(timestamp)
1739788257.0
线程休眠
print("Start")
time.sleep(3) # 休眠 3 秒
print("End")
Start
End
计算程序运行时间
# 使用 time.time()
start = time.time()
for _ in range(1000000):
pass
end = time.time()
print(f"Execution time: {end - start:.6f} seconds")
Execution time: 0.039733 seconds
# 使用 time.perf_counter() 获取高精度时间
start = time.perf_counter()
for _ in range(1000000):
pass
end = time.perf_counter()
print(f"Execution time: {end - start:.6f} seconds")
Execution time: 0.027269 seconds
获取 CPU 运行时间
start = time.process_time()
for _ in range(1000000):
pass
end = time.process_time()
print(f"CPU time used: {end - start:.6f} seconds")
CPU time used: 0.022966 seconds
获取 UTC 时间
utc_time = time.gmtime()
print(time.strftime("%Y-%m-%d %H:%M:%S", utc_time))
2025-05-21 13:22:12
5.7.2. datetime
模块#
datetime
是 Python 标准库中的一个模块,提供日期、时间处理的功能,包括获取当前时间、日期计算、时区处理等。
获取当前时间
from datetime import datetime
# 获取当前本地时间
now = datetime.now()
print(now) # 输出示例: 2025-02-17 10:30:57.123456
2025-05-21 14:22:12.448168
from datetime import datetime, timezone
# 获取当前 UTC 时间
utc_now = datetime.now(timezone.utc)
print(utc_now) # 2025-02-17 10:30:57.123456+00:00
2025-05-21 13:22:12.451064+00:00
创建自定义时间
from datetime import datetime
# 创建指定时间
dt = datetime(2025, 2, 17, 10, 30, 57)
print(dt) # 2025-02-17 10:30:57
2025-02-17 10:30:57
from datetime import datetime
# 从时间戳创建时间
timestamp = 1708193457 # 2025-02-17 10:30:57 对应的时间戳
dt = datetime.fromtimestamp(timestamp) # 本地时间
utc_dt = datetime.utcfromtimestamp(timestamp) # UTC 时间
print(dt)
print(utc_dt)
2024-02-17 18:10:57
2024-02-17 18:10:57
/var/folders/qz/d57_41f55ylf02cqq8twh3540000gn/T/ipykernel_7217/2033922435.py:6: DeprecationWarning: datetime.datetime.utcfromtimestamp() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.fromtimestamp(timestamp, datetime.UTC).
utc_dt = datetime.utcfromtimestamp(timestamp) # UTC 时间
时间格式化
from datetime import datetime
dt = datetime(2025, 2, 17, 10, 30, 57)
# datetime 转字符串
formatted_str = dt.strftime("%Y-%m-%d %H:%M:%S")
print(formatted_str)
2025-02-17 10:30:57
from datetime import datetime
# 字符串 转 datetime
time_str = "2025-02-17 10:30:57"
dt = datetime.strptime(time_str, "%Y-%m-%d %H:%M:%S")
print(dt)
2025-02-17 10:30:57
时间计算
from datetime import datetime, timedelta
dt = datetime(2025, 2, 17, 10, 30, 57)
new_dt = dt + timedelta(days=5, hours=3)
print(new_dt)
2025-02-22 13:30:57
from datetime import datetime
dt1 = datetime(2025, 2, 17, 10, 30, 57)
dt2 = datetime(2025, 2, 20, 15, 0, 0)
diff = dt2 - dt1
print(diff)
print(diff.total_seconds())
3 days, 4:29:03
275343.0
处理时区
from datetime import datetime, timezone, timedelta
utc_now = datetime.now(timezone.utc)
beijing_time = utc_now.astimezone(timezone(timedelta(hours=8)))
print(beijing_time)
2025-05-21 21:22:12.471625+08:00
from datetime import datetime, timezone
local_time = datetime.now()
utc_time = local_time.astimezone(timezone.utc)
print(utc_time)
2025-05-21 13:22:12.474293+00:00