《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😊)

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

相关推荐
小学生搞程序7 分钟前
学习Python的优势体现在哪些方面?
开发语言·python·学习
_玖-幽9 分钟前
Python 数据分析01 环境搭建教程
大数据·python·jupyter
databook13 分钟前
『Plotly实战指南』--面积图绘制与应用
python·数据分析·数据可视化
carpell23 分钟前
【双指针法】:这么常用的你怎么能不知道
python·链表·字符串·数组·双指针法
pound12729 分钟前
第五章.python函数
windows·python·microsoft
仙人掌_lz30 分钟前
企业年报问答RAG挑战赛冠军方案:从零到SotA,一战封神
python·gpt·ai·llm·rag·问答·年报
Code_流苏33 分钟前
《Python星球日记》第27天:Seaborn 可视化
python·数据可视化·python入门·seaborn·统计图表
过期动态1 小时前
【动手学深度学习】LeNet:卷积神经网络的开山之作
人工智能·python·深度学习·神经网络·机器学习·分类·cnn
晴天毕设工作室1 小时前
计算机毕业设计指南
java·开发语言·python·计算机网络·课程设计
明月看潮生1 小时前
青少年编程与数学 02-016 Python数据结构与算法 16课题、贪心算法
python·算法·青少年编程·贪心算法·编程与数学