课程引入

本节课我们将深入学习NumPy,它是Python数据科学生态的基石。🧱

注记

NumPy为我们提供了强大的多维数组对象和快速的数值计算能力,是数据分析和机器学习的必备工具!💪

目录

  • NumPy介绍 🧐
    • 什么是NumPy?
    • 为什么使用NumPy?
    • NumPy的应用场景
  • NumPy的数组对象-ndarray 📦
    • 什么是ndarray?
    • ndarray的重要属性
    • 创建ndarray
    • ndarray的数据类型
  • ndarray的索引、切片和迭代 🔍
    • 索引(Indexing)
    • 切片(Slicing)
    • 布尔索引(Boolean Indexing)
    • 花式索引(Fancy Indexing)
    • 迭代(Iteration)
  • ndarray的基础操作 ⚙️
    • 算术运算
    • 广播(Broadcasting)
    • 通用函数(Universal Functions, ufuncs)
    • 聚合函数(Aggregation Functions)

NumPy介绍

什么是NumPy?

  • NumPy(Numerical Python的缩写)是一个开源的Python库。🐍
  • 几乎所有Python的数据科学和机器学习库(如Pandas, SciPy, scikit-learn等)都依赖于NumPy。🧩
    • Pandas: 提供高性能、易于使用的数据结构和数据分析工具。
    • SciPy: 基于NumPy,提供许多科学计算中常用的算法,例如数值积分、插值、优化、线性代数等。
    • scikit-learn: 流行的机器学习库,建立在NumPy, SciPy, and matplotlib之上,提供了许多用于机器学习的工具,包括分类、回归、聚类、降维、模型选择和预处理等。
  • NumPy的核心是ndarray(n-dimensional array,多维数组)对象,它提供:
    • 快速的向量化运算(比Python内置列表快得多!⚡)。
    • 高效的内存利用。💾
    • 大量的数学函数库。➕➖✖️➗
    • 线性代数、傅里叶变换、随机数生成等高级功能。🧮
    • 向量化运算: 意味着运算可以直接应用于整个数组,而无需编写循环。

NumPy介绍

为什么要用NumPy, 不用Python自带的列表(list)? 🤔

提示

  1. 速度:NumPy底层使用C语言编写,执行速度快。🚄
    • NumPy数组上的操作通常比Python列表快得多,尤其是在进行数学和科学计算时。
  2. 内存:NumPy数组在内存中是连续存储的,Python列表中的元素是指针,分散在内存各处,访问效率低。💾 vs 🗂️
    • NumPy数组是连续的内存块,存储相同类型的元素。
    • Python列表可以包含不同类型的对象,这导致额外的内存开销和类型检查。
  3. 向量化操作:NumPy支持对整个数组进行操作,而无需编写循环。➿
    • 这种方式更简洁、更易读,也更高效。
  4. 广播机制:NumPy可以对形状不同的数组进行运算。📡
    • 广播是NumPy中一种强大的机制,可以自动处理不同形状数组之间的运算。

NumPy介绍

让我们通过一个例子来直观感受一下NumPy的速度优势:

import numpy as np
import time

# Python列表
size = 1000000
list1 = list(range(size))
list2 = list(range(size))

start = time.time()
result_list = [(x + y) for x, y in zip(list1, list2)]
end = time.time()
print(f"Python列表耗时: {(end - start) * 1000:.2f} 毫秒")

# Numpy数组
array1 = np.arange(size)
array2 = np.arange(size)

start = time.time()
result_array = array1 + array2
end = time.time()
print(f"NumPy数组耗时: {(end - start) * 1000:.2f} 毫秒")

NumPy介绍

你会发现,对于大规模数据的运算,NumPy比Python列表快得多!🚀

提示

通常情况下,数据量越大,NumPy的优势越明显。

NumPy介绍

NumPy的应用场景

  • 数据分析:清洗、转换、统计分析。📊
    • 使用NumPy可以方便地对数据进行各种操作,如筛选、排序、去重、聚合等。
  • 机器学习:特征工程、模型输入。🤖
    • NumPy数组是许多机器学习算法的期望输入格式。
  • 科学计算:物理模拟、工程计算。🔬
    • NumPy提供了许多用于科学计算的函数和工具。
  • 图像处理:图像表示、滤波、变换。🖼️
    • 图像可以表示为NumPy数组,从而进行各种处理。
  • 信号处理:滤波、频谱分析。📡
    • NumPy的傅里叶变换等函数可用于信号处理。

NumPy介绍

注记

可以说,NumPy是现代Python数据科学生态的核心。掌握NumPy,是进行高效数据处理和科学计算的关键!🔑

NumPy的数组对象-ndarray

什么是ndarray?

  • ndarray是NumPy中的核心数据结构,表示一个多维数组。📦
  • 数组中的所有元素必须是相同类型(例如,都是整数,或都是浮点数)。🔢
  • 数组的维度(dimension)称为轴(axis),轴的数量称为秩(rank)。📏

NumPy的数组对象-ndarray

ndarray示意图

提示

上图展示了一个二维数组,它有2个轴(axis),形状(shape)为(3, 4),即3行4列。

NumPy的数组对象-ndarray

ndarray的重要属性 📝

属性 说明
shape 返回一个元组(tuple),表示ndarray各个维度的长度。元组的长度就是数组的维度(轴的个数,也称作秩rank)。元组中每个元素的值表示对应维度的大小。
ndim ndarray对象的维度(轴的个数,即秩)。
size ndarray中元素的总个数。
dtype ndarray中存储的元素的数据类型(如int32, float64等)。
itemsize ndarray中每个元素占用的字节数。
nbytes 整个ndarray数组占用的总字节数

NumPy的数组对象-ndarray

注记

通过这些属性,我们可以快速了解数组的结构、大小和数据类型。

让我们看一个例子:

import numpy as np

arr = np.array([[1, 2, 3], [4, 5, 6]])

print(f"形状 (shape): {arr.shape}")
print(f"维度 (ndim): {arr.ndim}")
print(f"元素个数 (size): {arr.size}")

NumPy的数组对象-ndarray

import numpy as np

arr = np.array([[1, 2, 3], [4, 5, 6]])
print(f"数据类型 (dtype): {arr.dtype}")
print(f"元素字节数 (itemsize): {arr.itemsize}")
print(f"数组总字节数 (nbytes): {arr.nbytes}")

NumPy的数组对象-ndarray

创建ndarray 🛠️

我们可以使用多种方法创建ndarray:

函数 说明
array 将输入的序列类型数据(如列表、元组、其他ndarray等)转换为ndarray。如果未指定dtype,会自动推断。
asarray 类似于array,但如果输入已经是ndarray,则不会创建副本,而是直接引用。
arange 类似于Python内置的range,但返回的是ndarray而不是列表。可以指定起始值、终止值(不包含)和步长。
ones 创建指定形状的全1数组。
ones_like 以另一个ndarray的形状为模板,创建全1数组。
zeros 创建指定形状的全0数组。
zeros_like 以另一个ndarray的形状为模板,创建全0数组。
empty 创建指定形状的未初始化数组(值不确定,可能是内存中的残留数据)。
empty_like 以另一个ndarray的形状为模板,创建未初始化数组。
eye, identity 创建N×N单位矩阵(对角线元素为1,其余为0)。
full 创建指定形状,并用指定值填充的数组
full_like 以另一个ndarray的形状为模板,创建指定填充值的数组
random NumPy的子模块,用于生成各种随机数组,包括:random.rand, random.randn, random.randint, random.uniform等等

NumPy的数组对象-ndarray

import numpy as np

# 从列表创建
arr1 = np.array([1, 2, 3, 4])
print(f"arr1: \n{arr1}")

# 从元组创建
arr2 = np.array((5, 6, 7, 8))
print(f"arr2: \n{arr2}")

# 指定数据类型
arr3 = np.array([1, 2, 3], dtype=np.float64)
print(f"arr3: \n{arr3}")

NumPy的数组对象-ndarray

import numpy as np
# 使用arange
arr4 = np.arange(0, 10, 2)  # 从0开始,到10结束(不包含),步长为2
print(f"arr4: \n{arr4}")

# 创建全1数组
arr5 = np.ones((2, 3))  # 2行3列
print(f"arr5: \n{arr5}")

# 创建全0数组
arr6 = np.zeros((3, 2), dtype=np.int32)  # 3行2列,整数类型
print(f"arr6: \n{arr6}")

NumPy的数组对象-ndarray

import numpy as np
# 创建单位矩阵
arr7 = np.eye(3)  # 3x3单位矩阵
print(f"arr7: \n{arr7}")

# 创建指定填充值的数组
arr8 = np.full((2,3), 3.14)
print(f"arr8: \n{arr8}")

NumPy的数组对象-ndarray

import numpy as np
# 创建随机数组
arr9 = np.random.rand(2,3) # 从0到1的均匀分布随机数
print(f"arr9: \n{arr9}")

arr10 = np.random.randn(3,2) # 标准正态分布随机数
print(f"arr10: \n{arr10}")

NumPy的数组对象-ndarray

import numpy as np
# 创建随机数组
arr11 = np.random.randint(1, 10, (2,2)) # 最小值和最大值之间的随机整数
print(f"arr11: \n{arr11}")

arr12 = np.random.uniform(1, 10, (2,4)) # 从最小值和最大值之间的均匀分布
print(f"arr12: \n{arr12}")

NumPy的数组对象-ndarray

重要

np.array会试图为创建的数组推断出一个合适的数据类型。

# 整数列表
arr1 = np.array([1, 2, 3])
print(f"arr1 dtype: {arr1.dtype}")

NumPy的数组对象-ndarray

# 浮点数列表
arr2 = np.array([1.0, 2.0, 3.0])
print(f"arr2 dtype: {arr2.dtype}")

# 混合整数和浮点数
arr3 = np.array([1, 2.0, 3])
print(f"arr3 dtype: {arr3.dtype}")

NumPy的数组对象-ndarray

# 包含字符串
arr4 = np.array(['a', 'b', 'c'])
print(f"arr4 dtype: {arr4.dtype}")

NumPy的数组对象-ndarray

ndarray的数据类型 📊

数据类型 类型代码 说明
int8, uint8 i1, u1 有符号和无符号8位(1字节)整型
int16, uint16 i2, u2 有符号和无符号16位(2字节)整型
int32, uint32 i4, u4 有符号和无符号32位(4字节)整型
int64, uint64 i8, u8 有符号和无符号64位(8字节)整型
float16 f2 半精度浮点数(16位,2字节)
float32 f4f 单精度浮点数(32位,4字节),与C语言的float兼容
float64 f8d 双精度浮点数(64位,8字节),与C语言的double和Python的float对象兼容
float128 f16g 扩展精度浮点数(128位,16字节)
complex64 c8 复数,由两个32位浮点数表示
complex128 c16 复数,由两个64位浮点数表示
complex256 c32 复数,由两个128位浮点数表示
bool ? 布尔类型,存储TrueFalse
object O Python对象类型
string_ S 固定长度字符串类型(每个字符1字节)。例如,S10表示长度为10的字符串。
unicode_ U 固定长度Unicode类型(字节数取决于平台)。例如,U10表示长度为10的Unicode字符串。

NumPy的数组对象-ndarray

提示

我们可以使用dtype属性查看或指定数组的数据类型。在创建数组时,可以使用dtype参数指定数据类型。

arr = np.array([1, 2, 3], dtype=np.float64)
print(arr.dtype)

NumPy的数组对象-ndarray

注记

还可以使用astype方法显式地转换数组的数据类型。

arr = np.array([1, 2, 3])
print(f"Original dtype: {arr.dtype}")

float_arr = arr.astype(np.float64)
print(f"Converted to float64: {float_arr.dtype}")

NumPy的数组对象-ndarray

arr = np.array([1, 2, 3])

string_arr = arr.astype(np.string_)
print(f"Converted to string_: {string_arr.dtype}")

NumPy的数组对象-ndarray

重要

astype方法会创建一个新的数组(原始数组的副本),即使新的数据类型与原来的相同。

ndarray的索引、切片和迭代

索引(Indexing)

  • 一维数组:与Python列表类似,使用方括号[]和从0开始的下标。
arr = np.arange(10)
print(arr)
print(arr[0])  # 第一个元素
print(arr[5])  # 第六个元素
print(arr[-1])  # 最后一个元素

ndarray的索引、切片和迭代

索引(Indexing)

  • 多维数组
    • 每个维度都有一个索引,用逗号分隔。
    • 可以使用递归方式访问元素,也可以使用逗号分隔的索引列表。
arr2d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print(arr2d)
print(arr2d[0, 0])  # 第一行第一列
print(arr2d[1, 2])  # 第二行第三列

ndarray的索引、切片和迭代

索引(Indexing)

arr2d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print(arr2d[2, 0])  # 第三行第一列
print(arr2d[2][0])  # 与上一行等价

ndarray的索引、切片和迭代

提示

如果只指定部分维度,返回的将是降维后的子数组。

# 假设有一个3x4x5的三维数组
arr3d = np.arange(60).reshape(3, 4, 5)
print("arr3d:\n", arr3d)

# 获取第一个维度为0的子数组
slice_0 = arr3d[0]
print("arr3d[0]:\n", slice_0)

ndarray的索引、切片和迭代

# 假设有一个3x4x5的三维数组
arr3d = np.arange(60).reshape(3, 4, 5)

# 获取第一个维度为1的子数组
slice_1 = arr3d[1]
print("arr3d[1]:\n", slice_1)

# 获取第一个维度为2的子数组
slice_2 = arr3d[2]
print("arr3d[2]:\n", slice_2)

ndarray的索引、切片和迭代

切片(Slicing)

  • 一维数组的切片与Python列表的切片类似, 都是“左闭右开”区间。
arr = np.arange(10)
print(arr)
print(arr[2:5])  # 下标2到5(不包含5)

ndarray的索引、切片和迭代

切片(Slicing)

arr = np.arange(10)
print(arr[:4])  # 开头到4(不包含4)
print(arr[6:])  # 6到结尾
print(arr[::2])  # 从头到尾,步长为2
print(arr[::-1])  # 倒序

ndarray的索引、切片和迭代

切片(Slicing)

  • 多维数组的切片:
    • 在每个维度上分别进行切片,用逗号分隔。
    • 可以使用:表示整个轴。
arr2d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print(arr2d)
print(arr2d[:2, :2])  # 前两行,前两列

ndarray的索引、切片和迭代

切片(Slicing)

arr2d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print(arr2d[1, :])  # 第二行的所有列
print(arr2d[:, 2])  # 第三列的所有行

ndarray的索引、切片和迭代

重要

与Python列表不同,NumPy数组的切片是原始数组的视图(view)。这意味着对切片的修改会直接影响原始数组!⚠️

arr = np.arange(5)
print("Original array:", arr)
arr_slice = arr[1:4]
print("Slice:", arr_slice)

ndarray的索引、切片和迭代

arr = np.arange(5)
arr_slice = arr[1:4]
arr_slice[0] = 100
print("Modified slice:", arr_slice)
print("Original array after modification:", arr)

ndarray的索引、切片和迭代

提示

如果希望得到副本(copy)而不是视图,可以使用copy()方法。

arr = np.arange(5)
arr_copy = arr[1:4].copy()
arr_copy[0] = 100  # 修改副本不会影响原始数组
print(arr)
print(arr_copy)

ndarray的索引、切片和迭代

布尔索引(Boolean Indexing)

  • 可以使用布尔数组(通常是比较运算的结果)来选择元素。
  • 布尔数组的形状必须与要索引的数组相同。
arr = np.array([1, 2, 3, 4, 5])
bool_index = arr > 2  # 返回一个布尔数组
print(bool_index)
print(arr[bool_index])  # 选择大于2的元素

ndarray的索引、切片和迭代

布尔索引(Boolean Indexing)

arr2d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
bool_index2d = arr2d > 5
print(bool_index2d)
print(arr2d[bool_index2d])  # 选择大于5的元素

ndarray的索引、切片和迭代

注记

布尔索引常用于根据条件筛选数据。

我们还可以在布尔索引中使用逻辑运算符&(和), | (或), ~ (非)来组合多个条件。

arr = np.array([1, 2, 3, 4, 5, 6])

# 选择大于2且小于6的元素
condition1 = arr > 2
condition2 = arr < 6
combined_condition = condition1 & condition2
print(arr[combined_condition])

ndarray的索引、切片和迭代

arr = np.array([1, 2, 3, 4, 5, 6])

# 选择小于2或大于4的元素
condition3 = arr < 2
condition4 = arr > 4
combined_condition2 = condition3 | condition4
print(arr[combined_condition2])

ndarray的索引、切片和迭代

arr = np.array([1, 2, 3, 4, 5, 6])
# 选择不等于3的元素
condition5 = arr != 3
print(arr[condition5])

# 或者使用~运算符
condition6 = ~(arr==3)
print(arr[condition6])

ndarray的索引、切片和迭代

花式索引(Fancy Indexing)

  • 使用整数数组(或列表)作为索引,一次选择多个元素。
  • 与切片不同,花式索引总是返回数据的副本
arr = np.arange(10) * 10
print(arr)
indices = [1, 3, 5]
print(arr[indices])  # 选择下标为1、3、5的元素

ndarray的索引、切片和迭代

花式索引(Fancy Indexing)

arr2d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print(arr2d)
row_indices = [0, 2]
col_indices = [1, 0]
print(arr2d[row_indices, col_indices])  # 选择(0, 1)和(2, 0)位置的元素

ndarray的索引、切片和迭代

提示

花式索引可以用于按任意顺序选择或重排数组的行或列。

arr2d = np.arange(12).reshape(4,3)
print(arr2d)

new_order = [2, 0, 3, 1]
rearranged_arr2d = arr2d[new_order]
print(rearranged_arr2d)

ndarray的索引、切片和迭代

迭代(Iteration)

  • 一维数组:迭代方式与Python列表相同。
arr = np.arange(5)
for x in arr:
    print(x)

ndarray的索引、切片和迭代

迭代(Iteration)

  • 多维数组:迭代是相对于第一个轴(axis 0,即行)进行的。
arr2d = np.array([[1, 2, 3], [4, 5, 6]])
for row in arr2d:
    print(row)

ndarray的索引、切片和迭代

迭代(Iteration)

  • 如果需要遍历每个元素,可以使用flat属性(返回一个迭代器):
arr2d = np.array([[1, 2, 3], [4, 5, 6]])
for element in arr2d.flat:
    print(element)

ndarray的基础操作

算术运算 ➕➖✖️➗

  • NumPy数组支持元素级(element-wise)的算术运算(+, -, *, /, **等)。
  • 运算是在两个数组的对应元素之间进行的。
  • 数组必须具有兼容的形状(或满足广播规则)。
arr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])

print(arr1 + arr2)  # 对应元素相加
print(arr1 * arr2)  # 对应元素相乘
print(arr1 ** 2)  # 每个元素求平方

ndarray的基础操作

广播(Broadcasting)📡

  • 广播是一种强大的机制,允许NumPy在不同形状的数组之间进行算术运算。
  • 广播的规则:
    1. 如果两个数组的维度不同,则维度较小的数组会在其前面补1,直到维度相同。
    2. 如果两个数组在某个维度上的大小相同,或者其中一个数组在该维度上的大小为1,则认为它们在该维度上是兼容的。
    3. 如果两个数组在所有维度上都兼容,则可以进行广播运算。
    4. 在广播运算中,大小为1的维度会被“拉伸”以匹配另一个数组在该维度上的大小。

ndarray的基础操作

提示

理解广播规则对于高效使用NumPy非常重要。

可以参考如下图片来理解数组的广播:

ndarray的基础操作

让我们通过几个例子来理解广播:

# 例子1:数组与标量相加
arr = np.array([1, 2, 3])
scalar = 5
print(arr + scalar)  # 标量被广播到数组的每个元素

ndarray的基础操作

# 例子2:不同形状数组相加
arr1 = np.array([[1, 2, 3], [4, 5, 6]])  # 形状为(2, 3)
arr2 = np.array([10, 20, 30])            # 形状为(3,)
print(arr1 + arr2)
# arr2被广播到arr1的每一行

ndarray的基础操作

# 例子3:更复杂的广播
arr1 = np.array([[0, 0, 0], [1, 1, 1], [2, 2, 2], [3, 3, 3]])  # 形状为(4, 3)
arr2 = np.array([1, 2, 3])                                   # 形状为(3,)
print(arr1 + arr2)
# arr2被广播到arr1的每一行

ndarray的基础操作

# 例子3:更复杂的广播
arr1 = np.array([[0, 0, 0], [1, 1, 1], [2, 2, 2], [3, 3, 3]])  # 形状为(4, 3)
arr3 = np.array([[1,], [2,], [3,], [4,]])                   # 形状为(4, 1)
print(arr1 + arr3)
# arr3被广播到arr1的每一列

ndarray的基础操作

重要

如果两个数组的形状不满足广播规则,会抛出ValueError异常。

ndarray的基础操作

通用函数(Universal Functions, ufuncs)⚙️

  • ufunc是一种对ndarray中的每个元素进行操作的函数。
  • ufunc是向量化操作的基础,可以避免编写显式循环,提高效率。⚡
  • 常见的ufunc:
    • 一元ufunc(接受一个数组):abs, sqrt, exp, log, sin, cos, tan等。
    • 二元ufunc(接受两个数组):add, subtract, multiply, divide, power, maximum, minimum等。

ndarray的基础操作

arr = np.array([1, 4, 9, 16])

print(np.sqrt(arr))  # 对每个元素求平方根
print(np.sin(arr))  # 对每个元素求正弦值

ndarray的基础操作

arr1 = np.array([1, 2, 3])
arr2 = np.array([4, 5, 6])
print(np.maximum(arr1, arr2))  # 逐元素比较,取最大值

ndarray的基础操作

注记

许多ufunc都有一个可选的out参数,允许你指定结果存放的位置。

arr = np.arange(5)
out_arr = np.zeros(5)
np.multiply(arr, 10, out=out_arr)
print(out_arr)

ndarray的基础操作

聚合函数(Aggregation Functions)📊

  • 聚合函数是对数组进行汇总计算的函数,返回一个标量结果。
  • 常见的聚合函数:sum, mean, min, max, std, var, argmin, argmax等。
  • 可以指定axis参数来沿着某个轴进行聚合。

ndarray的基础操作

arr = np.array([[1, 2, 3], [4, 5, 6]])
print("arr:\n", arr)

print("np.sum(arr):", np.sum(arr))  # 所有元素求和
print("np.mean(arr):",np.mean(arr))  # 所有元素的平均值
print("np.min(arr):", np.min(arr))  # 所有元素的最小值
print("np.max(arr):", np.max(arr))  # 所有元素的最大值

ndarray的基础操作

arr = np.array([[1, 2, 3], [4, 5, 6]])
print("np.std(arr):", np.std(arr)) # 所有元素的标准差
print("np.var(arr):", np.var(arr))  # 所有元素的方差
print("np.argmin(arr):", np.argmin(arr))  # 最小元素的索引
print("np.argmax(arr):", np.argmax(arr))  # 最大元素的索引

ndarray的基础操作

arr = np.array([[1, 2, 3], [4, 5, 6]])

# 沿着axis 0(行)求和
print("np.sum(arr, axis=0):", np.sum(arr, axis=0))  
print("np.sum(arr, axis=1):", np.sum(arr, axis=1))  # 沿着axis 1(列)求和

ndarray的基础操作

重要

当对多维数组进行聚合时,如果不指定axis参数,会沿着所有轴进行聚合,得到一个标量值。如果指定了axis参数,会沿着指定的轴进行聚合,得到一个降维的数组。

总结 📝

  • NumPy是Python数据科学的核心库,提供了高性能的多维数组对象ndarray

  • ndarray具有多个重要属性,如shapendimsizedtype等。

  • 可以使用多种方法创建ndarray,如arrayarangeoneszeros等。🛠️

  • NumPy支持多种数据类型,如整数、浮点数、复数、布尔值等。📊

  • ndarray支持索引、切片、布尔索引、花式索引等多种数据访问方式。🔍

  • NumPy的广播机制允许在不同形状的数组之间进行算术运算。📡

  • 通用函数(ufunc)提供了元素级的快速运算。⚙️

  • 聚合函数可以对数组进行汇总计算。📊

思考与讨论 🤔

  1. 你能总结一下NumPy数组(ndarray)与Python列表(list)的主要区别吗?

    提示

    • NumPy数组是同质的(所有元素类型相同),Python列表可以是异质的。
    • NumPy数组在内存中连续存储,Python列表元素分散存储。
    • NumPy数组支持向量化运算和广播,Python列表需要循环。
    • NumPy数组通常比Python列表更快、更省内存。
  2. 你能举例说明NumPy的广播机制是如何工作的吗?

    提示

    例如,一个形状为(3, 3)的数组与一个形状为(3,)的数组相加,(3,)的数组会被广播到(3, 3)的每一行。

  3. 你能说出至少5种常见的NumPy通用函数(ufunc)吗?

    提示

    np.sqrt, np.sin, np.cos, np.exp, np.log, np.add, np.multiply, np.maximum等。

  4. 如何根据某个条件筛选NumPy数组中的元素?

    提示

    使用布尔索引。例如,arr[arr > 5]会选择arr中所有大于5的元素。

  5. 你觉得学习NumPy对你未来的数据分析或机器学习工作有何帮助?

    提示

    NumPy是数据分析和机器学习的基础工具,掌握NumPy可以提高数据处理的效率,为后续的学习打下基础。