参见:https://numpy.org/devdocs/user/quickstart.html#universal-functions
Numpy介绍与Python列表的区别
Numpy是Python中科学计算的基础包,提供多维数组对象、各种派送对象及一系列基本操作。ndarray是其中的基本对象。
区别:
- Numpy数组在创建时具有固定的大小,修改一个Numpy数组的大小将会创建一个新的数组并删除原来的数组(小部分操作会直接修改原数组)。
- Numpy数组中的元素都必须具有相同的数组类型,因此在内存中的大小也想通。例外:可以拥有(Python,包括 NumPy)对象的数组,从而允许不同大小元素的数组。
ndarray的基本属性
import numpy as np
a = np.arange(15).reshape(3, 5)
########
print("维度属性:"+str(a.ndim))
print("形状属性:"+str(a.shape))
print("大小属性:"+str(a.size))
print("元素类型:"+str(a.dtype))
print("元素大小:"+str(a.itemsize))
'''
维度属性:2
形状属性:(3, 5)
大小属性:15
元素类型:int32
元素大小:4
'''
创建ndarray
import numpy as np
from numpy import pi
# 将已知列表/元组直接转换为ndarray
# a = np.array([2, 3, 4])
a = np.array((2, 3, 4))
print("1")
print(a)
# 在创建时显式地指定类型
a = np.array([[1, 2], [3, 4]], dtype=complex)
print("2")
print(a)
# 创建大小已知但内容未知的ndarray
np.zeros((3, 4))
np.ones((2, 3, 4), dtype=np.int16)
np.empty((2, 3))
# 以步进的方式在选定范围内创建ndarray,默认开头为0,步长为1
a = np.arange(0, 2, 0.3)
print("3")
print(a)
# 当步进的元素类型是浮点型时,由于精度有限,建议用linspace
a = np.linspace(0, 2*pi, 100)
print("4")
print(a)
'''
1
[2 3 4]
2
[[1.+0.j 2.+0.j]
[3.+0.j 4.+0.j]]
3
[0. 0.3 0.6 0.9 1.2 1.5 1.8]
4
[0. 0.06346652 0.12693304 0.19039955 0.25386607 0.31733259
0.38079911 0.44426563 0.50773215 0.57119866 0.63466518 0.6981317
0.76159822 0.82506474 0.88853126 0.95199777 1.01546429 1.07893081
1.14239733 1.20586385 1.26933037 1.33279688 1.3962634 1.45972992
1.52319644 1.58666296 1.65012947 1.71359599 1.77706251 1.84052903
1.90399555 1.96746207 2.03092858 2.0943951 2.15786162 2.22132814
2.28479466 2.34826118 2.41172769 2.47519421 2.53866073 2.60212725
2.66559377 2.72906028 2.7925268 2.85599332 2.91945984 2.98292636
3.04639288 3.10985939 3.17332591 3.23679243 3.30025895 3.36372547
3.42719199 3.4906585 3.55412502 3.61759154 3.68105806 3.74452458
3.8079911 3.87145761 3.93492413 3.99839065 4.06185717 4.12532369
4.1887902 4.25225672 4.31572324 4.37918976 4.44265628 4.5061228
4.56958931 4.63305583 4.69652235 4.75998887 4.82345539 4.88692191
4.95038842 5.01385494 5.07732146 5.14078798 5.2042545 5.26772102
5.33118753 5.39465405 5.45812057 5.52158709 5.58505361 5.64852012
5.71198664 5.77545316 5.83891968 5.9023862 5.96585272 6.02931923
6.09278575 6.15625227 6.21971879 6.28318531]
'''
ndarray的打印
-
当对象过大时,python会改用“…”代替,如果需要强制打印所有内容可以修改如下:
np.set_printoptions(threshold=sys.maxsize)
基本操作
-
ndarray对象的基本算数操作是元素对元素操作的:
import numpy as np a = np.array([1, 2, 3, 4]) b = np.array([2, 3, 4, 5]) print(a+b) print(a**2) print(a<2) ''' [3 5 7 9] [ 1 4 9 16] [ True False False False] ''' -
特殊的,在Numpy中“*”是元素对元素,想要矩阵相乘请使用“@”或dot():
print(a*b) # 矩阵相乘 print(a@b) print(a.dot(b)) ''' [ 2 6 12 20] 40 40 ''' -
两种元素不同的数组操作时(如相乘),会自动转换为高精度
-
一些直接写在对象中的操作
# 一些集成在ndarray对象中的操作 print(a.sum()) print(a.max()) print(a.min()) ''' 10 4 1 ''' -
通过指定维度可以实现更精细的操作
c = np.array([[1, 2, 3, 4], [5, 6, 7, 8]]) print(c) print(c.sum(axis=0)) print(c.sum(axis=1)) ''' [[1 2 3 4] [5 6 7 8]] [ 6 8 10 12] [10 26] '''
通用函数
根据自己需求选择。
索引、切片和迭代
索引
- 每个维度都可以有一个索引,之间用逗号分割
- 当提供的索引少于轴的数量时,缺少的索引被视为完整的切片
迭代
多维数组的迭代是相对于第一个轴完成的。(一维数组迭代显然是各个元素)
import numpy as np
a = np.array([[1, 3, 5, 7], [2, 4, 6, 8]])
for item in a:
print(item)
'''
[1 3 5 7]
[2 4 6 8]
'''
如果相对数组中的每个元素进行操作,可以使用flat属性,它是数组所有元素的迭代器:
a = np.arange(20).reshape(5, 2, 2)
for element in a.flat:
print(element)
'''
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
'''
形状操纵
import numpy as np
a = np.arange(15).reshape(3, 5)
print(a.ravel())
print(a.reshape(5, 3))
print(a.resize(5, 3))
print(a)
'''
[ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14]
[[ 0 1 2]
[ 3 4 5]
[ 6 7 8]
[ 9 10 11]
[12 13 14]]
None
[[ 0 1 2]
[ 3 4 5]
[ 6 7 8]
[ 9 10 11]
[12 13 14]]
'''
'''
从上可以看出不同方法的效果:
1.ravel()会将数组进行展平处理
2.reshape与resize的不同在于reshape会创建一个新的数组对象,而resize会在原来数组的基础上进行操作,这就是第三个print为“None”的原因
'''
当参数写为-1时Numpy会自动根据已知信息推断具体值
将不同的数组堆叠在一起
注意需要数组在同一维度的元素数是相同的。
import numpy as np
a = np.arange(6).reshape(2, 3)
b = np.arange(6, 12).reshape(2, 3)
c = np.arange(12, 15)
print(np.vstack((a, b)))
print(np.hstack((a, b)))
print(np.column_stack((a, b)))
print(np.concatenate((a, b), 0))
print(np.concatenate((a, b), 1))
'''
[[ 0 1 2]
[ 3 4 5]
[ 6 7 8]
[ 9 10 11]]
[[ 0 1 2 6 7 8]
[ 3 4 5 9 10 11]]
[[ 0 1 2 6 7 8]
[ 3 4 5 9 10 11]]
[[ 0 1 2]
[ 3 4 5]
[ 6 7 8]
[ 9 10 11]]
'''
'''
concatenate():
numpy.concatenate((a1, a2, ...), axis=0, out=None, dtype=None, casting="same_kind")
- axis:堆叠的维度
- out:ndarray,输出到该对象
- dtype:输出元素类型,不可与out同用
-
'''
还有两种在创建时即堆叠的函数:
d = np.r_[(1, 2, 3), (4, 5, 6)]
print("1")
print(d)
d = np.r_[((1, 2, 3), (4, 5, 6)), ((7, 8, 9), (10, 11, 12))]
print("2")
print(d)
d = np.c_[(1, 2, 3), (4, 5, 6)]
print("3")
print(d)
d = np.c_[((1, 2, 3), (4, 5, 6)), ((7, 8, 9), (10, 11, 12))]
print("4")
print(d)
'''
1
[1 2 3 4 5 6]
2
[[ 1 2 3]
[ 4 5 6]
[ 7 8 9]
[10 11 12]]
3
[[1 4]
[2 5]
[3 6]]
4
[[ 1 2 3 7 8 9]
[ 4 5 6 10 11 12]]
'''
分割数组
import numpy as np
a = np.arange(16).reshape(4, 4)
print(np.vsplit(a, 2)) # 沿行切割
print(np.hsplit(a, 2)) # 沿列切割
a = a.reshape(2, 8)
print(np.hsplit(a,(3, 6, 7))) # 沿第三列、第六列和第七列切割
'''
[array([[0, 1, 2, 3],
[4, 5, 6, 7]]), array([[ 8, 9, 10, 11],
[12, 13, 14, 15]])]
[array([[ 0, 1],
[ 4, 5],
[ 8, 9],
[12, 13]]), array([[ 2, 3],
[ 6, 7],
[10, 11],
[14, 15]])]
[array([[ 0, 1, 2],
[ 8, 9, 10]]), array([[ 3, 4, 5],
[11, 12, 13]]), array([[ 6],
[14]]), array([[ 7],
[15]])]
'''
副本和视图
在操作数组时他到底是创建了一个新数组并删除了原来的数组还是直接在原来的数组基础上修改了?情况如下。
import numpy as np
a = np.arange(6)
# 情况1:不创建副本
b = a
print(id(a))
print(id(b))
# 情况2:浅拷贝
c = a.view()
print(id(c))
print(c)
c[5] = 6
print(a)
# 情况3:深拷贝
d = a.copy()
print(id(d))
print(d)
a[5] = 7
print(d)
'''
1953967626672
1953967626672
1953967632048
[0 1 2 3 4 5]
[0 1 2 3 4 6]
1954209518032
[0 1 2 3 4 6]
[0 1 2 3 4 6]
'''
广播规则
简单概要:但两个形状并不相同的数组进行操作时,会将形状小的数组进行填充以使得操作能够顺利进行。
高级索引和索引技巧
使用索引数组进行索引
import numpy as np
a = np.arange(12)**2
i = np.array([1, 1, 3, 8, 5])
print(a[i])
j = np.array([[3, 4], [9, 7]])
print(a[j])
'''
[ 1 1 9 64 25]
[[ 9 16]
[81 49]]
'''
当被索引的数组为多维数组时,数组索引是在第一个维度上进行:
# 当被索引的数组是多维时,数组索引是在第一个维度上进行索引(行)
a = np.arange(12).reshape(4, 3)
k = np.array([0, 2, 3])
print(a[k])
'''
[[ 0 1 2]
[ 6 7 8]
[ 9 10 11]]
'''
我们也可以在多个维度上进行索引:
# 我们也可以在多个维度上进行索引
a = a.reshape(3, 4)
i = np.array([[0, 1], # indices for the first dim of `a`
[1, 2]])
j = np.array([[2, 1], # indices for the second dim
[3, 3]])
print(a)
print(a[i])
print(a[i, j])
'''
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
[[[ 0 1 2 3]
[ 4 5 6 7]]
[[ 4 5 6 7]
[ 8 9 10 11]]]
[[ 2 5]
[ 7 11]]
'''
使用布尔数组进行索引
不同于使用整数索引数组索引,布尔数组可以显式地选择哪些项是我们需要的。
import numpy as np
a = np.arange(12).reshape(3, 4)
b = a > 4
print(a[b])
# 方式2
a = np.arange(12).reshape(3, 4)
b1 = np.array([False, True, True])
b2 = np.array([True, False, True, False])
print("------------------------")
print(a)
print(a[b1, :])
print(a[b1])
print(a[:, b2])
# 以下索引方式的进行:先在第一个数组b1找到第一个True,对应下标为1,
# 再在第二个数组b2找到第一个True,对应下标为0,故原数组[1,0]有效,以此类推
print(a[b1, b2])
'''
[ 5 6 7 8 9 10 11]
------------------------
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
[[ 4 5 6 7]
[ 8 9 10 11]]
[[ 4 5 6 7]
[ 8 9 10 11]]
[[ 0 2]
[ 4 6]
[ 8 10]]
[ 4 10]
'''
ix_()函数
ix_()函数可以用来快速创建一个用于索引的数组
import numpy as np
# 创建一个 3x3 的二维数组
a = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
# 使用 ix_() 函数创建一个用于索引的数组
idx = np.ix_([0, 1, 2], [0, 1, 1]) # 每个列表对应该维度的索引
print(idx)
# 使用索引数组来索引原数组
print(a[idx])
'''
(array([[0],
[1],
[2]]), array([[0, 1, 1]]))
[[1 2 2]
[4 5 5]
[7 8 8]]
'''
在官方文档中利用了ix_()函数+广播机制完成了数组之间的运算,感兴趣请自行查看。
Numpy参考
https://numpy.org/devdocs/reference/index.html#reference
本文详细介绍了Numpy库在Python中的应用,包括ndarray的基本概念、创建过程、属性操作、元素级和矩阵运算、形状操纵、索引与切片、迭代、广播规则以及数组操作技巧,如堆叠、分割和视图的使用。
1104





