盘一盘 Python 系列 2 - NumPy (上)(三 )

简介: 盘一盘 Python 系列 2 - NumPy (上)(三 )

本文首发于“生信补给站”公众号 https://mp.weixin.qq.com/s/HI92_O9uUiFgo_Gl_H6EXw

3数组的获取


获取数组是通过索引 (indexing) 和切片 (slicing) 来完成的,


  • 切片是获取一段特定位置的元素
  • 索引是获取一个特定位置的元素


索引和切片的方式和列表一模一样,参考 Python 入门篇 (上)的 2.3 节。对于一维数组 arr,


  • 切片写法是 arr[start : stop : step]
  • 索引写法是 arr[index]


因此,切片的操作是可以用索引操作来实现的 (一个一个总能凑成一段),只是没必要罢了。为了简化,我们在本章三节标题里把切片和索引都叫做索引。


索引数组有三种形式,正规索引 (normal indexing)、布尔索引 (boolean indexing) 和花式索引 (fancy indexing)。


3.1 正规索引



虽然切片操作可以由多次索引操作替代,但两者最大的区别在于


  • 切片得到的是原数组的一个视图 (view) ,修改切片中的内容改变原数组
  • 索引得到的是原数组的一个复制 (copy),修改索引中的内容改变原数组


请看下面一维数组的例子来说明上述两者的不同。


一维数组



arr = np.arange(10)arr
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])


arr[6]索引第 7 个元素 (记住 Python 是从 0 开始记录位置的)


arr[6]
6


把它赋给变量 a,并重新给 a 赋值 1000,但是元数组 arr 第 7 个元素的值还是 6,并没有改成 1000。




a = arr[6]a = 1000arr
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])


arr[5:8]切片第 6 到 8 元素 (记住 Python 切片包头不包尾)


arr[5:8]
array([5, 6, 7])


把它赋给变量 b,并重新给 b 的第二个元素赋值 12,再看发现元数组 arr 第 7 个元素的值已经变成 12 了。




b = arr[5:8]b[1] = 12arr
array([ 0, 1, 2, 3, 4, 5, 12, 7, 8, 9])



这就证实了切片得到原数组的视图 (view),更改切片数据会更改原数组,而索引得到原数组的复制 (copy), 更改索引数据不会更改原数组。希望用下面一张图可以明晰 view 和 copy 的关系。



了解完一维数组的切片和索引,类比到二维和多维数组上非常简单。



二维数组



arr2d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])arr2d
array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]])


索引

情况一:arr2d[2] 来索引第三行,更严格的说法是索引「轴 0」上的第三个元素。


arr2d[2]
array([7, 8, 9])


情况二:arr2d[0][2] 来索引第一行第三列


arr2d[0][2]
3


索引二维数组打了两个中括号好麻烦,索引五维数组不是要打了五个中括号?还有一个简易方法,用 arr2d[0, 2] 也可以索引第一行第三列


arr2d[0,2]
3


切片

情况一:arr2d[:2] 切片前两行,更严格的说法是索引「轴 0」上的前两个元素。


arr2d[:2]
array([[1, 2, 3],
       [4, 5, 6]])


情况二:arr2d[:, [0,2]] 切片第一列和第三列


arr2d[:,[0,2]]
array([[1, 3],
       [4, 6],
       [7, 9]])


情况三:arr2d[1, :2] 切片第二行的前两个元素


arr2d[1, :2]
array([4, 5])


情况四:arr2d[:2, 2] 切片第三列的前两个元素


arr2d[:2, 2]
array([3, 6])



3.2 布尔索引



布尔索引,就是用一个由布尔 (boolean) 类型值组成的数组来选择元素的方法。


假设我们有阿里巴巴 (BABA),脸书 (FB) 和京东 (JD) 的


  • 股票代码 code 数组
  • 股票价格 price 数组:每行记录一天开盘最高收盘价格。







code = np.array(['BABA', 'FB', 'JD', 'BABA', 'JD', 'FB'])price = np.array([[170,177,169],[150,159,153],                  [24,27,26],[165,170,167],                  [22,23,20],[155,116,157]])price
array([[170, 177, 169],
       [150, 159, 153],
       [ 24, 27, 26],
       [165, 170, 167],
       [ 22, 23, 20],
       [155, 161, 157]])


假设我们想找出 BABA 对应的股价,首先找到 code 里面是 'BABA' 对应的索引 (布尔索引),即一个值为 True 和 False 的布尔数组。


code == 'BABA'
array([ True, False, False, True, False, False])


用该索引可以获取 BABA 的股价:


price[ code == 'BABA' ]
array([[170, 177, 169],
       [165, 170, 167]])


用该索引还可以获取 BABA 的最高和收盘价格:


price[ code == 'BABA', 1: ]
array([[177, 169],
       [170, 167]])


再试试获取 JD 和 FB 的股价:


price[ (code == 'FB')|(code == 'JD') ]
array([[150, 159, 153],
       [ 24, 27, 26],
       [ 22, 23, 20],
       [155, 161, 157]])


虽然下面操作没有实际意义,试试把股价小于 25 的清零。



price[ price < 25 ] = 0price
array([[170, 177, 169],
       [150, 159, 153],
       [ 0, 27, 26],
       [165, 170, 167],
       [ 0, 0, 0],
       [155, 161, 157]])


注:这种布尔索引的操作在 Pandas 更常用也更方便,看完 pandas 那帖后就可以忽略这一节了。



3.3 花式索引



花式索引是获取数组中想要的特定元素的有效方法。考虑下面数组:



arr = np.arange(32).reshape(8,4)arr
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]])


假设你想按特定顺序来获取第 5, 4 和 7 行时,用 arr[ [4,3,6] ]


arr[ [4,3,6] ]
array([[16, 17, 18, 19],
       [12, 13, 14, 15],
       [24, 25, 26, 27]])


假设你想按特定顺序来获取倒数第 4, 3 和 6 行时 (即正数第 4, 5 和 2 行),用 arr[ [-4,-3,-6] ]


arr[ [-4,-3,-6] ]
array([[16, 17, 18, 19],
       [20, 21, 22, 23],
       [ 8, 9, 10, 11]])


此外,你还能更灵活的设定「行」和「列」中不同的索引,如下


arr[ [1,5,7,2], [0,3,1,2] ]
array([ 4, 23, 29, 10])


检查一下,上行代码获取的分别是第二行第一列、第六行第四列、第八行第二列、第三行第三列的元素,它们确实是 4, 23, 29 和 10。如果不用花式索引,就要写下面繁琐但等价的代码:



np.array( [ arr[1,0], arr[5,3],             arr[7,1], arr[2,2] ] )
array([ 4, 23, 29, 10])


最后,我们可以把交换列,把原先的 [0,1,2,3] 的列换成 [0,3,1,2]。


arr[:,[0,3,1,2]]
array([[ 0, 3, 1, 2],
       [ 4, 7, 5, 6],
       [ 8, 11, 9, 10],
       [12, 15, 13, 14],
       [16, 19, 17, 18],
       [20, 23, 21, 22],
       [24, 27, 25, 26],
       [28, 31, 29, 30]])





4总结



本帖讨论了 NumPy 的前三节,数组创建、数组存载和数组获取。同样把 numpy 数组当成一个对象,要学习它,无非就是学习怎么


  • 创建它:按步就班法、定定点法、一步登天法
  • 存载它:保存成 .npy, .txt 和 .csv 格式,下次加载即用
  • 获取它:一段用切片,一个用索引;有正规法、布尔法、花式法


等等,你好像还没教什么 numpy 数组硬核的东西呢,下帖讨论 NumPy 的后两节就教怎么


  • 变形它:重塑和打平,合并和分裂,元素重复和数组重复
  • 计算它:元素层面计算,线性代数计算,广播机制计算




回到引言的「数组转置」问题:



arr = np.arange(16).reshape((2, 2, 4))arr
array([[[ 0, 1, 2, 3],
        [ 4, 5, 6, 7]],
       [[ 8, 9, 10, 11],
        [12, 13, 14, 15]]])


第 1, 2, 3 维度转置到第 2, 1, 3 维度,即将轴 0, 1, 2 转置到轴 1, 0, 2


解答:

数组转置的本质:交换每个轴 (axis) 的形状 (shape) 和跨度 (stride)。


四幅图解决问题:



原数组




内存块的样子




轴 0 和轴 1 互换





转置结果



用代码验证一下:


arr.transpose(1,0,2)
array([[[ 0, 1, 2, 3],
        [ 8, 9, 10, 11]],
       [[ 4, 5, 6, 7],
        [12, 13, 14, 15]]])


欧了!下篇讨论 NumPy 系列的「数组的变性」和「数组的计算」。Stay Tuned!

相关文章
|
27天前
|
程序员 开发工具 索引
图解Python numpy基本操作
图解Python numpy基本操作
|
1天前
|
存储 API C语言
Python学习笔记之NumPy模块——超详细(安装、数组创建、正态分布、索引和切片、数组的复制、维度修改、拼接、分割...)-2
Python学习笔记之NumPy模块——超详细(安装、数组创建、正态分布、索引和切片、数组的复制、维度修改、拼接、分割...)
|
1天前
|
BI 测试技术 索引
Python学习笔记之NumPy模块——超详细(安装、数组创建、正态分布、索引和切片、数组的复制、维度修改、拼接、分割...)-1
Python学习笔记之NumPy模块——超详细(安装、数组创建、正态分布、索引和切片、数组的复制、维度修改、拼接、分割...)
|
11天前
|
数据挖掘 数据处理 C语言
18. Python 数据处理之 Numpy
18. Python 数据处理之 Numpy
11 2
|
18天前
|
存储 并行计算 数据挖掘
Python中的NumPy库:科学计算与数据分析的基石
Python中的NumPy库:科学计算与数据分析的基石
68 0
|
20天前
|
存储 索引 Python
python学习——NumPy数值计算基础
NumPy基础知识概览:涉及nan(非数字)和inf(无穷)的概念,nan在文件读取或不适当计算时出现,inf在除0操作中出现。数组操作有深拷贝(a=b.copy())、浅拷贝(a=b[:])和引用(a=b)。创建数组方式多样,如`np.array()`、`np.arange()`等。数据类型转换如`np.float64()`、`np.int8()`。随机数生成包含均匀分布、正态分布等。数组索引和切片支持多维操作。改变数组形状用`reshape()`,展平用`ravel()`和`flatten()`。矩阵运算包括加减乘、转置、逆矩阵等。
34 2
python学习——NumPy数值计算基础
|
24天前
|
Python
python相关库的安装:pandas,numpy,matplotlib,statsmodels
python相关库的安装:pandas,numpy,matplotlib,statsmodels
|
1月前
|
存储 机器学习/深度学习 数据处理
NumPy:从初识到实战,探索Python科学计算的无限可能
NumPy:从初识到实战,探索Python科学计算的无限可能
43 0
|
1月前
|
机器学习/深度学习 存储 算法
Python中的NumPy库:数值计算与科学计算的基石
【2月更文挑战第29天】NumPy是Python科学计算的核心库,专注于高效处理大型多维数组和矩阵。其核心是ndarray对象,提供快速数组操作和数学运算,支持线性代数、随机数生成等功能。NumPy广泛应用于数据处理、科学计算和机器学习,简化了矩阵运算、统计分析和算法实现,是数据科学和AI领域的重要工具。
|
1月前
|
存储 索引 Python
请解释Python中的NumPy库以及它的主要用途。
【2月更文挑战第27天】【2月更文挑战第97篇】请解释Python中的NumPy库以及它的主要用途。