《Python星球日记》第22天:NumPy 基础

名人说:路漫漫其修远兮,吾将上下而求索。------ 屈原《离骚》
创作者:Code_流苏(CSDN) (一个喜欢古诗词和编程的Coder😊)

目录

    • [一、NumPy 简介](#一、NumPy 简介)
      • [1. 什么是 NumPy?为什么使用 NumPy?](#1. 什么是 NumPy?为什么使用 NumPy?)
      • [2. 安装与导入](#2. 安装与导入)
    • 二、多维数组操作
      • [1. 创建数组](#1. 创建数组)
      • [2. 数组属性](#2. 数组属性)
      • [3. 数组索引与切片](#3. 数组索引与切片)
    • 三、广播机制
      • [1. 广播的概念与应用](#1. 广播的概念与应用)
      • [2. 向量化计算的优势](#2. 向量化计算的优势)
    • 四、练习:实现矩阵加法和乘法
      • [1. 矩阵加法](#1. 矩阵加法)
      • [2. 矩阵乘法](#2. 矩阵乘法)
    • 五、总结与进阶方向
    • 参考资源

专栏介绍: Python星球日记专栏介绍(持续更新ing)
更多Python知识,请关注我、订阅专栏《 Python星球日记》,内容持续更新中...

上一篇Python星球日记 - 第21天:基础阶段大总结

🌟引言欢迎来到Python星球🪐的第22天

今天我们正式进入数据分析与可视化进阶篇,从NumPy基础开始我们的新旅程。NumPy是Python数据分析的基石,掌握它将为你打开数据科学的大门。

一、NumPy 简介

1. 什么是 NumPy?为什么使用 NumPy?

NumPy (Numerical Python)是Python中用于科学计算的基础库,它提供了高性能的多维数组对象和处理这些数组的工具。NumPy是数据分析、机器学习 等领域的基础,几乎所有数据科学相关的Python库都以NumPy为基础。

使用NumPy的主要优势:

优势 描述
1️⃣高效的内存管理 NumPy数组在内存中是连续存储的,比Python原生列表更加高效
2️⃣执行速度快 NumPy底层使用C语言实现,处理大规模数据时比Python原生列表快10-100
3️⃣丰富的数学函数 内置了大量的数学函数和线性代数操作
4️⃣广播功能 能够高效地进行不同形状数组之间的运算
5️⃣与其他库的兼容性 几乎所有数据科学相关的Python库都支持NumPy数组

2. 安装与导入

在开始使用NumPy之前,我们需要先安装它。可以使用pip进行安装:

python 复制代码
pip install numpy

安装完成后,在Python脚本中导入NumPy

python 复制代码
import numpy as np  # 通常使用np作为NumPy的简写别名

💡 小贴士 :使用别名np是数据科学社区的通用约定,这样可以减少代码量并提高可读性。

二、多维数组操作

NumPy的核心是ndarray(N-dimensional array,多维数组)对象,它是一个快速、灵活的大数据集容器。

1. 创建数组

有多种方法可以创建NumPy数组:

1️⃣从Python列表创建一维数组

使用np.array()函数从Python列表创建一个一维NumPy数组,这是NumPy中最基本的数组创建方法。

python 复制代码
import numpy as np
# 从Python列表创建数组
arr1 = np.array([1, 2, 3, 4, 5])
print("一维数组:", arr1)

2️⃣创建二维数组

创建二维数组(矩阵),通过传入嵌套列表来定义行和列。二维数组是科学计算中常用的数据结构。

python 复制代码
import numpy as np
# 创建二维数组
arr2 = np.array([[1, 2, 3], [4, 5, 6]])
print("二维数组:\n", arr2)

3️⃣创建全0数组

这个代码块说明了如何使用np.zeros()函数创建所有元素都为0的数组。这在初始化数组或作为占位符时非常有用。

python 复制代码
import numpy as np
# 创建全0数组
zeros = np.zeros((3, 4))  # 3行4列的全0数组
print("全0数组:\n", zeros)

4️⃣创建全1数组

这个代码块展示了np.ones()函数的使用,它创建一个所有元素都为1的数组。这在需要默认值为1的计算中很有用。

python 复制代码
import numpy as np
# 创建全1数组
ones = np.ones((2, 3))    # 2行3列的全1数组
print("全1数组:\n", ones)

5️⃣创建等差数列

这个代码块演示了如何使用np.arange()创建等差数列。该函数类似于Python的range(),但返回的是NumPy数组而不是列表

python 复制代码
import numpy as np
# 创建等差数列
arange = np.arange(0, 10, 2)  # 从0开始,步长为2,小于10
print("等差数列:", arange)

6️⃣创建等间隔数值点

这个代码块展示了np.linspace()函数,它创建指定范围内均匀分布的点。这在绘图和数值积分等应用中特别有用。

python 复制代码
import numpy as np
# 创建等间隔的数值点
linspace = np.linspace(0, 1, 5)  # 从0到1之间均匀分布的5个点
print("等间隔数值点:", linspace)

7️⃣创建随机数组

使用NumPy的随机模块创建随机值数组。随机数在模拟、统计和机器学习中广泛应用。

python 复制代码
import numpy as np
# 创建随机数组
random_array = np.random.random((2, 2))  # 2×2的随机数组(值在0到1之间)
print("随机数组:\n", random_array)

8️⃣创建单位矩阵

这个代码块展示了如何使用np.eye()函数创建单位矩阵 。单位矩阵在线性代数运算中具有特殊地位,主对角线为1,其余为0

python 复制代码
import numpy as np
# 创建单位矩阵
identity = np.eye(3)  # 3×3的单位矩阵
print("单位矩阵:\n", identity)

2. 数组属性

NumPy数组有一些重要的属性,可以帮助我们了解数组的特性

创建一个 3x4二维数组

python 复制代码
import numpy as np

# 创建一个3x4的二维数组
arr = np.array([[1, 2, 3, 4], 
                [5, 6, 7, 8], 
                [9, 10, 11, 12]])

# shape:返回数组的形状(每个维度的大小)
print("数组形状:", arr.shape)  # 输出:(3, 4)

# ndim:返回数组的维度数量
print("维度数量:", arr.ndim)  # 输出:2

# size:返回数组元素的总数
print("元素总数:", arr.size)  # 输出:12

# dtype:返回数组元素的数据类型
print("数据类型:", arr.dtype)  # 输出:int64(可能因系统而异)

# itemsize:返回数组中每个元素的字节大小
print("元素字节大小:", arr.itemsize)  # 输出:8(对于64位整数)

# 创建指定数据类型的数组
float_arr = np.array([1, 2, 3, 4], dtype=np.float32)
print("浮点数组:", float_arr)
print("浮点数组数据类型:", float_arr.dtype)  # 输出:float32

输出结果:

python 复制代码
数组形状: (3, 4)
维度数量: 2
元素总数: 12
数据类型: int32
元素字节大小: 4
浮点数组: [1. 2. 3. 4.]
浮点数组数据类型: float32

注意:了解数组的数据类型对于内存优化和性能非常重要,尤其是处理大型数据集时。

3. 数组索引与切片

NumPy数组支持 与Python列表类似的索引和切片操作,但功能更加强大:

python 复制代码
import numpy as np

# 创建一个3x4的二维数组
arr = np.array([[1, 2, 3, 4], 
                [5, 6, 7, 8], 
                [9, 10, 11, 12]])

# 访问单个元素:arr[行, 列]
print("第2行第3列的元素:", arr[1, 2])  # 输出:7

# 访问整行
print("第1行:", arr[0])  # 输出:[1 2 3 4]

# 访问整列(需要使用:表示"所有行")
print("第2列:", arr[:, 1])  # 输出:[ 2  6 10]

# 切片:arr[行起始:行结束, 列起始:列结束]
print("子数组(前2行,中间2列):\n", arr[0:2, 1:3])
# 输出:
# [[2 3]
#  [6 7]]

# 使用负索引(从末尾开始计数)
print("最后一行:", arr[-1])  # 输出:[ 9 10 11 12]
print("倒数第二列:", arr[:, -2])  # 输出:[ 3  7 11]

# 条件索引(布尔索引)
print("大于6的元素:", arr[arr > 6])
# 输出:[ 7  8  9 10 11 12]

# 花式索引(使用索引数组)
print("第1行和第3行:\n", arr[[0, 2]])
# 输出:
# [[ 1  2  3  4]
#  [ 9 10 11 12]]

输出结果:

python 复制代码
第2行第3列的元素: 7
第1行: [1 2 3 4]
第2列: [ 2  6 10]
子数组(前2行,中间2列):
 [[2 3]
 [6 7]]
最后一行: [ 9 10 11 12]
倒数第二列: [ 3  7 11]
大于6的元素: [ 7  8  9 10 11 12]
第1行和第3行:
 [[ 1  2  3  4]
 [ 9 10 11 12]]

三、广播机制

1. 广播的概念与应用

广播 (Broadcasting)是NumPy 的一个强大特性 ,它允许不同形状的数组在算术运算时自动扩展,使数组间的运算更加灵活高效。

遵循以下规则:

  1. 如果两个数组的维度数不同,形状较小的数组会在左侧补1
  2. 如果两个数组在某个维度上的大小不匹配,但其中一个的大小为1,则该维度会被"广播"以匹配另一个数组

让我们看一些广播的例子

1️⃣不同形状数组之间的运算

python 复制代码
import numpy as np

# 创建数组
a = np.array([1, 2, 3])  # 一维数组:(3,)
b = 5                    # 标量

# 数组与标量运算 - 广播机制自动将标量扩展为数组
print("数组+标量:", a + b)  # 输出:[6 7 8]
print("数组*标量:", a * b)  # 输出:[5 10 15]

# 不同形状数组之间的运算
a = np.array([[1, 2, 3],
              [4, 5, 6]])  # 形状为(2, 3)

b = np.array([10, 20, 30])  # 形状为(3,)

# b会被广播成形状(2, 3)的数组,然后进行元素级加法
print("不同形状数组相加:\n", a + b)
# 输出:
# [[11 22 33]
#  [14 25 36]]

2️⃣更复杂的广播示例

python 复制代码
import numpy as np

# 创建数组
a = np.array([1, 2, 3])  # 一维数组:(3,)
b = 5                    # 标量

# 数组与标量运算 - 广播机制自动将标量扩展为数组
print("数组+标量:", a + b)  # 输出:[6 7 8]
print("数组*标量:", a * b)  # 输出:[5 10 15]

# 更复杂的广播示例
a = np.array([[1, 2, 3],
              [4, 5, 6]])        # 形状为(2, 3)
b = np.array([[10], [20]])       # 形状为(2, 1)

# b会被广播成形状(2, 3)的数组,每行重复列的值
print("列向量广播:\n", a + b)
# 输出:
# [[11 12 13]
#  [24 25 26]]

2. 向量化计算的优势

向量化 是指使用向量 (数组)操作替代循环 的编程风格,它是NumPy高性能的关键

向量化的主要优势

  • 代码简洁:向量化操作大大减少了代码量
  • 执行速度快:NumPy的向量化操作底层是用C实现的,远比Python循环快
  • 内存效率高:向量化操作通常更加内存高效

下面是循环和向量化的性能对比

python 复制代码
import numpy as np
import time

# 创建两个大数组
size = 10000000
a = np.random.random(size)
b = np.random.random(size)

# 使用Python循环计算
start_time = time.time()
result_loop = np.zeros(size)
for i in range(size):
    result_loop[i] = a[i] + b[i]
loop_time = time.time() - start_time
print(f"循环耗时: {loop_time:.6f}秒")

# 使用NumPy向量化计算
start_time = time.time()
result_vectorized = a + b
vectorized_time = time.time() - start_time
print(f"向量化耗时: {vectorized_time:.6f}秒")

# 计算加速比
print(f"向量化操作比循环快 {loop_time/vectorized_time:.1f} 倍")

# 验证两种方法的结果是否相同
print("结果是否相同:", np.allclose(result_loop, result_vectorized))

输出结果:

python 复制代码
循环耗时: 1.961162秒
向量化耗时: 0.028977秒
向量化操作比循环快 67.7 倍
结果是否相同: True

最佳实践 :尽可能使用NumPy的向量化操作避免 使用Python循环处理NumPy数组

四、练习:实现矩阵加法和乘法

下面我们将使用NumPy实现矩阵的加法和乘法操作。

1. 矩阵加法

矩阵加法是元素级操作,要求两个矩阵形状相同。

python 复制代码
import numpy as np

# 创建两个2x3矩阵
A = np.array([[1, 2, 3],
              [4, 5, 6]])

B = np.array([[7, 8, 9],
              [10, 11, 12]])

# 矩阵加法
C = A + B
print("矩阵加法结果:\n", C)

# 另一种实现方式
D = np.add(A, B)
print("使用np.add()的结果:\n", D)

# 验证两种方法结果相同
print("两种方法结果是否相同:", np.array_equal(C, D))

输出结果:

python 复制代码
矩阵加法结果:
 [[ 8 10 12]
 [14 16 18]]
使用np.add()的结果:
 [[ 8 10 12]
 [14 16 18]]
两种方法结果是否相同: True

2. 矩阵乘法

NumPy提供了多种实现矩阵乘法的方式:

python 复制代码
import numpy as np

# 创建矩阵
A = np.array([[1, 2],
              [3, 4],
              [5, 6]])  # 3x2矩阵

B = np.array([[7, 8, 9],
              [10, 11, 12]])  # 2x3矩阵

# 矩阵乘法(点积)
C = np.dot(A, B)
print("矩阵乘法结果 (np.dot):\n", C)

# 使用@运算符(Python 3.5+)
D = A @ B
print("矩阵乘法结果 (@运算符):\n", D)

# 使用matmul函数
E = np.matmul(A, B)
print("矩阵乘法结果 (np.matmul):\n", E)

# 元素级乘法(不是矩阵乘法!)
# 需要形状相同的矩阵
F = np.array([[1, 2], [3, 4]])
G = np.array([[5, 6], [7, 8]])
H = F * G  # 或 np.multiply(F, G)
print("元素级乘法结果:\n", H)

输出结果:

python 复制代码
矩阵加法结果:
 [[ 8 10 12]
 [14 16 18]]
使用np.add()的结果:
 [[ 8 10 12]
 [14 16 18]]
两种方法结果是否相同: True

注意 :不要混淆矩阵乘法(np.dot@np.matmul)和元素级乘法(*np.multiply)!它们的计算方式和结果完全不同。

五、总结与进阶方向

今天我们学习了NumPy的基础知识,包括数组创建、属性、索引、切片、广播机制和向量化计算 。NumPy是Python数据分析的基石,掌握好这些基础对后续学习Pandas、Matplotlib等高级库至关重要。

下一步学习方向

python 复制代码
- NumPy的高级函数(统计函数、线性代数函数等)
- 结构化数组和记录数组
- 文件I/O操作
- 与Pandas的结合使用

练习建议

python 复制代码
1. 尝试使用NumPy解决一些实际问题,如图像处理、数据分析等
2. 探索NumPy的其他创建数组的方法和函数
3. 实践不同形状数组之间的广播操作
4. 比较循环和向量化操作的性能差异

编程提示 :多使用np.info()help()函数查看NumPy函数的详细说明,例如np.info(np.dot)会显示dot函数的详细文档。

参考资源

希望今天的学习让你对NumPy有了初步的了解。在接下来的日子里,我们将继续深入数据分析与可视化的世界! 有什么关于NumPy的问题,欢迎在评论区留言交流!

下一篇预告 :在第23天的星球之旅中,我们将探索 Pandas 基础

创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊)

如果你对今天的内容有任何问题,或者想分享你的学习心得,欢迎在评论区留言讨论!

相关推荐
深蓝电商API8 小时前
不止是 Python:聊聊 Node.js/Puppeteer 在爬虫领域的应用
爬虫·python·node.js
Autumn72998 小时前
【材料学python入门】conda、 jupyter、cpu、GPAW、wsl、ubuntu
python·jupyter·conda
K2I-9 小时前
UCI中Steel Plates Faults不平衡数据集处理
python
蓑笠翁0019 小时前
Django REST Framework 全面指南:从模型到完整API接口开发
后端·python·django
感谢地心引力9 小时前
【Python】基于 PyQt6 和 Conda 的 PyInstaller 打包工具
数据库·python·conda·pyqt·pyinstaller
xiaohanbao0911 小时前
Transformer架构与NLP词表示演进
python·深度学习·神经网络
love530love11 小时前
【笔记】 Podman Desktop 中部署 Stable Diffusion WebUI (GPU 支持)
人工智能·windows·笔记·python·容器·stable diffusion·podman
程序员晚枫12 小时前
Python 3.14正式发布!这5大新特性太炸裂了
python
先做个垃圾出来………12 小时前
SortedList
python
这里有鱼汤12 小时前
从DeepSeek到Kronos,3个原因告诉你:Kronos如何颠覆传统量化预测
后端·python·aigc