布尔型索引
可以通过比较运算符来产生一个布尔型数组。
对同样大小的布尔型数组,可以利用&(和)、|(或)、-(非)进行运算。
data = np.random.randn(7, 4)
print(data)
print(data > 0)
print((data > -1) & (data < 1))
[[ 0.59711287 0.35911118 0.80925994 -1.60744802]
[ 1.4904879 0.1192616 -0.83902824 0.37876663]
[-0.26166516 -0.49346625 0.18346839 0.70833643]
[ 0.32048212 -0.69056052 -0.29403945 -0.14632815]
[-0.08186285 -0.49594495 0.12816477 1.27712333]
[ 0.44620341 -1.57771506 -0.78073316 -0.38668016]
[-0.66192819 -1.30421999 1.00875952 1.0798795 ]]
[[ True True True False]
[ True True False True]
[False False True True]
[ True False False False]
[False False True True]
[ True False False False]
[False False True True]]
[[ True True True False]
[False True True True]
[ True True True True]
[ True True True True]
[ True True True False]
[ True False True True]
[ True False False False]]
利用布尔型索引的功能,可以快速进行筛选。
定义一个名称数组,长度为7,并假设上述data中的每一行与名称数组中的名字一一对应。
names = np.array(['ben', 'tom', 'ben', 'jeremy', 'jeremy', 'tom', 'ben'])
print(names)
print(data[names == 'ben'])
print(data[(names == 'ben') | (names == 'tom')])
print(data[data > 0])
['ben' 'tom' 'ben' 'jeremy' 'jeremy' 'tom' 'ben']
[[ 0.59711287 0.35911118 0.80925994 -1.60744802]
[-0.26166516 -0.49346625 0.18346839 0.70833643]
[-0.66192819 -1.30421999 1.00875952 1.0798795 ]]
[[ 0.59711287 0.35911118 0.80925994 -1.60744802]
[ 1.4904879 0.1192616 -0.83902824 0.37876663]
[-0.26166516 -0.49346625 0.18346839 0.70833643]
[ 0.44620341 -1.57771506 -0.78073316 -0.38668016]
[-0.66192819 -1.30421999 1.00875952 1.0798795 ]]
[0.59711287 0.35911118 0.80925994 1.4904879 0.1192616 0.37876663 0.18346839 0.70833643 0.32048212 0.12816477 1.27712333 0.44620341
1.00875952 1.0798795 ]
花式索引
#对于使用一维整型数组作为索引,如果目标是一维数组,那么索引的结果就是对应位置的元素;如果目标是二维数组,那么就是对应下标的行。
print(names[[4, 3, 2, 1]])
print(names[[-1, -2, -3, -4]])
print(data[[3, 1]])
print(data[[3, 1, 2], [0, 2, 1]])
#一次性传入两个列表:[3,1,2]、[0,2,1],最终选取出三个元素,其在data数组中的位置分别是(3, 0)、(1, 2)、(2, 1)。并没有和切片索引一样,返回一个矩形区域。
#下面是得到矩形区域的一个这种的办法:
print(data[[3,1,2][:,[0,2,1]]])
['jeremy' 'jeremy' 'ben' 'tom']
['ben' 'tom' 'jeremy' 'jeremy']
[[ 0.32048212 -0.69056052 -0.29403945 -0.14632815]
[ 1.4904879 0.1192616 -0.83902824 0.37876663]]
[ 0.32048212 -0.83902824 -0.49346625]
[[ 0.32048212 -0.29403945 -0.69056052]
[-0.26166516 0.18346839 -0.49346625]
[ 1.4904879 -0.83902824 0.1192616 ]]
视图是指对数据的引用,通过该引用亦便可访问、操作原有数据,但原有数据不会产生拷贝。如果我们对视图进行修改,它会影响到原始数据,物理内存在同一位置。
副本是一个数据的完整的拷贝,如果我们对副本进行修改,它不会影响到原始数据,物理内存不在同一位置。
直接赋值
a = np.arange(12)
print("数组a:", a)
print("数组a的id:", id(a))
b = a
print("数组b:", b)
print("数组b的id:", id(b))
a.shape=(3,4)
print(a)
print(b)
数组a: [ 0 1 2 3 4 5 6 7 8 9 10 11]
数组a的id: 3027713941216
数组b: [ 0 1 2 3 4 5 6 7 8 9 10 11]
数组b的id: 3027713941216
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
直接赋值地址是一样的;改变a的形状,b跟着改变。改变b的性质,a跟着改变。
视图或浅拷贝
a = np.arange(6).reshape(3, 2)
print("数组a:", a)
print("数组a的id:", id(a))
b = a.view()
print("数组b:", b)
print("数组b的id:", id(b))
b.shape=(2,3)
print(b)
print(a)
数组a: [[0 1]
[2 3]
[4 5]]
数组a的id: 2141095934672
数组b: [[0 1]
[2 3]
[4 5]]
数组b的id: 2141135964000
[[0 1 2]
[3 4 5]]
[[0 1]
[2 3]
[4 5]]
视图地址不一样;改变a的形状,b不改变。改变b的形状,a不改变
arr = np.arange(12)
a = arr[3:]
b = arr[3:]
print("修改前的切片a:", a)
print("修改前的切片b:", b)
a[1] = 123
b[2] = 234
print("修改后的切片a:", a)
print("修改后的切片b:", b)
print("修改后的原数组arr:", arr)
修改前的切片a: [ 3 4 5 6 7 8 9 10 11]
修改前的切片b: [ 3 4 5 6 7 8 9 10 11]
修改后的切片a: [ 3 123 234 6 7 8 9 10 11]
修改后的切片b: [ 3 123 234 6 7 8 9 10 11]
修改后的原数组arr: [ 0 1 2 3 123 234 6 7 8 9 10 11]
我们可以发现:变量 a,b 都是 arr 的一部分视图,对视图的修改会直接反映到原数据和相关切片中。
副本或深拷贝
a = np.array([[0, 1], [2, 3], [4, 5]])
b = a.copy()
print(a)
print(b)
print(id(a))
print(id(b))
b[0, 0] = 100
print(a)
print(b)
[[0 1]
[2 3]
[4 5]]
[[0 1]
[2 3]
[4 5]]
2820242562624
2820247665360
[[0 1]
[2 3]
[4 5]]
[[100 1]
[ 2 3]
[ 4 5]]
副本的地址不一样;改变b的值,a不改变。改变a的值,b不改变。
a = np.array([[0, 1], [2, 3], [4, 5]])
b = a.copy()
c = a
d = a.view()
print(b is a)
print(c is a)
print(d is a)
False
True
False
bitwise_and 对数组元素执行位与操作
bitwise_or 对数组元素执行位或操作
invert 按位取反
left_shift 向左移动二进制表示的位
right_shift 向右移动二进制表示的位
numpy.bitwise_and函数
numpy.bitwise_and 函数对数组中整数的二进制形式执行位与运算。
a, b = 13, 17
print(np.bitwise_and(a, b))
# 解释:按位与都是1才是1
print("a的二进制为:", bin(a))
print("b的二进制为:", bin(b))
# a的二进制为:01101
# b的二进制为:10001
# 按位与: 00001
1
a的二进制为: 0b1101
b的二进制为: 0b10001
numpy.bitwise_or 函数
numpy.bitwise_or 函数对数组中整数的二进制形式执行位或运算。
a, b = 13, 17
print(np.bitwise_or(a, b))
# 解释:按位或只要有1就是1
print("a的二进制为:", bin(a))
print("b的二进制为:", bin(b))
# a的二进制为:01101
# b的二进制为:10001
# 按位或: 11101
29
a的二进制为: 0b1101
b的二进制为: 0b10001
numpy.invert函数
numpy.invert函数对数组中整数进行位取反运算,即 0 变成 1,1 变成 0。
对于有符号整数,取该二进制数的补码,然后 加1。二进制数,最高位为0表示正数,最高位为 1 表示负数。
print("1的二进制表示", np.binary_repr(1, width=8))
print("1的位反转", np.invert(1))
# 解释:
# 1的二进制码位 00000001
# 按位取反位 11111110
# 最高位为1表示负数,其他位取反 10000001
# 末位加1得其补码 10000010
# 转换回十进制 -2
1的二进制表示 00000001
1的位反转 -2
numpy.left_shift 函数
numpy.left_shift 函数将数组元素的二进制形式向左移动到指定位置,右侧附加相等数量的 0。
print("10的二进制表示", np.binary_repr(10, width=8))
print("10左移2位的结果:", np.left_shift(10,2))
# 解释:
#10的二进制为: 00001010
#左移两位为: 00101000
print(int('00101000',2))
10的二进制表示 00001010
10左移2位的结果: 40
40
numpy.right_shift函数
numpy.right_shift 函数将数组元素的二进制形式向右移动到指定位置,左侧附加相等数量的 0。
print("40的二进制表示", np.binary_repr(40, width=8))
print("40右移2位的结果:", np.right_shift(40, 2))
# 解释:
# 40的二进制为: 00101000
# 左移两位为: 00001010
print(int('00001010', 2))
40的二进制表示 00101000
40右移2位的结果: 10
10
进制转换
print(bin(10)) # 10转2
print(oct(10)) # 10转8
print(hex(10)) # 10转16
print(int('1010', 2)) # 2转10
print(int('37', 8)) # 8转10
print(int('4a', 16)) # 16转10
0b1010
0o12
0xa
10
31
74
二元运算
Numpy 提供了一系列可以用于线性代数运算的函数,具体如下:
dot 两个数组的点积,即元素对应相乘。
vdot 两个向量的点积
inner 两个数组的内积
matmul 两个数组的矩阵积
determinant 数组的行列式
solve 求解线性矩阵方程
inv 计算矩阵的乘法逆矩阵
对于两个一维数组,dot() 函数计算的是这两个数组对应下标元素的乘积和,也称之为內积。对于二维数组,计算的是两个数组的矩阵乘积。
a = np.array([1, 2, 3, 4])
b = np.array([6, 7, 8, 9])
print(np.dot(a, b))
# 80=1*6+2*7+3*8+4*9
A = np.array([[1, 2, 3], [4, 5, 6]])
B = np.array([[11, 22], [33, 44], [55, 66]])
print(np.dot(A, B))
# (2,3)*(3,2)=(2,2)
80
[[242 308]
[539 704]]
numpy.vdot() 函数是求两个向量的点积,即对应位置的元素乘积求和。
B = np.array([[11, 22], [33, 44], [55, 66]])
C = np.array([[1, 2], [3, 4], [5, 6]])
print(np.vdot(B, C))
1001
numpy.inner() 函数返回一维数组的向量内积。对于更高的维度,它返回最后一个轴上的元素乘积之和。
B = np.array([[11, 22], [33, 44], [55, 66]])
C = np.array([[1, 2], [3, 4], [5, 6]])
print(np.inner(B, C))
[[ 55 121 187]
[121 275 429]
[187 429 671]]
#解释
#[
# 11*1+22*2=55, 11*3+22*4=121, 11*5+22*6=187
# 33*1+44*2=121, 33*3+44*4=275, 33*5+44*6=429
# 55*1+66*2=187, 55*3+66*4=429, 55*5+66*6=671
#]
numpy.matmul 函数返回两个数组的矩阵乘积。对于二维数组,其计算结果与dot一致。
B = np.array([[11, 22], [33, 44], [55, 66]])
print(np.matmul(A,B))
[[242 308]
[539 704]]
线代求解
numpy.linalg.det() 函数计算输入矩阵的行列式。
行列式在线性代数中是非常有用的值。 它从方阵的对角元素计算。 对于 2×2 矩阵,它是左上和右下元素的乘积与其他两个的乘积的差。换句话说,对于矩阵 [[a,b],[c,d]],行列式计算为 ad-bc。 较大的方阵被认为是 2×2 矩阵的组合。
M = np.array([[6, 2, 1], [4, -2, 15], [12, 8, 7]])
print(M)
print(np.linalg.det(M))
-444.0000000000004
numpy.linalg.solve() 函数给出了矩阵形式的线性方程的解。
# x + y + z =10
# 2x + y = 6
# 3y -2z = 2
# 转换成矩阵
A = np.array([[1, 1, 1], [2, 1, 0], [0, 3, -2]])
b = np.array([[10], [6], [2]])
print(np.linalg.solve(A, b))
# x=1 y=4 z=5
[[1.]
[4.]
[5.]]
numpy.linalg.inv() 函数计算矩阵的乘法逆矩阵。逆矩阵的概念如下:设 A 是数域上的一个 n 阶矩阵,若在相同数域上存在另一个 n 阶矩阵 B,使得: AB=BA=E ,则我们称 B 是 A 的逆矩阵,而A则被称为可逆矩阵。注意:E 为单位矩阵。
利用逆矩阵,可以换一种思路求解 2.2 中的方程组的解:
对于矩阵 A,假设逆矩阵为 F,则有:x=Fb。因此方程组的解为:
A = np.array([[1, 1, 1], [2, 1, 0], [0, 3, -2]])
b = np.array([[10], [6], [2]])
print("计算A的逆矩阵:")
F = np.linalg.inv(A)
print("A的逆矩阵F:", F)
print("方程组的解为:", np.matmul(F, b))
计算A的逆矩阵:
A的逆矩阵F: [[-0.25 0.625 -0.125]
[ 0.5 -0.25 0.25 ]
[ 0.75 -0.375 -0.125]]
方程组的解为: [[1.]
[4.]
[5.]]
小结:
1.高级索引
比较运算符生成布尔类型数组
比较运算符与布尔类型索引
花式索引
2.副本与视图
直接赋值
.view()视图
.copy()副本
3.位运算
numpy.bitwise_and()位与
numpy.bitwise_or()位或
numpy.invert()取反
numpy.left_shift()左移
numpy.right_shift()右移
进制转换:
bin()10转2
oct() 10转8
hex() 10转16
int('1010', 2) 2转10
int('37', 8) 8转10
int('4a', 16) 16转10
4.线性代数
numpy.dot()两个数组的点积一维数组对应元素相乘加和,多维数组为矩阵乘法。
numpy.vdot()对应元素相乘求和。对于维度不一致的矩阵,如果其元素个数相等,则可以进行 vdot 点积运算;因为在 vdot运算过程中,会首先将矩阵展开。
numpy.inner()一维数组的向量内积。对于更高的维度,它返回最后一个轴上的元素乘积之和。
numpy.matmul()两个数组的矩阵乘积。
numpy.linalg.det()计算行列式。
numpy.linalg.solve()计算线性方程的解。
numpy.linalg.inv()计算矩阵的逆矩阵。
本文详细介绍了Python Numpy库中的一些高级操作,包括布尔型索引、花式索引、直接赋值、视图与深拷贝的概念,以及位运算如bitwise_and、bitwise_or、invert等函数的使用。此外,还讨论了二进制的进制转换和线性代数相关操作,如矩阵的行列式、求解线性方程组以及计算逆矩阵等。
1193

被折叠的 条评论
为什么被折叠?



