Python NumPy 索引与切片完全指南

温以宁
温以宁
发布时间:2026-10-16 | 2人浏览过
原创

本文深入解析 Python NumPy 库中的索引机制。从基础切片语法(start:stop:step)到高级整数索引和布尔过滤,详细讲解如何高效提取和处理多维数组数据。通过代码示例对比列表与数组的操作差异,阐明视图与副本的区别,帮助开发者掌握 NumPy 核心数据处理技巧。

NumPy(Numeric Python)是一个用于处理同质 n 维数组的核心计算包。在 NumPy 中,这些数组的维度被称为轴(axes)。

为什么我们需要 NumPy

既然 Python 原生列表已经存在,为何还要引入 NumPy?关键在于操作效率。Python 原生列表无法直接对元素执行批量数学运算,例如两个列表相乘必须逐个元素进行迭代。而 NumPy 数组原生支持向量化操作,能够直接对数组整体执行数学运算,从而大幅提升计算效率并简化代码。

示例 #1:

# 演示需要 NumPy 的 Python 程序
 
list1 = [1, 2, 3, 4 ,5, 6]
list2 = [10, 9, 8, 7, 6, 5]
 
# 将两个列表直接相乘会出错。
print(list1*list2)

输出 :

TypeError: can't multiply sequence by non-int of type 'list'

通过 NumPy 数组,上述乘法操作可以轻松且高效地完成。

示例 #2:

# 演示 NumPy 数组使用的 Python 程序
import numpy as np
 
list1 = [1, 2, 3, 4, 5, 6]
list2 = [10, 9, 8, 7, 6, 5]
 
# 将 list1 转换为 NumPy 数组
a1 = np.array(list1)
 
# 将 list2 转换为 NumPy 数组
a2 = np.array(list2)
 
print(a1*a2)

输出 :

array([10, 18, 24, 28, 30, 30])

Python 的 NumPy 包提供了强大且灵活的索引功能,允许以多种方式访问和修改数组数据。

使用索引数组进行索引

在 NumPy 中,可以使用另一个数组作为索引来提取数据。需要注意的是,使用切片操作返回的是原始数组的视图(浅表副本),而使用索引数组返回的则是原始数组数据的副本。NumPy 数组可以通过其他数组或任何序列(元组除外)进行索引。索引支持负数,其中 -1 代表最后一个元素,-2 代表倒数第二个,依此类推。

示例 #1:

# 演示索引数组使用的 Python 程序。
import numpy as np
 
# 创建一个从 10 到 1 的整数序列,步长为 -2
a = np.arange(10, 1, -2) 
print("\n A sequential array with a negative step: \n",a)
 
# 索引在 np.array 方法中指定。
newarr = a[np.array([3, 1, 2 ])]
print("\n Elements at these indices are:\n",newarr)

输出 :

A sequential array with a negative step: [10 8 6 4 2] Elements at these indices are: [4 8 6]

示例 #2:

import numpy as np
 
# 元素从 1 到 9 的 NumPy 数组
x = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9])
 
# 索引值可以是负数。
arr = x[np.array([1, 3, -3])]
print("\n Elements are : \n",arr)

输出 :

Elements are: [2 4 7]

索引类型

NumPy 主要包含两种索引方式:

基本切片和索引

考虑语法 x[obj],其中 x 是数组,obj 是索引对象。当 obj 为切片对象时,属于基本切片情况。

  • 形式为 start : stop : step 的切片对象
  • 一个整数
  • 或切片对象和整数的元组

由基本切片生成的所有数组始终是原始数组的视图,这意味着修改视图会影响原始数据。

代码#1:

# 用于基本切片的 Python 程序。
import numpy as np
 
# 从 0 到 19 排列元素
a = np.arange(20)
print("\n Array is:\n ",a)
 
# a[start:stop:step]
print("\n a[-8:17:1]  = ",a[-8:17:1]) 
 
# : 运算符表示直到最后的所有元素。
print("\n a[10:]  = ",a[10:])

输出 :

Array is: [ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19] a[-8:17:1] = [12 13 14 15 16] a[10:] = [10 11 12 13 14 15 16 17 18 19]

代码#2:

# 用于基本切片和索引的 Python 程序
import numpy as np
 
# A 3-Dimensional array
a = np.array([[0, 1, 2, 3, 4, 5]
              [6, 7, 8, 9, 10, 11]
              [12, 13, 14, 15, 16, 17]
              [18, 19, 20, 21, 22, 23]
              [24, 25, 26, 27, 28, 29]
              [30, 31, 32, 33, 34, 35]]
print("\n Array is:\n ",a)
 
# 切片和索引
print("\n a[0, 3:5]  = ",a[0, 3:5]) 
 
print("\n a[4:, 4:]  = ",a[4:, 4:]) 
 
print("\n a[:, 2]  = ",a[:, 2]) 
 
print("\n a[2:;2, ::2]  = ",a[2:;2, ::2]) 

输出 :

Array is: [[0 1 2 3 4 5] [6 7 8 9 10 11] [12 13 14 15 16 17] [18 19 20 21 22 23] [24 25 26 27 28 29] [30 31 32 33 34 35]] a[0, 3:5] = [3 4] a[4:, 4:] = [[28 29], [34 35]] a[:, 2] = [2 8 14 20 26 32] a[2:;2, ::2] = [[12 14 16], [24 26 28]]

下图让概念更清晰:

省略号(...)也可以与基本切片结合使用。省略号代表足够的 : 对象,以创建一个长度与数组维度相同的完整选择元组。

# 使用带省略号的基本切片进行索引的 Python 程序
import numpy as np
 
# A 3 dimensional array.
b = np.array([[[1, 2, 3],[4, 5, 6]],
              [[7, 8, 9],[10, 11, 12]]])
 
print(b[...,1]) #Equivalent to b[: ,: ,1 ]

输出 :

[[ 2 5] [ 8 11]]

高级索引

当 obj 为以下类型时,触发高级索引:

  • 整数或布尔类型的 ndarray
  • 或包含至少一个序列对象的元组
  • 是一个非元组序列对象

高级索引返回的是数据的副本,而非视图。高级索引分为整数索引和布尔索引两种类型。

纯整数索引: 当使用整数数组进行索引时,第一维的每个元素会与第二维的元素配对。例如,本例中元素的索引为 (0,0),(1,0),(2,1),并选择相应的元素。

# 显示高级索引的 Python 程序
import numpy as np
 
a = np.array([[1 ,2 ],[3 ,4 ],[5 ,6 ]])
print(a[[0 ,1 ,2 ],[0 ,0 ,1]])

输出 :

[1 3 6]

结合高级索引和基本索引

当索引中至少包含一个切片 (: )、省略号 (...) 或 newaxis(或者数组维度多于高级索引提供的维度)时,行为可能更为复杂。这相当于连接每个高级索引元素的索引结果。

在最简单的情况下,仅有一个高级索引。例如,单个高级索引可以替代切片,结果数组内容相同,但它是副本且内存布局可能不同。如果可能,优先使用切片。

# 显示高级和基本索引的 Python 程序
import numpy as np
 
a = np.array([[0 ,1 ,2],[3 ,4 ,5 ],
              [6 ,7 ,8],[9 ,10 ,11]])
 
print(a[1:2 ,1:3 ])
print(a[1:2 ,[1,2]])

输出 :

[4, 5] [4, 5]

理解这种情况最简单的方法是关注结果形状。索引操作包含两部分:由基本索引(不包括整数)定义的子空间,以及来自高级索引部分的子空间。需要区分两种索引组合的情况:

高级索引由切片、省略号或 newaxis 分隔。例如x[arr1, :, arr2].

高级索引都彼此相邻。例如x[..., arr1, arr2, :],但不是x[arr1, :, 1] 因为 1 在这方面是一个高级索引。

在第一种情况下,高级索引操作产生的维度首先出现在结果数组中,随后是子空间维度。在第二种情况下,来自高级索引操作的维度被插入到结果数组中,位置与它们在初始数组中的位置相同(这种逻辑使得简单的高级索引行为类似于切片)。

布尔数组索引

这种索引方式使用布尔表达式作为索引条件。它返回满足该布尔表达式的元素,常用于过滤特定值。

代码 #1

# 您可能希望选择大于 50 的数字
import numpy as np
 
a = np.array([10, 40, 80, 50, 100])
print(a[a>50])

输出 :

[80 100]

代码 #2

# 您可能希望将 40 的倍数平方
import numpy as np
 
a = np.array([10, 40, 80, 50, 100])
print(a[a%40==0]**2)

输出 :

[1600 6400])

代码 #3

# 您可能希望选择行之和是 10 的倍数的那些元素。
import numpy as np
 
b = np.array([[5, 5],[4, 5],[16, 4]])
sumrow = b.sum(-1)
print(b[sumrow%10==0])

输出 :

array([[ 5, 5], [16, 4]])

到此这篇关于Python NumPy教程之索引详解的文章就介绍到这了,更多相关Python Numpy索引内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表