Numpy索引和切片

一、Python与Numpy切片操作的异同

Python 原生的列表切片操作和 NumPy 数组的切片操作有相似之处,但在功能、性能和应用范围上存在一些关键差异。接下来将详细分析它们的不同点,并分别介绍它们的用法。

1. 基本概念与用法

Python 列表的切片操作:

Python 列表的切片是通过指定起始、结束和步长的方式来获取原列表的一个子列表。它遵循以下格式:

list[start:stop:step]
  • start:切片开始的索引,包含在切片结果中。
  • stop:切片结束的索引,但不包含在切片结果中。
  • step:切片的步长,默认为 1。

示例:

my_list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# 获取索引 2 到 5 的元素
print(my_list[2:6])  # 输出:[2, 3, 4, 5]

# 获取从 0 到结尾,每隔两个元素取一个
print(my_list[::2])  # 输出:[0, 2, 4, 6, 8]

# 反向切片
print(my_list[::-1])  # 输出:[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
NumPy 数组的切片操作:

NumPy 的切片操作类似于 Python 列表,但它可以处理多维数组,并且由于 NumPy 的底层实现,切片通常不会生成新的数组,而是返回原数组的视图。这意味着对切片结果的修改会影响原数组中的数据。

基本格式与 Python 列表相同:

array[start:stop:step]

示例:

import numpy as np

# 创建一个 1D NumPy 数组
arr = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

# 获取索引 2 到 5 的元素
print(arr[2:6])  # 输出:[2 3 4 5]

# 获取从 0 到结尾,每隔两个元素取一个
print(arr[::2])  # 输出:[0 2 4 6 8]

# 反向切片
print(arr[::-1])  # 输出:[9 8 7 6 5 4 3 2 1 0]

2. Python 列表 vs. NumPy 数组切片的不同点

2.1 返回对象
  • Python 列表:切片操作返回的是一个新列表,与原列表没有联系。对切片结果的修改不会影响原列表。
  • NumPy 数组:切片操作返回的是原数组的视图(view),而不是新数组。这意味着对切片结果的修改会影响原数组中的数据。

示例:

# Python 列表
my_list = [0, 1, 2, 3, 4, 5]
slice_list = my_list[2:5]
slice_list[0] = 99
print(my_list)  # 输出:[0, 1, 2, 3, 4, 5](原列表不变)

# NumPy 数组
arr = np.array([0, 1, 2, 3, 4, 5])
slice_arr = arr[2:5]
slice_arr[0] = 99
print(arr)  # 输出:[ 0  1 99  3  4  5](原数组被修改)

原因:NumPy 为了效率,默认通过切片操作返回的是视图而非副本。Python 列表则返回一个新的列表,原始列表不会受影响。

2.2 多维切片支持
  • Python 列表:仅支持一维切片操作,对于多维嵌套列表,必须分别索引每一维度的元素,无法同时切片多个维度。
  • NumPy 数组:可以直接对多维数组进行切片操作,支持在每一个维度上同时进行索引和切片。

示例:

# Python 多维列表的访问
my_list = [[0, 1, 2], [3, 4, 5], [6, 7, 8]]

# Python 列表不能一次性切片多个维度
print(my_list[0:2])  # 输出:[[0, 1, 2], [3, 4, 5]](只能切片第一维)

# NumPy 多维数组的切片
arr = np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]])

# NumPy 支持对多维数组进行切片
print(arr[0:2, 1:3])  # 输出:[[1 2] [4 5]]
2.3 步长
  • Python 列表:切片支持正步长和负步长。
  • NumPy 数组:同样支持正步长和负步长,但 NumPy 提供了更多功能,支持对多维数组的每一维度使用不同的步长。

示例:

# Python 列表正步长和负步长
my_list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(my_list[1:8:2])  # 输出:[1, 3, 5, 7]
print(my_list[8:1:-2])  # 输出:[8, 6, 4, 2]

# NumPy 数组步长
arr = np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]])

# 对不同维度使用不同的步长
print(arr[::2, ::2])  # 输出:[[0 2] [6 8]](两维度上步长都是 2)
2.4 高级索引
  • Python 列表:原生不支持布尔索引或整数数组索引。
  • NumPy 数组:支持布尔索引和整数数组索引,可以非常灵活地提取数据。

示例:

import numpy as np

# 创建一个 NumPy 数组
arr = np.array([10, 20, 30, 40, 50])

# 布尔索引
print(arr[arr > 30])  # 输出:[40 50]

# 整数数组索引
indices = np.array([0, 2, 4])
print(arr[indices])  # 输出:[10 30 50]

3. NumPy 的高级切片功能

3.1 布尔切片

NumPy 支持布尔切片,可以通过布尔条件筛选数组中的元素。

示例:

arr = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
print(arr[arr > 5])  # 输出:[ 6  7  8  9 10]
3.2 整数数组切片

NumPy 支持用整数数组对原数组进行切片,灵活地选择多个元素。

示例:

arr = np.array([10, 20, 30, 40, 50])
index_arr = np.array([1, 3])
print(arr[index_arr])  # 输出:[20 40]
3.3 花式索引

NumPy 支持使用多个整数数组对多维数组进行“花式索引”。

示例:

arr = np.array([[1, 2], [3, 4], [5, 6]])
rows = np.array([0, 1, 2])
cols = np.array([1, 0, 1])
print(arr[rows, cols])  # 输出:[2 3 6]

总结

特性Python 列表NumPy 数组
返回结果返回新列表返回原数组的视图,数据共享
多维切片只支持一维切片支持多维数组的切片操作
步长支持正步长和负步长支持正负步长,且可以对每一维度使用不同步长
高级索引(布尔、整数索引)不支持支持布尔索

在 NumPy 中,整数索引(也称为整型数组索引)是一种强大的功能,允许你通过一个或多个整数数组来访问或修改数组中的特定元素。通过整数索引,你可以根据数组中的位置快速提取所需的数据。

二、整数索引的使用

1. 基本整数索引

NumPy 中最常见的索引方式是使用单个整数或一组整数来访问数组元素。这种方式与 Python 的列表索引类似。

示例:
import numpy as np

# 创建一个 2D 数组
arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])

# 访问某个元素,例如获取第一行第二列的元素
print(arr[0, 1])  # 输出:2

2. 使用整型数组进行索引

你可以使用整型数组对 NumPy 数组的多个元素进行索引。整型数组中的每个元素对应原始数组的索引位置。

示例:
import numpy as np

# 创建一个 1D 数组
arr = np.array([10, 20, 30, 40, 50])

# 使用整型数组进行索引
index = np.array([0, 2, 4])  # 想要访问的索引
print(arr[index])  # 输出:[10 30 50]

3. 多维数组中的整型数组索引

对于多维数组,你可以提供多个整型数组来同时索引不同维度。

示例:
import numpy as np

# 创建一个 2D 数组
arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])

# 使用整型数组进行多维索引
row_indices = np.array([0, 1, 2])
col_indices = np.array([2, 1, 0])

# 提取指定位置的元素
print(arr[row_indices, col_indices])  # 输出:[3 5 7]

在这个例子中,arr[0, 2]arr[1, 1]arr[2, 0] 对应的元素分别是 357

4. 整数索引与切片的组合

你可以将整数索引与切片操作组合使用,以便选择多个维度上的特定元素。

示例:
import numpy as np

# 创建一个 3D 数组
arr = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])

# 使用整型索引和切片的组合
print(arr[1, :, 1])  # 输出:[6 8]

在这个例子中,1 是整型索引,表示选择第二个子数组;: 是切片,表示选取所有行;1 是第二列的元素。

5. 修改数组中的元素

整数索引不仅可以用于提取元素,还可以通过它直接修改数组中的某些元素。

示例:
import numpy as np

# 创建一个 1D 数组
arr = np.array([10, 20, 30, 40, 50])

# 使用整数索引修改元素
arr[[0, 2, 4]] = 99  # 将索引 0, 2, 4 的元素都改为 99
print(arr)  # 输出:[99 20 99 40 99]

6. 布尔索引与整数索引的结合

你也可以将布尔索引与整数索引结合使用,以更灵活地筛选和修改数据。

示例:
import numpy as np

# 创建一个数组
arr = np.array([10, 20, 30, 40, 50])

# 使用布尔索引和整数索引筛选并修改数据
arr[arr > 30] = -1  # 将大于 30 的元素修改为 -1
print(arr)  # 输出:[10 20 30 -1 -1]

总结:

在 NumPy 中,整数索引是一种高效且灵活的操作手段,能够帮助你根据指定的位置访问、提取或修改数组中的数据。通过整型数组索引、多维索引、切片的组合使用,你可以轻松地处理复杂的数据提取任务。

三、索引时逗号’,'的使用

NumPy 中,切片操作中的逗号(,)用来分隔不同维度的索引。当你对多维数组进行切片时,逗号用于区分每个维度的切片规则。

1. 基本概念

对于多维数组,逗号的作用是让你可以同时对不同维度进行索引或切片。

  • 在一维数组中,不需要逗号,因为只有一个维度。
  • 在二维数组中,逗号用于区分行和列的切片。
  • 在三维或更高维数组中,逗号用于区分每个维度。

每个逗号前后的索引或切片分别对应 NumPy 数组的一个维度。

2. 示例说明

2.1 一维数组(无需逗号)

一维数组只需要一个切片,不涉及维度间的区分。

import numpy as np

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

# 获取索引 2 到 4(不包含 4)的元素
print(arr[2:4])  # 输出:[2 3]
2.2 二维数组(行和列的切片)

在二维数组中,逗号分隔的切片。

import numpy as np

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

# 获取第 1 行、第 2 列的元素
print(arr[1, 2])  # 输出:6

# 获取第 0 行到第 1 行(不包括第 2 行),以及所有列
print(arr[0:2, :])  # 输出:
# [[1 2 3]
#  [4 5 6]]

# 获取所有行,第 1 列到第 2 列(不包括第 3 列)
print(arr[:, 1:3])  # 输出:
# [[2 3]
#  [5 6]
#  [8 9]]
2.3 三维数组

在三维数组中,逗号可以用来区分、和。对于一个三维数组,切片 arr[i, j, k] 的含义是:

  • i 表示层(第 0 维)
  • j 表示行(第 1 维)
  • k 表示列(第 2 维)
import numpy as np

# 创建一个 3x3x3 的三维数组
arr_3d = np.arange(27).reshape(3, 3, 3)

# 获取第 0 层的第 1 行第 2 列的元素
print(arr_3d[0, 1, 2])  # 输出:5

# 获取所有层的第 0 行
print(arr_3d[:, 0, :])  # 输出:
# [[ 0  1  2]
#  [ 9 10 11]
#  [18 19 20]]

# 获取第 1 层的所有行和列
print(arr_3d[1, :, :])  # 输出:
# [[ 9 10 11]
#  [12 13 14]
#  [15 16 17]]
2.4 不同维度的切片组合

NumPy 允许对每个维度指定不同的切片范围,并通过逗号分隔。你可以为每个维度提供具体的切片范围、索引或切片步长。

import numpy as np

arr_3d = np.arange(27).reshape(3, 3, 3)

# 获取第 1 层的前 2 行,前 2 列的子数组
print(arr_3d[1, 0:2, 0:2])  # 输出:
# [[ 9 10]
#  [12 13]]

# 获取所有层,步长为 2 的行,步长为 2 的列
print(arr_3d[:, ::2, ::2])  # 输出:
# [[[ 0  2]
#   [ 6  8]]
#  [[ 9 11]
#   [15 17]]
#  [[18 20]
#   [24 26]]]

3. :... 的特殊使用

  • ::表示从该维度的起点到终点的切片(即选择所有元素)。
  • ...:NumPy 的特殊语法,表示 “任意数量的维度”,可用于忽略一部分维度。
示例:
import numpy as np

arr_3d = np.arange(27).reshape(3, 3, 3)

# 使用 `:` 获取第 1 层的所有行和列
print(arr_3d[1, :, :])  # 输出:
# [[ 9 10 11]
#  [12 13 14]
#  [15 16 17]]

# 使用 `...` 获取第 2 列的所有层和行
print(arr_3d[..., 2])  # 输出:
# [[ 2  5  8]
#  [11 14 17]
#  [20 23 26]]

总结:

  • 在 NumPy 中,逗号用来分隔多维数组的不同维度。
  • 每个维度可以单独使用切片表达式,允许同时对多个维度进行操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

想要好名字

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值