numpy(六)——数组的变形,转置与换轴

本文主要介绍numpy数组的变形、转置与换轴操作。变形有reshape和resize两种方法,二者使用方式和结果有差异;转置可通过顶层的transpose函数和.T属性操作,结果一致;换轴可使用newaxis增轴和swapaxes换轴,增轴取决于np.newaxis位置,换轴接收轴编号参数,这些操作结果多为原数组视图。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

numpy(六)——数组的变形,转置与换轴

import numpy as np
  • 变形

numpy中的数组变形有reshape和resize两种方法,在第一篇中已经略有涉及。此二者作用相差不大,不过至细微处亦有颇多不同,故于此详加讲述,希能澄清。

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

首先,reshape和resize都有两种使用方法,一种是作为numpy的顶层函数使用,一种是作为ndarray的对象方法使用。

arr_reshape_1 = np.reshape(arr_shape,(5,4))
arr_reshape_1
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [12, 13, 14, 15],
       [16, 17, 18, 19]])
arr_reshape_1[0][0] = 999
print(arr_reshape_1)
print("--"*10)
print(arr_shape)
[[999   1   2   3]
 [  4   5   6   7]
 [  8   9  10  11]
 [ 12  13  14  15]
 [ 16  17  18  19]]
--------------------
[[999   1   2   3   4]
 [  5   6   7   8   9]
 [ 10  11  12  13  14]
 [ 15  16  17  18  19]]
arr_reshape_2 = arr_shape.reshape(2,10)
arr_reshape_2
array([[999,   1,   2,   3,   4,   5,   6,   7,   8,   9],
       [ 10,  11,  12,  13,  14,  15,  16,  17,  18,  19]])
arr_reshape_2[0][1] = 999
print(arr_reshape_2)
print("--"*10)
print(arr_shape)
[[999 999   2   3   4   5   6   7   8   9]
 [ 10  11  12  13  14  15  16  17  18  19]]
--------------------
[[999 999   2   3   4]
 [  5   6   7   8   9]
 [ 10  11  12  13  14]
 [ 15  16  17  18  19]]
  • 可见,无论是使用np顶层函数还是ndarray对象方法,这两种使用方法的结果是完全一致的,那就是:返回一个原数组的视图

我们再来看resize方法

arr_shape_1 = np.arange(20).reshape(4,5)
arr_shape_1
array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14],
       [15, 16, 17, 18, 19]])
arr_resize_1 = np.resize(arr_shape_1,(5,4))
arr_resize_1
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [12, 13, 14, 15],
       [16, 17, 18, 19]])
arr_shape_1
array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14],
       [15, 16, 17, 18, 19]])
arr_resize_1[0][0] = 999
print(arr_resize_1)
print("--"*10)
print(arr_shape_1)
[[999   1   2   3]
 [  4   5   6   7]
 [  8   9  10  11]
 [ 12  13  14  15]
 [ 16  17  18  19]]
--------------------
[[ 0  1  2  3  4]
 [ 5  6  7  8  9]
 [10 11 12 13 14]
 [15 16 17 18 19]]
arr_resize_2 = arr_shape_1.resize(2,10)
print(type(arr_resize_2))
<class 'NoneType'>
arr_shape_1
array([[ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14, 15, 16, 17, 18, 19]])
  • 可见,当使用resize改变数组的形状时,情况与reshape甚有不同:
    • 作为顶层函数的resize,会返回换一个新的数组对象,并且这个对象不是原数组的视图,而是一个独立的副本
    • 作为对象方法的resize,不回返回新对象,而是原地修改原数组

resize方法另有一个神奇的特点值得注意:

arr = np.arange(12).reshape(3,4)
arr
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
 np.resize(np.arange(20),(5,5))
array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14],
       [15, 16, 17, 18, 19],
       [ 0,  1,  2,  3,  4]])
 np.resize(np.arange(20),(3,4))
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
  • 可以看出,当使用顶层函数方式的resize时,哪怕resize中传入的形状与需要被变形的数组的长度不一致,resize函数也可以自动适应,多退少补,非常的人性化,想报错都难
  • 但是作为对象方法的ndarray和reshape,则是不能进行这样子的自动适应的,会报错
arr = np.arange(12).reshape(3,4)
arr
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
arr.resize(4,4)
---------------------------------------------------------------------------

ValueError                                Traceback (most recent call last)

<ipython-input-33-ca80ab1e27b3> in <module>
----> 1 arr.resize(4,4)


ValueError: cannot resize this array: it does not own its data
arr.reshape(4,4)
---------------------------------------------------------------------------

ValueError                                Traceback (most recent call last)

<ipython-input-34-966f28412ea6> in <module>
----> 1 arr.reshape(4,4)


ValueError: cannot reshape array of size 12 into shape (4,4)
np.reshape(arr,(4,4))
---------------------------------------------------------------------------

ValueError                                Traceback (most recent call last)

<ipython-input-35-67e91a25795c> in <module>
----> 1 np.reshape(arr,(4,4))


~\AppData\Local\conda\conda\envs\DataScience\lib\site-packages\numpy\core\fromnumeric.py in reshape(a, newshape, order)
    230            [5, 6]])
    231     """
--> 232     return _wrapfunc(a, 'reshape', newshape, order=order)
    233 
    234 


~\AppData\Local\conda\conda\envs\DataScience\lib\site-packages\numpy\core\fromnumeric.py in _wrapfunc(obj, method, *args, **kwds)
     55 def _wrapfunc(obj, method, *args, **kwds):
     56     try:
---> 57         return getattr(obj, method)(*args, **kwds)
     58 
     59     # An AttributeError occurs if the object does not have


ValueError: cannot reshape array of size 12 into shape (4,4)
  • 转置

arr_trans = np.arange(20).reshape(4,5)
arr_trans
array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14],
       [15, 16, 17, 18, 19]])
arr_T = arr_trans.T
arr_T
array([[ 0,  5, 10, 15],
       [ 1,  6, 11, 16],
       [ 2,  7, 12, 17],
       [ 3,  8, 13, 18],
       [ 4,  9, 14, 19]])
arr_T[0][0] = 999
print(arr_trans)
print("--"*10)
print(arr_T)
[[999   1   2   3   4]
 [  5   6   7   8   9]
 [ 10  11  12  13  14]
 [ 15  16  17  18  19]]
--------------------
[[999   5  10  15]
 [  1   6  11  16]
 [  2   7  12  17]
 [  3   8  13  18]
 [  4   9  14  19]]
arr_t = np.transpose(arr_trans)
arr_t
array([[999,   5,  10,  15],
       [  1,   6,  11,  16],
       [  2,   7,  12,  17],
       [  3,   8,  13,  18],
       [  4,   9,  14,  19]])
arr_t[0][1] = 999
print(arr_t)
print("--"*10)
print(arr_T)
print("--"*10)
print(arr_trans)
[[999 999  10  15]
 [  1   6  11  16]
 [  2   7  12  17]
 [  3   8  13  18]
 [  4   9  14  19]]
--------------------
[[999 999  10  15]
 [  1   6  11  16]
 [  2   7  12  17]
 [  3   8  13  18]
 [  4   9  14  19]]
--------------------
[[999   1   2   3   4]
 [999   6   7   8   9]
 [ 10  11  12  13  14]
 [ 15  16  17  18  19]]
  • 可以看到,数组的转置也可以有顶层的transpose函数和.T属性这两种方式进行操作。不过庆幸的是,这两种方法的结果完全一致:返回的是原数组的视图(所以你再也不必像记忆resize方法那样搞得自己精神分裂了)

  • 换轴

  • 使用newaxis增轴《Python数据科学手册》P60

使用np.newaxis属性可以改变原数组的形状并且增加原数组的维度

arr_axis = np.arange(12).reshape(3,4)
arr_axis
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
arr_newAxis_1 = arr_axis[:,np.newaxis,:]
print(arr_newAxis_1)
print("--"*10)
print(arr_newAxis_1.shape)
[[[ 0  1  2  3]]

 [[ 4  5  6  7]]

 [[ 8  9 10 11]]]
--------------------
(3, 1, 4)
arr_newAxis_0 = arr_axis[np.newaxis,:,:]
print(arr_newAxis_0)
print("--"*10)
print(arr_newAxis_0.shape)
[[[ 0  1  2  3]
  [ 4  5  6  7]
  [ 8  9 10 11]]]
--------------------
(1, 3, 4)
arr_newAxis_2 = arr_axis[:,:,np.newaxis]
print(arr_newAxis_2)
print("--"*10)
print(arr_newAxis_2.shape)
[[[ 0]
  [ 1]
  [ 2]
  [ 3]]

 [[ 4]
  [ 5]
  [ 6]
  [ 7]]

 [[ 8]
  [ 9]
  [10]
  [11]]]
--------------------
(3, 4, 1)
  • 可见,增轴后的数组的形状如何,其实取决于np.newaxis的位置
arr_newAxis_0[0][0][0] = 999
print(arr_newAxis_0)
print("--"*10)
print(arr_newAxis_1)
print("--"*10)
print(arr_newAxis_2)
print("--"*10)
print(arr_axis)
[[[999   1   2   3]
  [  4   5   6   7]
  [  8   9  10  11]]]
--------------------
[[[999   1   2   3]]

 [[  4   5   6   7]]

 [[  8   9  10  11]]]
--------------------
[[[999]
  [  1]
  [  2]
  [  3]]

 [[  4]
  [  5]
  [  6]
  [  7]]

 [[  8]
  [  9]
  [ 10]
  [ 11]]]
--------------------
[[999   1   2   3]
 [  4   5   6   7]
 [  8   9  10  11]]
  • 可见,使用newaxis增轴后的结果,也是原数组的视图

  • 使用swapaxes换轴《利用Python进行数据分析 第二版》P105

该方法接收一对轴编号作为参数,并且对轴进行调整用于重组数据

arr_swap = np.arange(18).reshape(2,3,3)
arr_swap
array([[[ 0,  1,  2],
        [ 3,  4,  5],
        [ 6,  7,  8]],

       [[ 9, 10, 11],
        [12, 13, 14],
        [15, 16, 17]]])
arr_swap_1 = arr_swap.swapaxes(0,1)
arr_swap_1
array([[[ 0,  1,  2],
        [ 9, 10, 11]],

       [[ 3,  4,  5],
        [12, 13, 14]],

       [[ 6,  7,  8],
        [15, 16, 17]]])
print(arr_swap_1.shape)
print(arr_swap.shape)
(3, 2, 3)
(2, 3, 3)
  • 轴编号就是数组形状元组的索引。因此,交换0,1的轴编号,就是将数组形状从323变成233
arr_swap_1[0][0][0] = 999
print(arr_swap)
print("--"*10)
print(arr_swap_1)
[[[999   1   2]
  [  3   4   5]
  [  6   7   8]]

 [[  9  10  11]
  [ 12  13  14]
  [ 15  16  17]]]
--------------------
[[[999   1   2]
  [  9  10  11]]

 [[  3   4   5]
  [ 12  13  14]]

 [[  6   7   8]
  [ 15  16  17]]]
  • 可见,使用swapaxes换轴后,结果还是原数组的视图
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值