原创

NumPy基础:数组与向量化的常见操作


1.数组的索引与切片

import numpy as np

# 生成一个由0~9组成的数组
arr = np.arange(10)
print(arr)
print(arr[5:8])

# 给数组切片传入666
# 数组的切片是原数组的视图,这意味着数组不是被复制了,任何对于视图的修改都会反映在原数组上。
arr[5:8] = 666
arr_slice = arr[5:8]
print(arr_slice)

arr_slice[1] = 111
print(arr)
[0 1 2 3 4 5 6 7 8 9]
[5 6 7]
[666 666 666]
[ 0 1 2 3 4 666 111 666 8 9]

【说明】:你可能会惊讶,这与其他编程语言不太一样,因为,其他的数组编程语言都是更为急切地复制数据。由于Numpy被设计成适合处理非常大的数组,你就可以想象:如果Numpy持续复制数据会引起多少内存问题。

# 如果你想要一份数组切片地拷贝,而不是一份视图的话:
temp = arr[5:8].copy()

2.布尔索引

import numpy as np

names = np.array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'])
print(names)

data = np.random.randn(7, 4)
print(data)

# 通过条件生成一个布尔数组
condition = (names == 'Bob')
print(condition)

# 通过布尔数组筛选原数组
output = data[condition]
print(output)

# 将小于0的元素赋100
data[data < 0] = 10
print(data)
['Bob' 'Joe' 'Will' 'Bob' 'Will' 'Joe' 'Joe']

[[-0.19095908  0.02638248  3.40061838  0.64332047]
 [ 1.24643818  0.31518418 -0.97122966 -0.23856172]
 [-2.07085086  0.58235416 -0.96226216  0.39574454]
 [ 1.64036416  0.09535173 -0.4957701   1.65694795]
 [-0.17115793  1.14371387  0.51771578 -0.48858814]
 [-1.00854954 -2.06948291 -0.8706871   0.78130176]
 [-1.14102298 -0.58537114 -1.12550156 -0.46906488]]
 
[ True False False  True False False False]

[[-0.19095908  0.02638248  3.40061838  0.64332047]
 [ 1.64036416  0.09535173 -0.4957701   1.65694795]]
 
 [[ 2.26566417 10.         10.         10.        ]
 [ 1.29367836  0.4144992   0.67154118  1.1829212 ]
 [ 2.67102253  0.6123542   0.03956005  1.41526961]
 [10.         10.          0.78039751 10.        ]
 [ 0.30668879 10.          1.01036469 10.        ]
 [10.         10.         10.          0.60727882]
 [10.          1.19906783  0.01936304 10.        ]]

3.神奇索引

import numpy as np

arr = np.arange(32).reshape((8, 4))
print(arr)

# 依次打印二维数组的第5、4、1、7行
print(arr[[4, 3, 0, 6]])
# 依次打印如下位置的元素:(1,0)、(5,3)、(7, 1)、(2, 2)
print(arr[[1, 5, 7, 2], [0, 3, 1, 2]])

temp = arr[[4, 3, 0, 6]]
print(temp)

# 与切片不同,神奇索引总是将数据复制到一个新的数组中,因此原数组不发生变化
temp[0] = -10
print(temp)
print(arr)
[[16 17 18 19]
 [12 13 14 15]
 [ 0  1  2  3]
 [24 25 26 27]]

[[-10 -10 -10 -10]
 [ 12  13  14  15]
 [  0   1   2   3]
 [ 24  25  26  27]]

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

4.面向数组编程的思想

使用了这么长时间的Numpy你就会发现:在对数组、向量、矩阵等数据结构进行操作时,不再需要按照平时那样使用大量的循环操作。这种利用数组表达式来替代显示循环的方法,称为“向量化”。通常,向量化的数组操作会比纯Python的等价实现在速度上快一到两个数量级(甚至更多),这里面便存在一种Numpy独有的机制——“广播”,在后续深入学习时我们还会遇见。

5.将条件逻辑作为数组操作

import numpy as np

arr = np.random.randn(4,4)
print(arr)

# where()函数:本质上就是三元表达式
# 满足条件取100,不满足条件保持不变
result = np.where(arr > 0, 100, arr)
print(result)
[[ 0.73560492  0.00444043  1.75764649  1.43913789]
 [ 0.44036978  1.54873196 -1.60608571  0.65768845]
 [-0.76240625  1.93341631  0.96526121 -0.49597636]
 [ 1.646327    0.79781332 -0.70924863  1.28317489]]

[[100.         100.         100.         100.        ]
 [100.         100.          -1.60608571 100.        ]
 [ -0.76240625 100.         100.          -0.49597636]
 [100.         100.          -0.70924863 100.        ]]
Python
  • 作者:李延松(联系作者)
  • 发表时间:2020-07-18 18:44
  • 版本声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)
  • 公众号转载:请在文末添加作者公众号二维码

评论

留言