numpy_4 数组操作

概要

本文对数组操作进行知识梳理,重点掌握切片和索引。

array的分解和组合

切片和索引——依照「某种方法」切出一块内容

在做数组运算或数组操作时,返回结果不是数组的副本就是** 视图**。
所有赋值运算不会为数组和数组中的任何元素创建副本。
numpy.ndarray.copy() 函数创建一个副本。 对副本数据进行修改,不会影响到原始数据。
python 列表进行切片操作得到的数组是原数组的副本,而对** Numpy 数据进行切片操作得到的数组则是指向相同缓冲区的视图**。
start:stop:step

rng = np.random.default_rng(42)
arr = rng.random((5, 4))
arr
array([[0.77395605, 0.43887844, 0.85859792, 0.69736803],
       [0.09417735, 0.97562235, 0.7611397 , 0.78606431],
       [0.12811363, 0.45038594, 0.37079802, 0.92676499],
       [0.64386512, 0.82276161, 0.4434142 , 0.22723872],
       [0.55458479, 0.06381726, 0.82763117, 0.6316644 ]])
# 最简单的索引,取第 0 行
arr[0]         array([0.77395605, 0.43887844, 0.85859792, 0.69736803])
# 最简单的切片,取第 0 行第 1 列
arr[0, 1]      0.4388784397520523
# 带点范围 第 1-2 行
arr[1:3]
# 离散也可以:第 1,3 行
arr[[1, 3]]
# 加上维度:第 1-2 行,第 1 列
arr[1:3, 1]    array([0.97562235, 0.45038594])
# 离散也是一样:第 1,3 行,第 0 列
arr[[1,3], [0]]
# 简写:到最后或到开始。如第 3 行到最后一行
arr[3:]
# 开始到第 3 行(不包括第3行),第 1-3 列(不包括第3列)
arr[:3, 1:3]
# 跳跃,步长:start:stop:step,第 1 行到第 4 行,间隔为 2,即第 1、3 行
arr[1: 4: 2]
# 加上列,第 1、3 行,第 0、2 列
arr[1:4:2, 0:3:2]
# 第一列的值,其实是所有其他维度第 1 维的值
arr[...,1] 或者 arr[:,1]
x = np.array([[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]])

r = np.array([[0, 1], [3, 4]])
print(x[r])
# [[[11 12 13 14 15]
#   [16 17 18 19 20]]
#
#  [[26 27 28 29 30]
#   [31 32 33 34 35]]]

dots索引
使用…表示足够多的冒号来构建完整的索引列表。
比如,如果 x 是 5 维数组:

x[1,2,...] 等于 x[1,2,:,:,:]
x[...,3] 等于 x[:,:,:,:,3]
x[4,...,5,:] 等于 x[4,:,:,5,:]

take 索引
numpy. take(a, indices, axis=None, out=None, mode=‘raise’)

x = np.array([[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]])
r = [0, 1, 2]
print(np.take(x, r, axis=0))
# [[11 12 13 14 15]
#  [16 17 18 19 20]
#  [21 22 23 24 25]]

bool 索引

x = np.array([np.nan, 1, 2, np.nan, 3, 4, 5])
y = np.logical_not(np.isnan(x))
print(x[y])
# [1. 2. 3. 4. 5.]

数组遍历 apply_along_axis(func1d, axis, arr)

import numpy as np
x = np.array([[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]])
y = np.apply_along_axis(np.sum, 0, x)
print(y)  # [105 110 115 120 125]
y = np.apply_along_axis(np.sum, 1, x)
print(y)  # [ 65  90 115 140 165]

拼接、堆叠

np.concatenate 和 np.stack,前者是拼接,后者是堆叠(会增加一个维度),都可以指定维度

(array([[0.77395605, 0.43887844, 0.85859792],
[0.69736803, 0.09417735, 0.97562235]]),
array([[0.7611397 , 0.78606431, 0.12811363],
[0.45038594, 0.37079802, 0.92676499]]))

拼接

# 默认沿axis=0(列)连接
np.concatenate((arr1, arr2))
# 或:(维度大于1时)
# 竖直按行顺序拼接
# 注:vstack 看起来像 stack,但它是 concatenate,建议只使用 `np.concatenate`
np.vstack((arr1, arr2))

array([[0.77395605, 0.43887844, 0.85859792],
[0.69736803, 0.09417735, 0.97562235],
[0.7611397 , 0.78606431, 0.12811363],
[0.45038594, 0.37079802, 0.92676499]])

# 沿 axis=1(行)连接
np.concatenate((arr1, arr2), axis=1)
# 或:(维度大于1时)
# 水平按列顺序拼接
# 道理和 vstack 一样,建议使用 `np.concatenate` axis=1
np.hstack((arr1, arr2))

array([[0.77395605, 0.43887844, 0.85859792, 0.7611397 , 0.78606431,0.12811363],
[0.69736803, 0.09417735, 0.97562235, 0.45038594, 0.37079802, 0.92676499]])

堆叠(增加维度的拼接)

# 堆叠,默认根据 axis=0 进行
np.stack((arr1, arr2))

array([[[0.77395605, 0.43887844, 0.85859792],
        [0.69736803, 0.09417735, 0.97562235]],
        
       [[0.7611397 , 0.78606431, 0.12811363],
        [0.45038594, 0.37079802, 0.92676499]]])
# shape为(2,2,3)
# 堆叠,根据 axis=2
np.stack((arr1, arr2), axis=2)
# 或:
# 纵深按 axis=2 堆叠,不管它就行,我们认准 `stack`
np.dstack((arr1, arr2))

array([[[0.77395605, 0.7611397 ],
        [0.43887844, 0.78606431],
        [0.85859792, 0.12811363]],

       [[0.69736803, 0.45038594],
        [0.09417735, 0.37079802],
        [0.97562235, 0.92676499]]])
# shape为(2,3,2)

样例(注意)

import numpy as np
x = np.array([1, 2, 3])
y = np.array([7, 8, 9])
z = np.stack([x, y])
print(z.shape)  # (2, 3)
print(z)
# [[1 2 3]
#  [7 8 9]]

z = np.stack([x, y], axis=1)
print(z.shape)  # (3, 2)
print(z)
# [[1 7]
#  [2 8]
#  [3 9]]
import numpy as np
x = np.array([1, 2, 3]).reshape(1, 3)
y = np.array([7, 8, 9]).reshape(1, 3)
z = np.stack([x, y])
print(z.shape)  # (2, 1, 3)
print(z)
# [[[1 2 3]]
#
#  [[7 8 9]]]

z = np.stack([x, y], axis=1)
print(z.shape)  # (1, 2, 3)
print(z)
# [[[1 2 3]
#   [7 8 9]]]

z = np.stack([x, y], axis=2)
print(z.shape)  # (1, 3, 2)
print(z)
# [[[1 7]
#   [2 8]
#   [3 9]]]
import numpy as np
x = np.array([[1, 2, 3], [4, 5, 6]])
y = np.array([[7, 8, 9], [10, 11, 12]])
z = np.stack([x, y])
print(z.shape)  # (2, 2, 3)
print(z)
# [[[ 1  2  3]
#   [ 4  5  6]]
# 
#  [[ 7  8  9]
#   [10 11 12]]]

z = np.stack([x, y], axis=1)
print(z.shape)  # (2, 2, 3)
print(z)
# [[[ 1  2  3]
#   [ 7  8  9]]
# 
#  [[ 4  5  6]
#   [10 11 12]]]

z = np.stack([x, y], axis=2)
print(z.shape)  # (2, 3, 2)
print(z)
# [[[ 1  7]
#   [ 2  8]
#   [ 3  9]]
# 
#  [[ 4 10]
#   [ 5 11]
#   [ 6 12]]]

重复

numpy.tile(A, reps)
numpy.repeat(a, repeats, axis=None)
axis=0,沿着y轴复制,实际上增加了行数。
axis=1,沿着x轴复制,实际上增加了列数。
axis=None,会flatten当前矩阵,实际上就是变成了一个行向量。
repeats,可以为一个数,也可以为一个矩阵。

array([[0, 7, 6, 4],
[4, 8, 0, 6],
[2, 0, 5, 9]])

import numpy as np
x = np.repeat(3, 4)
print(x)  # [3 3 3 3]

x = np.array([[1, 2], [3, 4]])
y = np.repeat(x, 2)
print(y)
# [1 1 2 2 3 3 4 4]

y = np.repeat(x, 2, axis=0)
print(y)
# [[1 2]
#  [1 2]
#  [3 4]
#  [3 4]]

y = np.repeat(x, 2, axis=1)
print(y)
# [[1 1 2 2]
#  [3 3 4 4]]

y = np.repeat(x, [2, 3], axis=0)
print(y)
# [[1 2]
#  [1 2]
#  [3 4]
#  [3 4]
#  [3 4]]

y = np.repeat(x, [2, 3], axis=1)
print(y)
# [[1 1 2 2 2]
#  [3 3 4 4 4]]

分拆

记住 np.split 即可,其他是快捷方式。
array([[ 9, 77, 65, 44],
[43, 86, 9, 70],
[20, 10, 53, 97],
[73, 76, 72, 78],
[51, 13, 84, 45],
[50, 37, 19, 92]])

# 默认切分列(axis=0),切成 3 份
np.split(arr, 3)
# 或:
np.vsplit(arr, 3)  #  v-vertically (垂直,按照高速)

[array([[ 9, 77, 65, 44],
        [43, 86,  9, 70]]),
 array([[20, 10, 53, 97],
        [73, 76, 72, 78]]),
 array([[51, 13, 84, 45],
        [50, 37, 19, 92]])]
#(axis=1)切分行
np.split(arr, 2, axis=1)
# 或:
np.hsplit(arr, 2)  # h-horizontally(水平,按照宽度)

[array([[ 9, 77],
        [43, 86],
        [20, 10],
        [73, 76],
        [51, 13],
        [50, 37]]),
 array([[65, 44],
        [ 9, 70],
        [53, 97],
        [72, 78],
        [84, 45],
        [19, 92]])]

一些练习补充

验证两随机数组是否相等

例题:给定两个随机数组A和B,验证它们是否相等。
A = np.random.randint(0,2,5) B = np.random.randint(0,2,5)

#Assuming identical shape of the arrays and a tolerance for the comparison of values
equal = np.allclose(A,B)
print(equal)
#Checking both the shape and the element values, no tolerance (values have to be exactly equal)
equal = np.array_equal(A,B)
print(equal)

知识点总结:
numpy.allclose()函数: 比较两个数组在一个公差内按元素方向是否相等。
numpy.allclose(a, b, rtol=1e-05, atol=1e-08, equal_nan=False)
参数
a, b:要比较的输入数组。
rtol:浮动,相对公差参数。
atol:浮动,绝对公差参数。
equal_nan:是否将Nan的值比较为相等——在同一个地方,如果 equal_nan=True ,若inf在两个数组中位于同一位置且符号相同,则将它们视为相等。
返回布尔值:如果两个数组在给定的公差内相等,则返回“真”;否则返回“假”。

numpy.array_equal(arr1,arr2):此逻辑函数检查两个数组是否具有相同的形状和元素。

数组去重——如何在numpy数组中找到重复值?

例题:
在给定的numpy数组中找到重复的条目(第二次出现以后),并将它们标记为True。第一次出现应为False。
a = np.random.randint(0, 5, 10)

import numpy as np​
np.random.seed(100)
a = np.random.randint(0, 5, 10)
print(a)
# [0 0 3 0 2 4 2 2 2 2]
b = np.full(10, True)
vals, counts = np.unique(a, return_index=True)
b[counts] = False
print(b)
# [False  True False  True False False  True  True  True  True]

知识点总结:
numpy.unique(ar, return_index=False, return_inverse=False, return_counts=False, axis=None)[source]
一维数组
对一维数组或列表,unique()函数去除其中重复元素,并按元素大小返回一个新的无重复元组或列表。

import numpy as np
A = [1, 2, 2, 5,3, 4, 3]
a = np.unique(A)
print(a)
# [1 2 3 4 5]
C= ['fgfh','asd','fgfh','asdfds','wrh']
c= np.unique(C)
print(c)
# ['asd' 'asdfds' 'fgfh' 'wrh']

return_index = True表示:返回新列表元素在旧列表中的位置,并以列表形式储存在s中。

a, s= np.unique(A, return_index=True)
print(a)
print(s)
# [1 2 3 4 5]
# [0 1 4 5 3]

return_inverse = True表示:返回旧列表元素在新列表中的位置,并以列表形式储存在p中。

a,s,p = np.unique(A, return_index=True, return_inverse=True)
print(a)
print(s)
print(p)
# [1 2 3 4 5]
# [0 1 4 5 3]
# [0 1 1 4 2 3 2]

二维数组

import numpy
c=np.array(((1,2),(3,4),(5,6),(7,8),(7,8),(3,4),(1,2)))
x=c[:,0]+c[:,1]*1j
print('转化为虚数:',x)
print('虚数去重后:',np.unique(x))
print(np.unique(x,return_index=True)) # return_index:输出的元素索引值
idx=np.unique(x,return_index=True)[1]
print('二维数组去重:\n',c[idx])

#转化为虚数: [ 1.+2.j  3.+4.j  5.+6.j  7.+8.j  7.+8.j  3.+4.j  1.+2.j]
#虚数去重后: [ 1.+2.j  3.+4.j  5.+6.j  7.+8.j]
#(array([ 1.+2.j,  3.+4.j,  5.+6.j,  7.+8.j]), array([0, 1, 2, 3], dtype=int64))
#二维数组去重:
#[[1 2]
#[3 4]
#[5 6]
#[7 8]]
print('去重方案2:\n',np.array(list(set([tuple(t) for t in c]))))
#去重方案2:
#[[1 2]
#[3 4]
#[5 6]
#[7 8]]
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值