Python 数据分析三剑客之 NumPy(二):数组索引 / 切片 / 广播 / 拼接 / 分割


文章目录


NumPy 系列文章:


专栏:


推荐学习资料与网站:


这里是一段物理防爬虫文本,请读者忽略。
本文原创首发于 CSDN,作者 ITBOB。
博客首页:https://itrhx.blog.csdn.net/
本文链接:https://itrhx.blog.csdn.net/article/details/104988137
未经授权,禁止转载!恶意转载,后果自负!尊重原创,远离剽窃!

【1x00】认识 Numpy 中的 nan 和 inf

nan(NAN,Nan):全称 not a number,即不是一个数字
inf(-inf,inf):全称 infinity,inf 表示正无穷,-inf 表示负无穷

以下情况 Numpy 中会出现 nan:

  • 当读取本地的文件为 float 的时候,如果有缺失,就会出现 nan
  • 当做了一个不合适的计算的时候(如:无穷大减去无穷大)

以下情况会出现 inf 或者 -inf:

  • 比如一个数字除以 0,在 Python 中直接会报错,但在 Numpy 中则是一个 inf 或者 -inf

指定一个 nan 或者 inf:

>>> import numpy as np
>>> a = np.nan
>>> b = np.inf
>>> print(a)
nan
>>> print(b)
inf
>>> type(a)
<class 'float'>
>>> type(b)
<class 'float'>

注意两个 nan 并不相等,而两个 inf 是相等的

>>> np.nan == np.nan
False
>>> np.inf == np.inf
True

nan 和任何值计算都为 nan:

>>> import numpy as np
>>> a = np.array([1, 2, 3, 4, 5])
>>> b = np.array([1, 2, np.nan, 4, np.nan])
>>> print(a+b)
[ 2.  4. nan  8. nan]

【1x01】判断是否为 nan 和 inf

  • isnan:判断元素是否为 nan(非数字)
  • isinf:判断元素是否为正无穷大或负无穷大
  • isposinf:判断元素是否为正无穷大
  • isneginf:判断元素是否为负无穷大
  • isfinite:判断元素是否为有限的(不是非数字,正无穷大和负无穷大中的一个)
>>> import numpy as np
>>> a = np.array([[1, 2, 3, 4], [np.nan, 6, 7, np.nan], [9 ,np.nan, 10, 11]])
>>> print(a)
[[ 1.  2.  3.  4.]
 [nan  6.  7. nan]
 [ 9. nan 10. 11.]]
>>> np.isnan(a)
array([[False, False, False, False],
       [ True, False, False,  True],
       [False,  True, False, False]])

【1x02】统计数组中 nan 的个数

1、利用 np.count_nonzero 方法,结合两个 nan 不相等的属性,可以判断数组中 nan 的个数:

>>> import numpy as np
>>> a = np.array([[1, 2, 3, 4], [np.nan, 6, 7, np.nan], [9 ,np.nan, 10, 11]])
>>> print(a)
[[ 1.  2.  3.  4.]
 [nan  6.  7. nan]
 [ 9. nan 10. 11.]]
>>> np.count_nonzero(a != a)    # 判断 nan 的个数,a != a 即为 nan,nan != nan
3

2、isnan() 方法可以判断哪些是 nan,再结合 np.count_nonzero 方法可以判断数组中 nan 的个数:

>>> import numpy as np
>>> a = np.array([[1, 2, 3, 4], [np.nan, 6, 7, np.nan], [9 ,np.nan, 10, 11]])
>>> print(a)
[[ 1.  2.  3.  4.]
 [nan  6.  7. nan]
 [ 9. nan 10. 11.]]
>>> np.isnan(a)                        # np.isnan(a) 与 a != a 效果相同,判断那些是 nan
array([[False, False, False, False],
       [ True, False, False,  True],
       [False,  True, False, False]])
>>> np.count_nonzero(np.isnan(a))
3

3、利用 collections 模块的 Counter 方法来统计 nan 的个数(此方法仅适用于一维数组):

>>> from collections import Counter
>>> import numpy as np
>>> a = np.array([1, 2, np.nan, 4, np.nan])
>>> print(Counter(np.isnan(a)))
Counter({False: 3, True: 2})

【1x03】统计数组中 inf 的个数

1、isinf() 方法可以判断哪些是 inf,再结合 np.count_nonzero 方法可以判断数组中 inf 的个数:

>>> import numpy as np
>>> a = np.array([[1, 2, 3, 4], [np.inf, 6, 7, -np.inf], [9 ,-np.inf, 10, 11]])
>>> print(a)
[[  1.   2.   3.   4.]
 [ inf   6.   7. -inf]
 [  9. -inf  10.  11.]]
>>> np.isinf(a)
array([[False, False, False, False],
       [ True, False, False,  True],
       [False,  True, False, False]])
>>> np.count_nonzero(np.isinf(a))
3

2、利用 collections 模块的 Counter 方法来统计 inf 的个数(此方法仅适用于一维数组):

>>> from collections import Counter
>>> import numpy as np
>>> a = np.array([1, 2, np.inf, 4, -np.inf])
>>> print(Counter(np.isinf(a)))
Counter({False: 3, True: 2})

【1x04】替换 inf 和 nan

numpy.nan_to_num() 方法可以将 nan 替换为零,将 inf 替换为有限数。

>>> import numpy as np
>>> a = np.array([[1, np.nan, 3, 4], [np.inf, 6, 7, -np.inf], [9 ,-np.inf, 10, np.nan]])
>>> print(a)
[[  1.  nan   3.   4.]
 [ inf   6.   7. -inf]
 [  9. -inf  10.  nan]]
>>> print(np.nan_to_num(a))
[[ 1.00000000e+000  0.00000000e+000  3.00000000e+000  4.00000000e+000]
 [ 1.79769313e+308  6.00000000e+000  7.00000000e+000 -1.79769313e+308]
 [ 9.00000000e+000 -1.79769313e+308  1.00000000e+001  0.00000000e+000]]

如果要将 nan 和 inf 替换成特定的值,则可以用以下方法:

>>> import numpy as np
>>> a = np.array([[1, np.nan, 3, 4], [np.inf, 6, 7, -np.inf], [9 ,-np.inf, 10, np.nan]])
>>> print(a)
[[  1.  nan   3.   4.]
 [ inf   6.   7. -inf]
 [  9. -inf  10.  nan]]
>>> loc_nan = np.isnan(a)
>>> loc_inf = np.isinf(a)
>>> a[loc_nan] = 111
>>> a[loc_inf] = 222
>>> print(a)
[[  1. 111.   3.   4.]
 [222.   6.   7. 222.]
 [  9. 222.  10. 111.]]

【2x00】NumPy 索引

【2x01】获取具体元素

NumPy 的索引和 Python 列表的索引类似,可以通过中括号指定索引获取第 i 个值(从 0 开始计数):

>>> import numpy as np
>>> a = np.array([1, 2, 3, 4])
>>> print(a[0])
1
>>> print(a[2])
3
>>> print(a[-1])
4
>>> print(a[-2])
3

在多维数组中,可以用逗号分隔的索引元组获取具体某个元素:

>>> import numpy as np
>>> a = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
>>> print(a)
[[1 2 3]
 [4 5 6]
 [7 8 9]]
>>> print(a[1, 2])
6
>>> print(a[0, -2])
2
>>> a = np.array([[[1,2,3,4], [5,6,7,8]], [[9,10,11,12], [13,14,15,16]], [[17,18,19,20], [21,22,23,24]]])
>>> print(a)
[[[ 1  2  3  4]
  [ 5  6  7  8]]

 [[ 9 10 11 12]
  [13 14 15 16]]

 [[17 18 19 20]
  [21 22 23 24]]]
>>> print(a[0, 1, 2])
7
>>> print(a[1, 0, -1])
12

【2x02】获取行或列

>>> a = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]])
>>> print(a)
[[ 1  2  3]
 [ 4  5  6]
 [ 7  8  9]
 [10 11 12]]
>>> print(a[1])       # 取一整行
[4 5 6]
>>> print(a[1, :])    # 取一整行,效果同上
[4 5 6]
>>> print(a[1, ...])  # 取一整行,效果同上
[4 5 6]
>>> print(a[:, 2])    # 取一整列
[ 3  6  9 12]
>>> print(a[..., 2])  # 取一整列,效果同上
[ 3  6  9 12]
>>> print(a[1:3])     # 取多行
[[4 5 6]
 [7 8 9]]
>>> print(a[:, 0:2])  # 取多列
[[ 1  2]
 [ 4  5]
 [ 7  8]
 [10 11]]
>>> print(a[[1, 3], :])  # 取第一、三行和所有列
[[ 4  5  6]
 [10 11 12]]
>>> print(a[:, [0, 2]])  # 取第零、二列和所有行
[[ 1  3]
 [ 4  6]
 [ 7  9]
 [10 12]]

【2x03】布尔索引

除了直接获取元素以外,还可以通过一个布尔数组来索引目标数组,即通过布尔运算(如:比较运算符)来获取符合指定条件的元素的数组。

以下实例将筛选出大于 6 的元素:

>>> a = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]])
>>> print(a)
[[ 1  2  3]
 [ 4  5  6]
 [ 7  8  9]
 [10 11 12]]
>>> print(a[a > 6])
[ 7  8  9 10 11 12]

以下实例使用取补运算符 ~ 来过滤掉 inf:

>>> import numpy as np
>>> a = np.array([1, 2, np.inf, 3, -np.inf, 4, 5])
>>> print(a)
[  1.   2.  inf   3. -inf   4.   5.]
>>> print(a[~np.isinf(a)])
[1. 2. 3. 4. 5.]

【2x04】花式索引

花式索引:传递一个索引数组来一次性获得多个数组元素,花式索引总是将数据复制到新数组中。

花式索引根据索引数组的值作为目标数组的某个轴的下标来取值。对于使用一维整型数组作为索引,如果目标是一维数组,那么索引的结果就是对应位置的元素;如果目标是二维数组,那么就是对应下标的行。

花式索引结果的形状与索引数组的形状一致,而不是与被索引数组的形状一致。

一维数组中的应用:

>>> import numpy as np
>>> a = np.array([1, 2, 3, 4, 5, 6])
>>> print([a[0], a[2], a[-1]])
[1, 3, 6]
>>> import numpy as np
>>> a = np.array([1, 2, 3, 4, 5, 6])
>>> ind = [0, 2, -1]
>>> print(a[ind])
[1 3 6]

二维数组中的应用:

>>> import numpy as np
>>> a = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
>>> print(a)
[[ 1  2  3  4]
 [ 5  6  7  8]
 [ 9 10 11 12]]
>>> print([a[0, 1], a[1, 2], a[2, 3]])
[2, 7, 12]
>>> import numpy as np
>>> a = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
>>> row = np.array([0, 1, 2])       # 行
>>> col = np.array([1, 2, 3])       # 列
>>> print(a[row, col])
[ 2  7 12]

【3x00】NumPy 切片

Ndarray 数组对象基于 0 - n 的下标进行索引,与 Python 中列表的切片操作一样,NumPy 的切片也可以通过冒号分隔切片参数 [start:stop:step] 来进行切片操作,另外,NumPy 也提供了一个内置函数 slice(start, stop, step) 来进行切片操作。

slice 方法应用:

>>> import numpy as np
>>> a = np.arange(10)
>>> print(a)
[0 1 2 3 4 5 6 7 8 9]
>>> b = slice(2, 8, 2)    # 从索引 2 开始到索引 8 停止,步长为 2
>>> print(a[b])
[2 4 6]

通过冒号分隔切片参数 [start:stop:step] 来进行切片:

>>> import numpy as np
>>> a = np.arange(12)
>>> print(a)
[ 0  1  2  3  4  5  6  7  8  9 10 11]
>>> print(a[1:9:2])        # 从索引 1 开始到索引 9 停止,步长为 2
[1 3 5 7]
>>> print(a[5:])
[ 5  6  7  8  9 10 11]     # 从索引 5 开始一直到最后一个元素

二数组中的切片,格式类似于 a[start:stop:step, start:stop:step],以逗号来分割行与列。

>>> import numpy as np
>>> a = np.array([[1, 2, 3], [4, 5, 6], [7, 8 ,9], [10, 11, 12], [13, 14, 15], [16, 17, 18]])
>>> print(a)
[[ 1  2  3]
 [ 4  5  6]
 [ 7  8  9]
 [10 11 12]
 [13 14 15]
 [16 17 18]]
>>> print(a[0:4:2])       # 按照行从索引 0 开始到索引 4 停止,步长为 2
[[1 2 3]
 [7 8 9]]
>>> print(a[0:4:2,...])   # 与上述方法相同,... 与 : 作用相同
[[1 2 3]
 [7 8 9]]
>>> print(a[...,1:])      # 按照列从索引 1 开始一直到最后一个元素
[[ 2  3]
 [ 5  6]
 [ 8  9]
 [11 12]
 [14 15]
 [17 18]]
>>> print(a[1:5:2,1:])   # 分别按照行从索引 1 开始到索引 5 停止,步长为 2,按照列从索引 1 开始一直到最后一个元素
[[ 5  6]
 [11 12]]

三数组中的切片,格式类似于 a[start:stop:step, start:stop:step, start:stop:step],以逗号来分割块、行与列。

>>> import numpy as np
>>> a = np.array([[[1,2,3,4], [5,6,7,8]], [[9,10,11,12], [13,14,15,16]], [[17,18,19,20], [21,22,23,24]]])
>>> print(a)
[[[ 1  2  3  4]
  [ 5  6  7  8]]

 [[ 9 10 11 12]
  [13 14 15 16]]

 [[17 18 19 20]
  [21 22 23 24]]]
>>> print(a[1,:,0:2])   # 取索引为 1 的块数、所有行、索引为 0 到 2 的列
[[ 9 10]
 [13 14]]
>>> print(a[1,:,:])     # 取索引为 1 的块数、所有行与列
[[ 9 10 11 12]
 [13 14 15 16]]
>>> print(a[1,...,:])   # ... 与 : 作用相同
[[ 9 10 11 12]
 [13 14 15 16]]

【4x00】NumPy 数组运算以及广播原则

NumPy 数组与数之间、数组与数组之间都支持加减乘除的计算。

  • 对于数组与数之间的计算,由于 NumPy 的广播机制,加减乘除都会对数组的每一个元素进行操作。

  • 对于数组与数组之间的计算,相同维度的,相同位置元素之间会进行计算,不同维度的,将自动触发广播机制。

广播(Broadcast)原则:如果两个数组的后缘维度(trailing dimension,即从末尾开始算起的维度)的轴长度相符,或其中的一方的长度为 1,则认为它们是广播兼容的。广播会在缺失和(或)长度为 1 的维度上进行。

通俗理解,以下情况的两个数组均可进行广播:

1、两个数组各维度大小从后往前比对均一致:

>>> import numpy as np
>>> a = np.ones((3, 4, 5))
>>> b = np.ones((4, 5))
>>> print((a+b).shape)
(3, 4, 5)
>>>
>>> 
>>> c = np.ones((3))
>>> d = np.ones((2, 3))
>>> print((c+d).shape)
(2, 3)
>>>
>>> 
>>> e = np.ones((3, 4, 5))
>>> f = np.ones((4, 2))
>>> print((e+f).shape)
Traceback (most recent call last):
  File "<pyshell#16>", line 1, in <module>
    print((e+f).shape)
ValueError: operands could not be broadcast together with shapes (3,4,5) (4,2) 
# 因为 e 和 f 维度大小此前往后对比不一致,所以会抛出异常

2、两个数组存在一些维度大小不相等时,在其中一个数组中,这个不相等的维度大小为 1:

>>> import numpy as np
>>> a = np.ones((3, 4, 5))
>>> b = np.ones((4, 1))
>>> print((a+b).shape)
(3, 4, 5)
# 此时虽然 a 与 b 的维度大小此前往后对比不一致,但是 b 数组的这个维度大小为 1,所以仍然可以相加

那么当两个数组之间可以进行广播的时候,具体是怎样广播、怎样计算的呢?以下通过代码和图解来更进一步理解广播机制:

数组与数之间的运算:

>>> import numpy as np
>>> a = np.array([1, 2, 3, 4, 5])
>>> print(a)
[1 2 3 4 5]
>>> print(a+1)     # 对数组每一个元素都 +1
[2 3 4 5 6]
>>> print(a-1)     # 对数组每一个元素都 -1
[0 1 2 3 4]
>>> print(a*2)     # 对数组每一个元素都 *1
[ 2  4  6  8 10]
>>> print(a/2)     # 对数组每一个元素都 /1
[0.5 1.  1.5 2.  2.5]

相同维度的数组与数组之间的运算:

>>> import numpy as np
>>> a = np.array([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]])
>>> b = np.array([[11, 12, 13, 14, 15], [16, 17, 18, 19, 20]])
>>> print(a)
[[ 1  2  3  4  5]
 [ 6  7  8  9 10]]
>>> print(b)
[[11 12 13 14 15]
 [16 17 18 19 20]]
>>> print(a+b)
[[12 14 16 18 20]
 [22 24 26 28 30]]
>>> print(b-a)
[[10 10 10 10 10]
 [10 10 10 10 10]]
>>> print(a*b)
[[ 11  24  39  56  75]
 [ 96 119 144 171 200]]
>>> print(b/a)
[[11.          6.          4.33333333  3.5         3.        ]
 [ 2.66666667  2.42857143  2.25        2.11111111  2.        ]]

不同维度的数组与数组之间的运算:

实例一:一个二维数组与一个一维数组相加,此时就会触发广播机制,代码与图解如下:

>>> import numpy as np
>>> a = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]])
>>> b = np.array([20, 20, 20])
>>> print(a)
[[ 1  2  3]
 [ 4  5  6]
 [ 7  8  9]
 [10 11 12]]
>>> print(b)
[20 20 20]
>>> print(a+b)
[[21 22 23]
 [24 25 26]
 [27 28 29]
 [30 31 32]]

01

实例二:一个 4 行 3 列的二维数组与一个 4 行 1 列的二维数组相加,此时就会触发广播机制,代码与图解如下:

>>> import numpy as np
>>> a = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]])
>>> b = np.array([[1], [2], [3], [4]])
>>> print(a)
[[ 1  2  3]
 [ 4  5  6]
 [ 7  8  9]
 [10 11 12]]
>>> print(b)
[[1]
 [2]
 [3]
 [4]]
>>> print(a+b)
[[ 2  3  4]
 [ 6  7  8]
 [10 11 12]
 [14 15 16]]

02

实例三:一个 3 块 4 行 2 列,即 shape=(3, 4, 2) 的三维数组与一个 1 块 4 行 2 列,即 shape=(1, 4, 2) 的三维数组相加,此时就会触发广播机制,代码与图解如下:

>>> import numpy as np
>>> a = np.array([[[1, 2], [3, 4], [5, 6], [7, 8]], [[9, 10], [11, 12], [13, 14], [15, 16]], [[17, 18], [19, 20], [21, 22], [23, 24]]])
>>> b = np.array([[[1, 2], [3, 4], [5, 6], [7, 8]]])
>>> print(a)
[[[ 1  2]
  [ 3  4]
  [ 5  6]
  [ 7  8]]

 [[ 9 10]
  [11 12]
  [13 14]
  [15 16]]

 [[17 18]
  [19 20]
  [21 22]
  [23 24]]]
>>> print(b)
[[[1 2]
  [3 4]
  [5 6]
  [7 8]]]
>>> print(a.shape)
(3, 4, 2)
>>> print(b.shape)
(1, 4, 2)
>>> print(a+b)
[[[ 2  4]
  [ 6  8]
  [10 12]
  [14 16]]

 [[10 12]
  [14 16]
  [18 20]
  [22 24]]

 [[18 20]
  [22 24]
  [26 28]
  [30 32]]]

03


这里是一段物理防爬虫文本,请读者忽略。
本文原创首发于 CSDN,作者 ITBOB。
博客首页:https://itrhx.blog.csdn.net/
本文链接:https://itrhx.blog.csdn.net/article/details/104988137
未经授权,禁止转载!恶意转载,后果自负!尊重原创,远离剽窃!

【5x00】数组的拼接与元素的添加

【5x01】将数组转换成列表,拼接完成再转换成数组

数组的拼接,可以先将数组转成列表,利用列表的拼接函数,如:append()、extend() 等进行拼接处理,然后再将列表转成数组即可。

>>> import numpy as np
>>> a = np.array([1, 2, 3])
>>> b = np.array([4, 5, 6])
>>> a_list = list(a)
>>> b_list = list(b)
>>> for i in b_list:
    a_list.append(i)

    
>>> a_list
[1, 2, 3, 4, 5, 6]
>>> a = np.array(a_list)
>>> a
array([1, 2, 3, 4, 5, 6])

【5x02】numpy.append()

numpy.append() 方法可以将一个数组附加到另一个数组的尾部,与 Python 列表中的 append 方法类似,仅支持两个数组之间的拼接,不能一次性拼接多个数组。

基本语法:numpy.append(a, values, axis=None)

参数解释:

参数 描述
a 被添加元素的目标数组
values 要添加元素的目标数组,即将该数组添加到 a 数组的尾部
如果指定了 axis 的值,则要求该数组的维度必须与 a 相同
axis 指定轴,按照指定轴的方向进行拼接
如果未指定轴,则在使用前会将 a 和 values 都展平

应用举例:

>>> import numpy as np
>>> a = np.array([1, 2, 3])
>>> b = np.array([4, 5, 6])
>>> print(np.append(a, b))                 # 两个一维数组进行拼接
[1 2 3 4 5 6]
>>> 
>>> a = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
>>> b = np.array([10, 11, 12])
>>> print(np.append(a, b))                 # 一维数组与二维数组进行拼接
[ 1  2  3  4  5  6  7  8  9 10 11 12]
>>> 
>>> a = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]])
>>> b = np.array([[13, 14, 15], [16, 17, 18]])
>>> print(np.append(a, b))                # 二维数组与三维数组进行拼接
[ 1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18]
>>> print(type(np.append(a, b)))          # 拼接后的数组仍然是一个 ndarray 对象
<class 'numpy.ndarray'>

指定 axis 的值举例(指定了 axis 的值,要求两个数组的维度必须相同):

>>> import numpy as np
>>> a = np.array([[1, 2, 3], [4, 5, 6]])
>>> b = np.array([[7, 8, 9]])
>>> print(np.append(a, b, axis=0))       # a、b 均为二维数组,指定 axis 值为 0
[[1 2 3]
 [4 5 6]
 [7 8 9]]
>>>
>>> a = np.array([[1, 2, 3], [4, 5, 6]])
>>> b = np.array([7, 8, 9])
>>> print(np.append(a, b, axis=0))      # a 为二维数组,b 为一维数组,指定 axis 值为 0,此时会报错
Traceback (most recent call last):
  ...
  ...
ValueError: all the input arrays must have same number of dimensions, ...

【5x03】numpy.concatenate()

numpy.concatenate() 方法能够一次完成多个相同形状数组的拼接。该方法效率更高,适合大规模的数据拼接。

基本语法:numpy.concatenate((a1, a2, ...), axis=0)

参数解释:

参数 描述
a1, a2, … 要拼接的多个数组,要求各数组形状相同
axis 指定轴,按照指定轴的方向进行拼接,默认为 0 轴

要求各数组形状相同举例:如果 axis=0,则要求 1 轴(竖轴)相同,如果 axis=1,则要求 0 轴(横轴)相同。

应用举例:

>>> import numpy as np
>>> a = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
>>> b = np.array([[10, 11, 12], [13, 14, 15]])
>>> c = np.array([[16, 17, 18]])        # 三个二维数组的 1 轴(竖轴)相同
>>> print(np.concatenate((a, b, c)))    # 三个二维数组默认沿 0 轴(横轴)进行拼接
[[ 1  2  3]
 [ 4  5  6]
 [ 7  8  9]
 [10 11 12]
 [13 14 15]
 [16 17 18]]
>>> import numpy as np
>>> a = np.array([[1, 2, 3, 4], [5, 6, 7, 8]])
>>> b = np.array([[9, 10, 11], [12, 13, 14]])
>>> c = np.array([[15, 16], [17, 18]])          # 三个二维数组的 0 轴(横轴)相同
>>> print(np.concatenate((a, b, c), axis=1))    # 三个二维数组沿 1 轴(竖轴)进行拼接
[[ 1  2  3  4  9 10 11 15 16]
 [ 5  6  7  8 12 13 14 17 18]]
>>> import numpy as np
>>> a = np.array([[1, 2, 3, 4], [5, 6, 7, 8]])
>>> b = np.array([[9, 10, 11], [12, 13, 14]])
>>> c = np.array([[15, 16], [17, 18]])          # 三个二维数组的 0 轴(横轴)相同
>>> print(np.concatenate((a, b, c), axis=0))    # 三个二维数组沿 0 轴(横轴)进行拼接将会报错
Traceback (most recent call last):
  ...
  ...
ValueError: all the input array dimensions for the concatenation axis must match exactly, ...

【5x04】numpy.stack()

numpy.stack() 方法用于沿新轴连接数组序列。

基本语法:numpy.stack(arrays, axis=0)

参数解释:

参数 描述
arrays 相同形状的数组序列
axis 返回数组中的轴,输入数组将沿着该轴来进行堆叠

应用举例:

>>> import numpy as np
>>> a = np.array([1, 2, 3])
>>> b = np.array([4, 5, 6])
>>> print(np.stack((a, b),axis=0))
[[1 2 3]
 [4 5 6]]
>>> print(np.stack((a, b),axis=1))
[[1 4]
 [2 5]
 [3 6]]
>>> import numpy as np
>>> a = np.array([[1,2],[3,4]])
>>> b = np.array([[5,6],[7,8]])
>>> print(np.stack((a,b),axis=0))
[[[1 2]
  [3 4]]

 [[5 6]
  [7 8]]]
>>> print(np.stack((a,b),axis=1))
[[[1 2]
  [5 6]]

 [[3 4]
  [7 8]]]

【5x05】numpy.vstack()

numpy.vstack() 方法通过垂直堆叠来生成数组。

基本语法:numpy.vstack(tup)

参数解释:tup:数组序列,如果是一维数组进行堆叠,则数组长度必须相同,其它数组除了第一个轴(axis=0)的长度可以不同外,其它轴的长度必须相同。

应用举例:

>>> import numpy as np
>>> a = np.array([1, 2, 3])
>>> b = np.array([4, 5, 6])
>>> print(np.vstack((a,b)))
[[1 2 3]
 [4 5 6]]
>>> 
>>> b = np.array([4, 5])
>>> print(np.vstack((a,b)))       # 一维数组长度不一样时将抛出异常
Traceback (most recent call last):
  ...
  ...
ValueError: all the input array dimensions for the concatenation axis must match exactly, ...
>>> import numpy as np
>>> a = np.array([[1,2],[3,4]])
>>> b = np.array([[5,6],[7,8]])
>>> a.shape
(2, 2)
>>> b.shape
(2, 2)
>>> print(np.vstack((a,b)))
[[1 2]
 [3 4]
 [5 6]
 [7 8]]
>>> import numpy as np
>>> a = np.array([[1,2],[3,4]])
>>> b = np.array([[5,6],[7,8],[9,10]])
>>> a.shape
(2, 2)
>>> b.shape
(3, 2)
>>> print(np.vstack((a,b)))    # 第一个轴(axis=0)可以不同,其它轴必须相同
[[ 1  2]
 [ 3  4]
 [ 5  6]
 [ 7  8]
 [ 9 10]]

【5x06】numpy.hstack()

numpy.hstack() 方法通过水平堆叠来生成数组。

基本语法:numpy.hstack(tup)

参数解释:tup:数组序列,除了一维数组的堆叠可以是不同长度外,其它数组堆叠时,除了第二个轴(axis=1)的长度可以不同外,其它轴的长度必须相同。

应用举例:

>>> import numpy as np
>>> a = np.array([1, 2, 3])
>>> b = np.array([4, 5])
>>> print(np.hstack((a,b)))
[1 2 3 4 5]
>>> import numpy as np
>>> a = np.array([[1,2],[3,4]])
>>> b = np.array([[5,6],[7,8]])
>>> a.shape
(2, 2)
>>> b.shape
(2, 2)
>>> print(np.hstack((a,b)))
[[1 2 5 6]
 [3 4 7 8]]
>>> import numpy as np
>>> a = np.array([[1,2],[3,4]])
>>> b = np.array([[5,6,7],[8,9,10]])
>>> a.shape
(2, 2)
>>> b.shape
(2, 3)
>>> print(np.hstack((a,b)))       # 第二个轴(axis=1)可以不同,其它轴必须相同
[[ 1  2  5  6  7]
 [ 3  4  8  9 10]]

【5x07】numpy.dstack()

numpy.dstack() 方法会沿着第三个维度拼接数组。

基本语法:numpy.dstack(tup)

参数解释:tup:数组序列,除了第三个轴(axis=2)的长度可以不同外,其它轴的长度必须相同。一维或二维数组必须具有相同的形状。

应用举例:

>>> import numpy as np
>>> a = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
>>> b = np.array([[[9], [10]], [[11], [12]]])
>>> a.shape
(2, 2, 2)
>>> b.shape
(2, 2, 1)
>>> print(np.dstack((a,b)))     # a 与 b 的第三个轴(axis=2)一个是 2,另一个是 1,可以不同,但其他轴必须相同
[[[ 1  2  9]
  [ 3  4 10]]

 [[ 5  6 11]
  [ 7  8 12]]]
>>> import numpy as np
>>> a = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
>>> b = np.array([[[9, 10], [11, 12]]])
>>> a.shape
(2, 2, 2)
>>> b.shape
(1, 2, 2)
>>> print(np.dstack((a,b)))    # a 与 b 的第一个轴(axis=0)不同,将会抛出异常
[[[ 1  2  9]
  [ 3  4 10]]

 [[ 5  6 11]
  [ 7  8 12]]]
>>> print(np.dstack((a,b)))
Traceback (most recent call last):
  ...
  ...
ValueError: all the input array dimensions for the concatenation axis must match exactly, ...

【5x08】以上几种方法的区别

  • concatenate() 方法在 axis=0 的时候相当于 vstack() 方法;
  • concatenate() 方法在 axis=1 的时候相当于 hstack() 方法;
  • concatenate() 方法在 axis=2 的时候相当于 dstack() 方法;
  • concatenate() 方法不会生成一个新的维度,且数组的维度不一定相同,而 stack() 方法生成一个新的维度,并且要求所有数组形状都要一样。

concatenate() 方法与 stack() 方法比较:

>>> import numpy as np
>>> a = np.array([1, 2, 3])
>>> b = np.array([4, 5, 6])
>>> c = np.stack((a, b), axis=0)
>>> d = np.concatenate((a, b), axis=0)
>>> a.shape
(3,)
>>> b.shape
(3,)
>>> c.shape
(2, 3)
>>> d.shape
(6,)
>>> print(c)
[[1 2 3]
 [4 5 6]]
>>> print(d)
[1 2 3 4 5 6]

【5x09】numpy.insert()

numpy.insert() 方法沿指定轴在指定索引之前插入值。

基本语法:numpy.insert(arr, obj, values, axis=None)

参数解释:

参数 描述
arr 原数组
obj 索引值,将在其之前插入值
values 要插入的值
axis 轴,将沿着该轴进行插入操作,如果未指定,则插入前,原数组会被展开,变为一维数组

应用举例:

>>> import numpy as np
>>> a = np.array([[1,2],[3,4],[5,6]])
>>> print(np.insert(a, 3, [0, 0]))          # 未指定 axis 参数,在插入之前原数组会被展开
[1 2 3 0 0 4 5 6]
>>> print(np.insert(a, 1, [0], axis = 0))   # 沿 0 轴广播插入
[[1 2]
 [0 0]
 [3 4]
 [5 6]]
>>> print(np.insert(a, 1, 11, axis = 1))    # 沿 1 轴广播插入
[[ 1 11  2]
 [ 3 11  4]
 [ 5 11  6]]

【5x10】numpy.r_

numpy.r_:rrow(行) 的缩写,即按照行连接两个矩阵,要求列数相等。

应用举例:

>>> import numpy as np
>>> a = np.array([[1, 2, 3],[7, 8, 9]])
>>> b = np.array([[4, 5, 6],[1, 2, 3]])
>>> 
>>> np.r_[a, b]
array([[1, 2, 3],
       [7, 8, 9],
       [4, 5, 6],
       [1, 2, 3]])

【5x11】numpy.c_

numpy.c_:ccolumn(列) 的缩写,即按照列连接两个矩阵,要求行数相等。

应用举例:

>>> import numpy as np
>>> a = np.array([[1, 2, 3],[7, 8, 9]])
>>> b = np.array([[4, 5, 6],[1, 2, 3]])
>>> 
>>> np.c_[a, b]
array([[1, 2, 3, 4, 5, 6],
       [7, 8, 9, 1, 2, 3]])

【6x00】数组的分割与元素的删除

【6x01】numpy.split()

numpy.split() 方法可以沿特定的轴将数组均等的分割为子数组。如果不能等分,将抛出异常。

基本语法:numpy.split(ary, indices_or_sections, axis=0)

参数解释:

参数 描述
ary 被分割的数组
indices_or_sections 如果是一个整数 N,则该数组将沿 axis 均分为 N 个数组
如果是一维整数数组,则数组元素代表每个分割点位置(左闭右开),N 个分裂点会得到 N + 1 个子数组
axis 沿着哪个维度进行分割,默认为 0,横向分割;为 1 时,纵向分割

应用举例:

>>> import numpy as np
>>> a = np.arange(10)
>>> print(a)
[0 1 2 3 4 5 6 7 8 9]
>>> print(np.split(a, 5))              # 将数组分为五个大小相等的子数组
[array([0, 1]), 
 array([2, 3]), 
 array([4, 5]), 
 array([6, 7]), 
 array([8, 9])]
>>>
>>> print(np.split(a, 4))              # 无法等分的情况下将抛出异常
Traceback (most recent call last):
  ...
  ...
ValueError: array split does not result in an equal division
>>>
>>> print(np.split(a, [4, 8]))        # 分割点为索引 4 和 8 的位置,相当于 a[:4]、a[4:8]、a[8:]
[array([0, 1, 2, 3]), 
 array([4, 5, 6, 7]), 
 array([8, 9])]
>>>
>>> a = np.array([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]])
>>> print(np.split(a, 5, axis=1))     # 指定 axis=1,按照纵向分割数组
[array([[1], 
        [6]]),
 array([[2], 
 		[7]]),
 array([[3], 
 		[8]]),
 array([[4], 
 		[9]]),
 array([[ 5], 
 		[10]])]

【6x02】numpy.array_split()

numpy.array_split() 的用法和作用都与 split() 方法一致,都可以用一个整数或者整数列表来分割数组。

两者的区别:如果输入的是一个 int 类型的数字,那么在 split() 方法中,数组必须是均等的分割,否则就会报错,而在 array_split() 方法中是可以进行不均等的分割的。

基本语法:numpy.array_split(ary, indices_or_sections, axis=0)

参数解释:

参数 描述
ary 被分割的数组
indices_or_sections 如果是一个整数 N,则该数组将沿 axis 分割为 N 个数组,可以不是均分的
如果是一维整数数组,则数组元素代表每个分割点位置(左闭右开),N 个分裂点会得到 N + 1 个子数组
axis 沿着哪个维度进行分割,默认为 0,横向分割;为 1 时,纵向分割

应用举例:

>>> import numpy as np
>>> a = np.array([1, 2, 3, 4, 5, 6, 7])
>>> print(np.array_split(a, 3))
[array([1, 2, 3]), array([4, 5]), array([6, 7])]   # 可以是不均分的
>>>
>>> print(np.array_split(a, 4))
[array([1, 2]), array([3, 4]), array([5, 6]), array([7])]

【6x03】numpy.vsplit()

numpy.vsplit() 方法相当于 split() 方法在 axis=0 时的效果,即横向分割数组。

基本语法:numpy.vsplit(ary, indices_or_sections)

参数解释:

参数 描述
ary 被分割的数组
indices_or_sections 如果是一个整数 N,则该数组将沿 axis 分为 N 个相等的数组
如果是一维整数数组,则数组元素代表每个分割点位置(左闭右开),N 个分裂点会得到 N + 1 个子数组

应用举例:

>>> import numpy as np
>>> a = np.array([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]])
>>> a = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]])
>>> print(np.vsplit(a, 2))
[array([[1, 2, 3], 
        [4, 5, 6]]),
 array([[ 7,  8,  9], 
 		[10, 11, 12]])]
>>>
>>> print(np.vsplit(a, [1, 3]))
[array([[1, 2, 3]]),
 array([[4, 5, 6], 
 		[7, 8, 9]]),
 array([[10, 11, 12]])]

【6x04】numpy.hsplit()

numpy.hsplit() 方法相当于 split() 方法在 axis=1 时的效果,即纵向分割数组。

基本语法:numpy.hsplit(ary, indices_or_sections)

参数解释:

参数 描述
ary 被分割的数组
indices_or_sections 如果是一个整数 N,则该数组将沿 axis 分为 N 个相等的数组
如果是一维整数数组,则数组元素代表每个分割点位置(左闭右开),N 个分裂点会得到 N + 1 个子数组

应用举例:

>>> import numpy as np
>>> a = np.array([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]])
>>> print(np.hsplit(a, 5))
[array([[1], 
        [6]]), 
 array([[2], 
 		[7]]),
 array([[3], 
 		[8]]),
 array([[4], 
 		[9]]),
 array([[ 5], 
 		[10]])]
>>>
>>> print(np.hsplit(a, [1, 3]))
[array([[1], 
        [6]]),
 array([[2, 3], 
 		[7, 8]]),
 array([[ 4,  5], 
 		[ 9, 10]])]

【6x05】numpy.dsplit()

numpy.dsplit() 方法相当于 split() 方法在 axis=2 时的效果,即沿第三轴将数组拆分为多个子数组。

基本语法:numpy.dsplit(ary, indices_or_sections)

参数解释:

参数 描述
ary 被分割的数组
indices_or_sections 如果是一个整数 N,则该数组将沿 axis 分为 N 个相等的数组
如果是一维整数数组,则数组元素代表每个分割点位置(左闭右开),N 个分裂点会得到 N + 1 个子数组

应用举例:

>>> import numpy as np
>>> a = np.arange(16).reshape(2, 2, 4)
>>> print(a)
[[[ 0  1  2  3]
  [ 4  5  6  7]]

 [[ 8  9 10 11]
  [12 13 14 15]]]
>>> print(np.dsplit(a, 2))
[array([[[ 0,  1], 
         [ 4,  5]], 
         [[ 8,  9], 
         [12, 13]]]), 
 array([[[ 2,  3], 
 		 [ 6,  7]], 
 		 [[10, 11], 
 		 [14, 15]]])]
>>>
>>> print(np.dsplit(a, [3, 6]))
[array([[[ 0,  1,  2], 
         [ 4,  5,  6]], 
         [[ 8,  9, 10], 
         [12, 13, 14]]]),
 array([[[ 3], 
 		 [ 7]], 
 		 [[11], 
 		 [15]]]), 
 array([], shape=(2, 2, 0), dtype=int32)]

【6x06】numpy.delete()

numpy.delete() 方法返回一个从原数组中删除了指定子数组的新数组。

基本语法:numpy.delete(arr,obj,axis=None)

参数解释:

参数 描述
arr 原数组
obj 可以是切片、整数或整数数组形式,表示沿指定轴删除的子数组的索引
当 obj 为切片形式时,要用 np.s_[:] 的格式
axis 轴,将沿着该轴进行插入操作,如果未指定,则插入前,原数组会被展开,变为一维数组

应用举例:

>>> import numpy as np
>>> a = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
>>> print(np.delete(a, 8))          # 未指定 axis 参数,在插入之前原数组会被展开,然后再删除索引为 8 的元素
[ 1  2  3  4  5  6  7  8 10 11 12]
>>>
>>> print(np.delete(a, 1, axis=0))  # 指定 axis=0,删除索引值为 1 即第二行
[[ 1  2  3  4]
 [ 9 10 11 12]]
>>>
>>> print(np.delete(a, 1, axis=1))  # 指定 axis=1,删除索引值为 1 即第二列
[[ 1  3  4]
 [ 5  7  8]
 [ 9 11 12]]
>>>
>>> print(np.delete(a, np.s_[:2], axis=1)) # 切片形式,删除前两列
[[ 3  4]
 [ 7  8]
 [11 12]]
>>>
>>> print(np.delete(a, [0, 2], axis=1))    # 数组形式,删除索引值为 0 和 2 的列
[[ 2  4]
 [ 6  8]
 [10 12]]

【6x07】numpy.unique()

numpy.unique() 方法用于去除数组中的重复元素。

基本语法:numpy.unique(arr, return_index=False, return_inverse=False, return_counts=False, axis=None)

参数解释:

参数 描述
arr 原数组,如果不是一维数组则会被展开为一维数组
return_index 如果为 true,则返回新列表元素在旧列表中的位置(下标),并以列表形式储
return_inverse 如果为 true,则返回旧列表元素在新列表中的位置(下标),并以列表形式储
return_counts 如果为 true,则返回去重数组中的元素在原数组中的出现次数
axis 指定轴

应用举例:

未指定 axis 值,原数组将会被展开:

>>> import numpy as np
>>> a = np.array([1, 1, 2, 2, 3, 4, 5, 5])
>>> b = np.array([[1, 1], [2, 3], [3, 4]])
>>> print(np.unique(a))
[1 2 3 4 5]
>>> print(np.unique(b))
[1 2 3 4]

指定 axis 值:

>>> import numpy as np
>>> a = np.array([[1, 0, 1], [1, 0, 1], [2, 3, 2], [5, 6, 5]])
>>> print(a)
[[1 0 1]
 [1 0 1]
 [2 3 2]
 [5 6 5]]
>>> print(np.unique(a, axis=0))    # 删除相同的行
[[1 0 1]
 [2 3 2]
 [5 6 5]]
>>> print(np.unique(a, axis=1))    # 删除相同的列
[[0 1]
 [0 1]
 [3 2]
 [6 5]]

return_counts 为 True 时,返回去重数组中的元素在原数组中的出现次数:

>>> import numpy as np
>>> a = np.array([1, 1, 1, 2, 2, 3, 4, 5, 5])
>>> print(np.unique(a, return_counts=True))
(array([1, 2, 3, 4, 5]), array([3, 2, 1, 1, 2], dtype=int64))
# 前一个 array 表示去重后的数组,后一个 array 表示每一个元素在原数组中出现的次数

这里是一段物理防爬虫文本,请读者忽略。
本文原创首发于 CSDN,作者 ITBOB。
博客首页:https://itrhx.blog.csdn.net/
本文链接:https://itrhx.blog.csdn.net/article/details/104988137
未经授权,禁止转载!恶意转载,后果自负!尊重原创,远离剽窃!