python矩阵所有元素取整_NUMPY矩阵处理

1.1. NumPy ndarray:多维数组对象

NumPy的一个关键特性是它的N维数组对象(ndarray),它在Python中是一个大型数据集的快速的,灵活的容器。数组使你能够在整个数据块上进行数学运算,且与对应的纯量元素间操作有相似的语法:

In [8]: data

Out[8]:

array([[ 0.9526, -0.246 , -0.8856],

[ 0.5639, 0.2379, 0.9104]])

In [9]: data * 10 In [10]: data + data

Out[9]: Out[10]:

array([[ 9.5256, -2.4601, -8.8565], array([[ 1.9051, -0.492 , -1.7713],

[ 5.6385, 2.3794, 9.104 ]]) [ 1.1277, 0.4759, 1.8208]])

ndarray是一个同种类数据的多维容器,也就是说,它的所有元素都是同类型的。每一个数组都有一个 shape (表示它每一维大小的元组)和dtype (一个描述数组数据类型的对象):

In [11]: data.shape

Out[11]: (2, 3)

In [12]: data.dtype

Out[12]: dtype(‘float64’)

本章将介绍ndarray的基础知识,并足以应对本书剩下的部分。虽然对于许多的数据分析应用来说不必要对NumPy有深入的理解,但是精通面向数组编程和思想是成为一名科学的Python大师的关键一步。

每当你在正文中看见“array”, “NumPy array”, or “ndarray”,除了很少的列外之外,它们都指的是同一个东西:ndarray对象。

1.1.1. 创建ndarray

最简单的创建数组的方式是使用 array 函数。它接受任何数组对象(包括其它数组),产生一个包含所传递的数据的新NumPy数组。例如,列表就是一个很好的用于转换的候选:

In [13]: data1 = [6, 7.5, 8, 0, 1]

In [14]: arr1 = np.array(data1)

In [15]: arr1

Out[15]: array([ 6. , 7.5, 8. , 0. , 1. ])

嵌套序列,如等长列表的列表,将会转化为一个多维数组:

In [16]: data2 = [[1, 2, 3, 4], [5, 6, 7, 8]]

In [17]: arr2 = np.array(data2)

In [18]: arr2

Out[18]:

array([[1, 2, 3, 4],

[5, 6, 7, 8]])

In [19]: arr2.ndim

Out[19]: 2

In [20]: arr2.shape

Out[20]: (2, 4)

除非明确指定(在此以后会更多), np.array 试图推断一个好的数据类型给它所创建的数组。数据类型存储在一个特定的 dtype 的对象中;例如,在上面的两个例子中,我们有:

In [21]: arr1.dtype

Out[21]: dtype(‘float64’)

In [22]: arr2.dtype

Out[22]: dtype(‘int64’)

除 np.array 之外,还有许多函数来创建新的数组。例如, zeros 和 ones 使用给定的长度或形状分别的创建0‘s 和 1‘s数组。

empty 会创建一个没有使用特定值来初始化的数组。给这些方法传递一个元组作为形状来创建高维数组:

In [23]: np.zeros(10)

Out[23]: array([ 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])

In [24]: np.zeros((3, 6))

Out[24]:

array([[ 0., 0., 0., 0., 0., 0.],

[ 0., 0., 0., 0., 0., 0.],

[ 0., 0., 0., 0., 0., 0.]])

In [25]: np.empty((2, 3, 2))

Out[25]:

array([[[ 4.94065646e-324, 4.94065646e-324],

[ 3.87491056e-297, 2.46845796e-130],

[ 4.94065646e-324, 4.94065646e-324]],

[[ 1.90723115e+083, 5.73293533e-053],

[ -2.33568637e+124, -6.70608105e-012],

[ 4.42786966e+160, 1.27100354e+025]]])

假定 np.array 会返回一个全零的数组是不安全的。在许多情况下,如前所示,它将返回未初始化的垃圾值。

arange 是Python内建 range 函数的数组版本:

In [26]: np.arange(15)

Out[26]: array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14])

表格4-1 是一个用于构建数组的标准函数的清单。

数组构建函数

函数

描述

array

转换输入数据(列表,数组或其它序列类型)到一个ndarray,可以推断一个dtype或明确的设置一个dtype。默认拷贝输入数据。

asarray

转换输入为一个ndarray,当输入已经是一个ndarray时就不拷贝。

arange

同内建的range函数,但不返回列表而是一个ndarray

ones, ones_like

根据提供的shape和dtype产生一个全1的数组。ones_like使用另一歌数组为入参,产生一个shape和dtype都相同的数组。

zeros, zeros_like

同ones和ones_like,但是生成全0的数组

empty, enpty_like

通过分配新内存来构造新的数组,但不同与ones 和 zeros,不初始任何值。

eye, identity

生成一个NxN的单位方阵(对角线上为1,其它地方为0)

1.1.2. ndarray的数据类型

数据类型或dtype是一个特别的对象,保存了ndarray如何解释一块内存为特定类型数据的信息:

In [27]: arr1 = np.array([1, 2, 3], dtype=np.float64)

In [28]: arr2 = np.array([1, 2, 3], dtype=np.int32)

In [29]: arr1.dtype

Out[29]: dtype(‘float64’)

In [30]: arr2.dtype

Out[30]: dtype(‘int32’)

Dtypes是使NumPy如此强大和灵活的一部分。在大多数情况下,它们直接映射到底层的机器表示,这是的很容易地读取和写入二进制流到磁盘上,也能链接低级语言,如C或Fortran编写的代码。数值表示的dtypes以相同的方式命名:一个类型名,如folt 或

int ,后面跟着一个表示数字有多少位的数字。一个标准的双精度浮点值(它是Python的

float 对象的底层表示)占据8字节或64位。因此,这一类型在NumPy中被认为是

float64 。见 表格4-2 是一个NumPy支持的全部数据类型的清单。

不要为了记忆NumPy的dtypes而烦恼,尤其你是一个新用户。通常只需要关心你所处理数据的普通类型(浮点、复数、整形、布尔型、字符窜或一般的Python对象)。当你需要更多的控制数据如何存储到内存和磁盘,特别是大的数据集,知道你所控制的存储类型是很好的。

NumPy数据类型

类型

类型码

描述

类型

类型码

描述

int8, uint8

i1, u1

有符号和无符号8位(1字节)整数类型

int16, uint16

i2, u2

有符号和无符号16位整数类型

int32, uint32

i4, u4

有符号和无符号32位整数类型

int64, uint64

i8, u8

有符号和无符号64位整数类型

float16

f2

半精度浮点类型

float32

f4 or f

标准精度浮点。与C的 float 兼容

float64, float128

f8 or d

标准双精度浮点。与C的 double 和Python 的folat 对象兼容

float128

f16 or g

扩展精度浮点

complex64, complex128, complex256

c8, c16, c32

分别使用两个32,64,128位浮点表示的复数

bool

?

布尔值,存储 True 和 False

object

O

Python对象类型

string_

S

定长字符窜类型(每字符一字节)。例如,为了生成长度为10的字符窜,使用 ‘S10’

unicode_

f16 or g

扩展精度浮点(字节书依赖平台)。同 string_ 有相同的语义规范(例如:“U10“ )

你可以使用ndarray的 astype 方法显示的把一个数组的dtype转换或 投射 到另外的类型:

In [31]: arr = np.array([1, 2, 3, 4, 5])

In [32]: arr.dtype

Out[32]: dtype(‘int64’)

In [33]: float_arr = arr.astype(np.float64)

In [34]: float_arr.dtype

Out[34]: dtype(‘float64’)

在这个例子中,整形被转换到浮点型。如果把浮点数转换到整形dtype,小数部分将会被截断:

In [35]: arr = np.array([3.7, -1.2, -2.6, 0.5, 12.9, 10.1])

In [36]: arr

Out[36]: array([ 3.7, -1.2, -2.6, 0.5, 12.9, 10.1])

In [37]: arr.astype(np.int32)

Out[37]: array([ 3, -1, -2, 0, 12, 10], dtype=int32)

你可能有一个字符窜数组表示的数字,可以使用 astype 把它们转换到数字的形式:

In [38]: numeric_strings = np.array([‘1.25’, ‘-9.6′, ’42’], dtype=np.string_)

In [39]: numeric_strings.astype(float)

Out[39]: array([ 1.25, -9.6 , 42. ])

如果因为某些原因(如一个字符窜不能转换到 float64 )转换失败了,将会引起一个 TypeError 。正如你所看见的,我有一些懒,使用float 而不是

np.float64 ;NumPy会足够聪明的把Python的类型对应到等价的dtypes。

你也可以使用dtype的另一个属性:

In [40]: int_array = np.arange(10)

In [41]: calibers = np.array([.22, .270, .357, .380, .44, .50], dtype=np.float64)

In [42]: int_array.astype(calibers.dtype)

Out[42]: array([ 0., 1., 2., 3., 4., 5., 6., 7., 8., 9.])

你也可以使用速记的类型码字符窜来指定一个dtype:

In [43]: empty_uint32 = np.empty(8, dtype=’u4′)

In [44]: empty_uint32

Out[44]:

array([ 0, 0, 65904672, 0, 64856792, 0,

39438163, 0], dtype=uint32)

调用 astype 总是会创建一个新的数组(原数据的拷贝),即使是新的dtype和原来的dtype相同。

值得牢记的是浮点数,如那些是 float64 和 float32 的数组,是唯一能够接近分数的。在复杂的计算中,可能会产生

浮点错误 ,计较时到了一定的小数位数时才有效。

1.1.3. 数组和纯量间的操作

数组非常重要,因为它们使你不使用循环就可以在数据上进行一系列操作。这通常被叫做矢量化。相同大小的数组间的算术运算,其操作作用在对应的元素上:

In [45]: arr = np.array([[1., 2., 3.], [4., 5., 6.]])

In [46]: arr

Out[46]:

array([[ 1., 2., 3.],

[ 4., 5., 6.]])

In [47]: arr * arr In [48]:arr – arr

Out[47]: Out[48]:

array([[ 1., 4., 9.], array([[ 0., 0., 0.],

[ 16., 25., 36.]]) [ 0., 0., 0.]])

纯量的算术操作正如你期望的一样,把操作值作用于每一个元素:

In [49]: 1 / arr In [50]: arr ** 0.5

Out[49]: Out[50]:

array([[ 1. , 0.5 , 0.3333], array([[ 1. , 1.4142, 1.7321],

[ 0.25 , 0.2 , 0.1667]]) [ 2. , 2.2361, 2.4495]])

在不同大小的数组见的操作被叫做 broadcasting ,将在第12章 详细讨论。深入的了解broadcasting在本书的多数地方是不必要的。

1.1.4. 基本的索引和切片

NumPy的索引是一个内容丰富的主题,因为有许多方法可以使你在你的数据中选取一个子集或单个元素。一维的数组很简单,表面上它们的行为类似于Python的列表:

In [51]: arr = np.arange(10)

In [52]: arr

Out[52]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

In [53]: arr[5]

Out[53]: 5

In [54]: arr[5:8]

Out[54]: array([5, 6, 7])

In [55]: arr[5:8] = 12

In [56]: arr

Out[56]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

如你所见,当你给一个切片赋一纯量值,如 arr[5:8]=

12 所示,该值被传送(或 传播 )到整个选择区域。与列表的第一个重要的区别是数组的切片在原来的数组上(不生成新的数组)。这意味着数据不会被拷贝,且对切片的任何修改都会影响源数组:

In [57]: arr_slice = arr[5:8]

In [58]: arr_slice[1] = 12345

In [59]: arr

Out[59]: array([ 0, 1, 2, 3, 4, 12, 12345, 12, 8, 9])

In [60]: arr_slice[:] = 64

In [61]: arr

Out[61]: array([ 0, 1, 2, 3, 4, 64, 64, 64, 8, 9])

如果你是使用NumPy的新手,这一点回事你感到惊讶,尤其当你使用过其它数组编程语言,它们非常热衷于拷贝数据。请记住,NumPy是设计用来处理大数据的情况,你可以想象如果NumPy坚持使用拷贝数据将会出现的性能和内存问题。

如果你想有数组切片的一个拷贝,你需要明显的拷贝数组;例如 arr[5:8].copy() 。

对于高维数组,你会有更多选项。在两维的数组,每一个索引的元素将不再是一个纯量,而是一个一维数组:

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

In [63]: arr2d[2]

Out[63]: array([7, 8, 9])

因此,单个元素可以递归的访问,但是这会做多一点的工作。不过,你可以使用一个逗号分隔的索引列表来选择单个元素。因此,下面的操作是等价的:

In [64]: arr2d[0][2]

Out[64]: 3

In [65]: arr2d[0, 2]

Out[65]: 3

见 NumPy数组的索引,是在二维数组上的索引图例。

《python矩阵所有元素取整_NUMPY矩阵处理》

NumPy数组的索引

在多维数组中,如果你省略了后面的索引,返回的对象将会是一个较低维的ndarray,它包括较高维度的所有数据。因此,在 2*2*3 的数组arr3d 中

In [66]: arr3d = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]])

In [67]: arr3d

Out[67]:

array([[[ 1, 2, 3],

[ 4, 5, 6]],

[[ 7, 8, 9],

[10, 11, 12]]])

arr3d[0] 是一个 2*3 的数组:

In [68]: arr3d[0]

Out[68]:

array([[1, 2, 3],

[4, 5, 6]])

纯量值和数组都可以给 arr3d[0] 赋值:

In [69]: old_values = arr3d[0].copy()

In [70]: arr3d[0] = 42

In [71]: arr3d

Out[71]:

array([[[42, 42, 42],

[42, 42, 42]],

[[ 7, 8, 9],

[10, 11, 12]]])

In [72]: arr3d[0] = old_values

In [73]: arr3d

Out[73]:

array([[[ 1, 2, 3],

[ 4, 5, 6]],

[[ 7, 8, 9],

[10, 11, 12]]])

类似的, arr3d[1, 0] 给你那些索引以 (1, 0) 开始的值,形成了一个1维数组:

In [74]: arr3d[1, 0]

Out[74]: array([7, 8, 9])

请注意,在所有的情况下,被选中的子节返回的数组总是数组视窗。

1.1.4.1. 带切片的索引

如同一维对象,例如Python的列表,ndarrys可以使用熟悉的语法来切片:

In [75]: arr[1:6]

Out[75]: array([ 1, 2, 3, 4, 64])

较高维的对象给你更多的选择,你可以切割一个或多个坐标坐标轴,并且可以混合整数。对上面的2维数组, arr2d ,对它的切片有些不同:

In [76]: arr2d In [77]: arr2d[:2]

Out[76]: Out[77]:

array([[1, 2, 3], array([[1, 2, 3],

[4, 5, 6], [4, 5, 6]])

[7, 8, 9]])

正如你所见,它沿着 0 坐标坐标轴(第一个坐标坐标轴)切片。因此,一个切片沿着一个坐标坐标轴向选择一个范围的元素。你可以传递多个切片,就像你传递多个索引一样:

In [78]: arr2d[:2, 1:]

Out[78]:

array([[2, 3],

[5, 6]])

象这样切片时,你得到的总是相同维数的数组视窗。通过混合整形索引和切片,你可以得到较低维的切片:

In [79]: arr2d[1, :2] In [80]: arr2d[2, :1]

Out[79]: array([4, 5]) Out[80]: array([7])

见 两维数组切片 图解。注意,一个单一的冒号意味着取整个坐标/坐标轴,因此,你可以只切割更高维的坐标轴,做法如下:

In [81]: arr2d[:, :1]

Out[81]:

array([[1],

[4],

[7]])

当然,给一个切片表达式赋值会对整个选择赋值:

In [82]: arr2d[:2, 1:] = 0

《python矩阵所有元素取整_NUMPY矩阵处理》

两维数组切片

1.1.5. 布尔索引

让我们来考虑一个例子,我们有一些数据在一个数组中和一个有重复名字的数组。我将会在这使用 numpy.random 中的 randn 函数来产生一些随机的正态分布的数据:

In [83]: names = np.array([‘Bob’, ‘Joe’, ‘Will’, ‘Bob’, ‘Will’, ‘Joe’, ‘Joe’])

In [84]: data = randn(7, 4)

In [85]: names

Out[85]:

array([‘Bob’, ‘Joe’, ‘Will’, ‘Bob’, ‘Will’, ‘Joe’, ‘Joe’],

dtype=’|S4′)

In [86]: data

Out[86]:

array([[-0.048 , 0.5433, -0.2349, 1.2792],

[-0.268 , 0.5465, 0.0939, -2.0445],

[-0.047 , -2.026 , 0.7719, 0.3103],

[ 2.1452, 0.8799, -0.0523, 0.0672],

[-1.0023, -0.1698, 1.1503, 1.7289],

[ 0.1913, 0.4544, 0.4519, 0.5535],

[ 0.5994, 0.8174, -0.9297, -1.2564]])

假设每一个名字都和 data 数组中的一行对应。如果我们想要选择与 ‘Bob’ 名字对应的所有行。象算术运算一样,数组的比较操作(例如== )也可以矢量化。因此,

names 和 Bob 字符窜的比较会产生一个布尔数组:

In [87]: names == ‘Bob’

Out[87]: array([ True, False, False, True, False, False, False], dtype=bool)

当索引数组时可以传递这一布尔数组:

In [88]: data[names == ‘Bob’]

Out[88]:

array([[-0.048 , 0.5433, -0.2349, 1.2792],

[ 2.1452, 0.8799, -0.0523, 0.0672]])

布尔数组必须和它索引的坐标轴的长度相同。你甚至可以把布尔数组和切片或整数(或者整数序列,关于这一点后面会更多介绍)混合和匹配起来:

In [89]: data[names == ‘Bob’, 2:]

Out[89]:

array([[-0.2349, 1.2792],

[-0.0523, 0.0672]])

In [90]: data[names == ‘Bob’, 3]

Out[90]: array([ 1.2792, 0.0672])

为了选择除了 ‘Bob’ 之外的所有东西,你可以使用 != 或用 – 对条件表达式取反:

In [91]: names != ‘Bob’

Out[91]: array([False, True, True, False, True, True, True], dtype=bool)

In [92]: data[-(names == ‘Bob’)]

Out[92]:

array([[-0.268 , 0.5465, 0.0939, -2.0445],

[-0.047 , -2.026 , 0.7719, 0.3103],

[-1.0023, -0.1698, 1.1503, 1.7289],

[ 0.1913, 0.4544, 0.4519, 0.5535],

[ 0.5994, 0.8174, -0.9297, -1.2564]])

使用布尔算术操作符如 & (and) 和 | (or)来结合多个布尔条件,下面是从三个名字中选取两个的操作:

In [93]: mask = (names == ‘Bob’) | (names == ‘Will’)

In [94]: mask

Out[94]: array([True, False, True, True, True, False, False], dtype=bool)

In [95]: data[mask]

Out[95]:

array([[-0.048 , 0.5433, -0.2349, 1.2792],

[-0.047 , -2.026 , 0.7719, 0.3103],

[ 2.1452, 0.8799, -0.0523, 0.0672],

[-1.0023, -0.1698, 1.1503, 1.7289]])

通过布尔索引从一个数组中选取数据 总是 会创建数据的一份拷贝,即使是返回的数组没有改变。

Python的 and 和 or 关键字不能与布尔数组一起工作。

通过布尔数组设置值工作于一种种常识性的方式。为了设置 data 中所有的负值为0,我们只需要:

In [96]: data[data < 0] = 0

In [97]: data

Out[97]:

array([[ 0. , 0.5433, 0. , 1.2792],

[ 0. , 0.5465, 0.0939, 0. ],

[ 0. , 0. , 0.7719, 0.3103],

[ 2.1452, 0.8799, 0. , 0.0672],

[ 0. , 0. , 1.1503, 1.7289],

[ 0.1913, 0.4544, 0.4519, 0.5535],

[ 0.5994, 0.8174, 0. , 0. ]])

使用一维布尔数组设置整行或列也非常简单:

In [98]: data[names != ‘Joe’] = 7

In [99]: data

Out[99]:

array([[ 7. , 7. , 7. , 7. ],

[ 0. , 0.5465, 0.0939, 0. ],

[ 7. , 7. , 7. , 7. ],

[ 7. , 7. , 7. , 7. ],

[ 7. , 7. , 7. , 7. ],

[ 0.1913, 0.4544, 0.4519, 0.5535],

[ 0.5994, 0.8174, 0. , 0. ]])

1.1.6. Fancy索引

Fancy 索引 是一个术语,被NumPy用来描述使用整形数组索引。假如我们有一个 8*4 的数组:

In [100]: arr = np.empty((8, 4))

In [101]: for i in range(8):

…..: arr[i] = i

In [102]: arr

Out[102]:

array([[ 0., 0., 0., 0.],

[ 1., 1., 1., 1.],

[ 2., 2., 2., 2.],

[ 3., 3., 3., 3.],

[ 4., 4., 4., 4.],

[ 5., 5., 5., 5.],

[ 6., 6., 6., 6.],

[ 7., 7., 7., 7.]])

为了选出一个有特定顺序行的子集,你可以传递一个列表或整形ndarray来指定想要的顺序:

In [103]: arr[[4, 3, 0, 6]]

Out[103]:

array([[ 4., 4., 4., 4.],

[ 3., 3., 3., 3.],

[ 0., 0., 0., 0.],

[ 6., 6., 6., 6.]])

很庆幸这个代码做了你所期望的!使用负的索引从结尾选择行:

In [104]: arr[[-3, -5, -7]]

Out[104]:

array([[ 5., 5., 5., 5.],

[ 3., 3., 3., 3.],

[ 1., 1., 1., 1.]])

传递多个索引数组有些微的不同;它选取一个一维数组,元素对应与索引的每一个元组:

# 关于reshape在第12章会跟多介绍

In [105]: arr = np.arange(32).reshape((8, 4))

In [106]: arr

Out[106]:

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]])

In [107]: arr[[1, 5, 7, 2], [0, 3, 1, 2]]

Out[107]: array([ 4, 23, 29, 10])

花一点儿时间来看看刚刚发生了什么:元素 (1, 0), (5, 3), (7, 1), 和(2, 2)被选择了。 fancy索引的行为与一些用户(也包括我自己)可能期望的有所不同,它因该是一个矩形区域,由选取的矩形的行和列组成。这里有一个方法来得到它:

In [108]: arr[[1, 5, 7, 2]][:, [0, 3, 1, 2]]

Out[108]:

array([[ 4, 7, 5, 6],

[20, 23, 21, 22],

[28, 31, 29, 30],

[ 8, 11, 9, 10]])

另一种方法是使用 np.ix_ 函数,将两个以为整形数组转换为位标,来选取一个正方形区域:

In [109]: arr[np.ix_([1, 5, 7, 2], [0, 3, 1, 2])]

Out[109]:

array([[ 4, 7, 5, 6],

[20, 23, 21, 22],

[28, 31, 29, 30],

[ 8, 11, 9, 10]])

注意,fancy索引,不像切片,它总是拷贝数据到一个新的数组。

1.1.7. 转置数组和交换坐标轴

转置是一种特殊形式的变形,类似的它会返回基础数据的一个视窗,而不会拷贝任何东西。数组有 transpose 方法和专门的 T 属性:

In [110]: arr = np.arange(15).reshape((3, 5))

In [111]: arr In [112]: arr.T

Out[111]: Out[112]:

array([[ 0, 1, 2, 3, 4], array([[ 0, 5, 10],

[ 5, 6, 7, 8, 9], [ 1, 6, 11],

[10, 11, 12, 13, 14]]) [ 2, 7, 12],

[ 3, 8, 13],

[ 4, 9, 14]])

当进行矩阵运算时,你常常会这样做,像下面的例子一样,使用 np.dot 计算内部矩阵来产生 XTX` :

In [113]: arr = np.random.randn(6, 3)

In [114]: np.dot(arr.T, arr)

Out[114]:

array([[ 2.584 , 1.8753, 0.8888],

[ 1.8753, 6.6636, 0.3884],

[ 0.8888, 0.3884, 3.9781]])

对于更高维的数组, transpose 接受用于转置的坐标轴的号码的一个元组(for extra mind bending):

In [115]: arr = np.arange(16).reshape((2, 2, 4))

In [116]: arr

Out[116]:

array([[[ 0, 1, 2, 3],

[ 4, 5, 6, 7]],

[[ 8, 9, 10, 11],

[12, 13, 14, 15]]])

In [117]: arr.transpose((1, 0, 2))

Out[117]:

array([[[ 0, 1, 2, 3],

[ 8, 9, 10, 11]],

[[ 4, 5, 6, 7],

[12, 13, 14, 15]]])

使用 .T 的转置,仅仅是交换坐标轴的一个特殊的情况:

In [118]: arr In [119]: arr.swapaxes(1, 2)

Out[118]: Out[119]:

array([[[ 0, 1, 2, 3], array([[[ 0, 4],

[ 4, 5, 6, 7]], [ 1, 5],

[ 2, 6],

[[ 8, 9, 10, 11], [ 3, 7]],

[12, 13, 14, 15]]])

[[ 8, 12],

[ 9, 13],

[10, 14],

[11, 15]]])

类似的 swapaxes 返回在数据上的一个视窗,而不进行拷贝。

    原文作者:又见山人
    原文地址: https://blog.csdn.net/weixin_42523389/article/details/112019177
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞