Numpy用法(二)

文章发布时间:

最后更新时间:

文章总字数:
1.9k

预计阅读时间:
8 分钟

一.数组变维

1.1 reshape

reshape() 可以改变数组维度,但是返回的是一个新的数组,原数组的形状不会被修改。reshape后产生的新数组是原数组的一个视图,即它与原数组共享相同的数据,但可以有不同的形状或维度,且对视图的修改会直接影响原数组数据。

元素总数必须匹配:新形状中的元素总数必须与原数组中的元素总数相同,即(2,3)可以改成(3,2)而不能是(2,2)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import numpy as np

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

# 进行变维
b = a.reshape(3,2)

print(a)

# 换个行
print()


print(b)

结果:

1
2
3
4
5
6
[[1 2 3]
[4 5 6]]

[[1 2]
[3 4]
[5 6]]
1
2
3
4
5
6
7
8
9
10
11
# 试试将一维变成三维
import numpy as np

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

b = a.reshape(2,2,3)


print(a)
print()
print(b)

结果:

1
2
3
4
5
6
7
[ 1  2  3  4  5  6  7  8  9 10 11 12]

[[[ 1 2 3]
[ 4 5 6]]

[[ 7 8 9]
[10 11 12]]]

事实确实证明,只要两个形状里元素个数一致,形状怎么变,或者改变维度也可以。

-1 作为占位符:

你可以使用-1作为占位符,让 numpy 自动计算某个维度的大小。也就是-1在哪,就会自动改变那个行或列的大小以适配新的形状。

1
2
3
4
5
6
import numpy as np

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

b = a.reshape(3,-1)
print(b)

结果:

1
2
3
[[1 2]
[3 4]
[5 6]]

1.2 flat

返回一个一维迭代器,用于遍历数组中的所有元素。

1
2
3
4
5
6
7
8
import numpy as np

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

# 创建flat
b = a.flat
for i in b:
print(i)

结果:

1
2
3
4
5
6
1
2
3
4
5
6

1.3 flatten()

用于将多维数组转换为一维数组,返回的也是一个副本

ndarray.flatten(order='C')

  • ‘C’:按行优先顺序展开(默认)。

  • ‘F’:按列优先顺序展开。

  • ‘A’:如果原数组是 Fortran 连续的,则按列优先顺序展开;否则按行优先顺序展开。

  • ‘K’:按元素在内存中的顺序展开。

1
2
3
4
5
6
import numpy as np

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

b = a.flatten()
print(b)

结果:

1
[1 2 3 4 5 6]

1.4 ravel()

ndarray.ravel()

  • ‘C’:按行优先顺序展开(默认)。

  • ‘F’:按列优先顺序展开。

  • ‘A’:如果原数组是 Fortran 连续的,则按列优先顺序展开;否则按行优先顺序展开。

  • ‘K’:按元素在内存中的顺序展开。

其用于将多维数组转换为一维数组。与 flatten() 不同,ravel() 返回的是原数组的一个视图(view),而不是副本。因此,对返回的数组进行修改会影响原数组数据。

1
2
3
4
5
6
7
8
9
import numpy as np

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

b = a.ravel()
print(b)

b[0] = 100
print(a)

结果:

1
2
3
[1 2 3 4 5 6]
[[100 2 3]
[ 4 5 6]]

二.数组转置

| transpose | 将数组的维度值进行对换,比如二维数组维度(2,4)使用该方法后为(4,2) |
| ndarray.T | 与 transpose 方法相同 |

1
2
3
4
5
6
7
8
9
10
11
12
13
import numpy as np 
# x.T
a = np.arange(1,7).reshape(2,3)
print(a)

print()

print(a.T)

print()

# transpose()
print(np.transpose(a))

结果:

1
2
3
4
5
6
7
8
9
10
[[1 2 3]
[4 5 6]]

[[1 4]
[2 5]
[3 6]]

[[1 4]
[2 5]
[3 6]]

如果是2维以上的数组怎么转置呢?来看看:

1
2
3
4
5
6
7
8
9
10
11
12
13
import numpy as np 

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

# 四维数组
x.shape = (4,2,1,1)
print(x.shape)

print()

# transpose()
b = np.transpose(x)
print(b.shape)

结果:

1
2
3
(4, 2, 1, 1)

(1, 1, 2, 4)

可见就是把原来的形状反向输出。

三.升维和降维

多维数组(也称为 ndarray)的维度(或轴)是从外向内编号的。这意味着最外层的维度是轴0,然后是轴1,依此类推。

比如[ [ [ 1,2,3 ] ] ],最外面那层括号就是轴0,也就是最外层维度,该形状为(1,1,3)。维度长度分别为1,1,3。

| expand_dims(arr, axis) | arr:输入数组、axis:新轴插入的位置 | 在指定位置插入新的轴(相对于结果数组而言),从而扩展数组的维度 |
| squeeze(arr, axis) | axis:取值为整数或整数元组,用于指定需要删除的维度所在轴,指定的维度值必须为 1 ,否则将会报错,若为 None,则删除数组维度中所有为 1 的项 |删除数组中维度为 1 的项 |

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
import numpy as np
# 升维
a = np.array([1, 2, 3])
print(a.shape)

# 在轴0即 行上升维
b = np.expand_dims(a, axis=0)
print(b.shape)
print(b)


# 换个行
print()

# 在轴1即 列上升维
c = np.expand_dims(a, axis=1)
print(c.shape)
print(c)


# 换个行
print()

# 在原来轴1的位置上再升维
d = np.expand_dims(c, axis=1)
print(d.shape)
print(d)
# 注意,这里的1是加在(3,1)中间的

结果:

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

(3, 1)
[[1]
[2]
[3]]

(3, 1, 1)
[[[1]]

[[2]]

[[3]]]

你可以这样理解,按轴0升维是在最外层加上俩括号,按最大轴升维是在最内层元素两旁加上俩括号。

1
2
3
4
5
6
7
import numpy as np
# 降维
a = np.array([[[1, 2, 3]]])

# 删除最外层维度即最外层括号
b = np.squeeze(a, axis = 0)
print(b)

结果:

1
[[1 2 3]]
1
2
3
4
5
6
7
# 降维不了的情况,即要删除的维度长度不为1

a = np.array([1, 2, 3])
a.shape = (3, 1)
print(a)

np.squeeze(a,axis=0)

结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[[1]
[2]
[3]]

---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
Cell In[31], line 7
4 a.shape = (3, 1)
5 print(a)
----> 7 np.squeeze(a,axis=0)

File c:\Users\Clocky7\anaconda3\envs\pyhon-numpy\lib\site-packages\numpy\core\fromnumeric.py:1558, in squeeze(a, axis)
1556 return squeeze()
1557 else:
-> 1558 return squeeze(axis=axis)

ValueError: cannot select an axis to squeeze out which has size not equal to one

四.连接数组

| hstack(tup) | tup:可以是元组,列表,或者numpy数组返回结果为numpy的数组 | 按水平顺序堆叠序列中数组(列方向) |
| vstack(tup) | tup:可以是元组,列表,或者numpy数组返回结果为numpy的数组 | 按垂直顺序堆叠序列中数组(行方向) |

其上分别要求行数一致和列数一致,而且 vstack()hstack() 要求堆叠的数组在某些维度上具有相同的形状,否则无法堆叠。

1
2
3
4
5
6
7
8
9
import numpy
# hstack
a = numpy.array([1, 2, 3])
b = numpy.array([4, 5, 6])
print(np.hstack((a, b)))


# vstack
print(np.vstack((a, b)))

结果:

1
2
3
[1 2 3 4 5 6]
[[1 2 3]
[4 5 6]]

五.分割数组

| hsplit(ary, indices_or_sections) | ary:原数组 indices_or_sections:按列分割的索引位置 | 数组水平分割为多个子数组(按列) |
| vsplit(ary, indices_or_sections) | ary:原数组 indices_or_sections:按行分割的索引位置 | 数组垂直分割为多个子数组(按行) |

1
2
3
4
5
6
import numpy as np

a = np.array([[1, 2, 3,4], [ 5,6,7,8]])
# 注意这里的索引位置要加括号哦
b = np.hsplit(a,[1,3])
print(b)

结果:

1
2
3
4
[array([[1],
[5]]), array([[2, 3],
[6, 7]]), array([[4],
[8]])]

六.矩阵运算

6.1 np.dot

是一个通用的点积函数,适用于多种维度的数组。

  • 对于二维数组(矩阵),np.dot 等价于矩阵乘法。

  • 对于一维数组(向量),np.dot 计算的是向量的点积(内积)。

1
2
3
4
# 点积
a = numpy.array([1, 2, 3])
b = numpy.array([4, 5, 6])
print(numpy.dot(a, b))

结果:

1
32
1
2
3
4
# 矩阵乘法
a = numpy.array([[1, 2],[3, 4]])
b = numpy.array([[5, 6],[7, 8]])
print(numpy.dot(a, b))

结果:

1
2
[[19 22]
[43 50]]

注意:矩阵 用 * 相乘是逐元素(element-wise)乘法,而不是线性代数中的矩阵乘法。也就是对应元素相乘,同样需要广播机制。

6.2 np.matmul

是专门用于矩阵乘法的函数,适用于二维及更高维度的数组。np.dot是通用点积函数,np.matmul专门用于矩阵运算,性能要好于np.dot

6.3 np.linalg.det

求方阵行列式。

1
2
3
4
import numpy as np

a = np.array([[1, 2], [3, 4]])
print(np.linalg.det(a))

结果:

1
-2.0000000000000004