一. 高级索引
相比于基本索引,高级索引可以访问到数组中的任意元素,并且可以用来对数组进行复杂的操作和修改。
1.整数数组索引
整数数组索引是指使用一个数组来访问另一个数组的元素。这个数组中的每个元素都是目标数组中某个维度上的索引值。
示例:打印(0,0),(1,1),(2.0)上的三个元素
import numpy as npx = np.array([[1, 2], [3, 4], [5, 6]]) # 3行2列
y = x[[0, 1, 2], [0, 1, 0]] # 前后两个相互对应,(0,0),(1,1),(2.0)
print(y)
打印
import numpy as npx = np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11]])
print('我们的数组是:')
print(x)
print('\n')
# 获取(0,0),(0,2),(3.0),(3,2)四个位置的元素
rows = np.array([[0, 0], [3, 3]])
cols = np.array([[0, 2], [0, 2]])
y = x[rows, cols]
print('这个数组的四个角元素是:')
print(y)
打印
可以借助切片 : 或 … 与索引数组组合。
示例
import numpy as npa = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print(a)
b = a[1:3, 1:3] # 获取行索引从1开始,到3前一个数结束,获取列索引从1开始,到3前一个数结束
c = a[1:3, [1, 2]] # 获取行索引从1开始,到3前一个数结束,列获取列索引1,2
d = a[..., 1:] # 获取全部的行,列获取列索引从1开始到最后一个
print(b)
print(c)
print(d)
打印
2.布尔索引
布尔索引通过布尔运算(如:比较运算符)来获取符合指定条件的元素的数组。
示例:以下实例获取大于 5 的元素
import numpy as npy = np.array([[0, 1, 2], [3, 4, 5], [1, 7, 8], [9, 10, 11]])
print('我们的数组是:')
print(y)
print('\n')
# 现在我们会打印出大于 5 的元素
print('大于 5 的元素是:')
print(y[y > 5]) # 依照理解,第一y是指数组y,第二个y指数组中元素的值
打印
使用了 ~(取补运算符)过滤 NaN。
示例:
import numpy as np
from numpy import int32a = np.array([np.nan, 1, 2, np.nan, 3, 4, 5], dtype=np.float32)
print(a[~np.isnan(a)])
打印
获取复数元素(如果获取非复数的话,'['后面加上'~'符)
import numpy as npa = np.array([1, 2 + 6j, 5, 3.5 + 5j])
print(a[np.iscomplex(a)])
打印
3.花式索引
(1)花式索引指的是利用整数数组进行索引。
(2)花式索引根据索引数组的值作为目标数组的某个轴的下标来取值。
(3)对于使用一维整型数组作为索引,如果目标是一维数组,那么索引的结果就是对应位置的元素,如果目标是二维数组,那么就是对应下标的行。
(4)花式索引跟切片不一样,它总是将数据复制到新数组中。
示例
import numpy as npx = np.array([2, 4, 6, 3, 4, 5, 9])
print(x)
# 一维数组读取指定下标对应的元素
print("-------读取下标对应的元素-------")
x2 = x[[0, 6]] # 使用花式索引
print(x2)print(x2[0])
print(x2[1])
打印
读取对应的行
import numpy as np x=np.arange(32).reshape((8,4))
print(x)
# 二维数组读取指定下标对应的行
print("-------读取下标对应的行-------")
print (x[[4,2,1,7]])
打印:
传入倒序索引数组
示例
import numpy as np x=np.arange(32).reshape((8,4))
print (x[[-4,-2,-1,-7]])
打印
传入多个索引数组(要使用 np.ix_)
np.ix_ 函数就是输入两个数组,产生笛卡尔积的映射关系。
笛卡尔乘积是指在数学中,两个集合 X 和 Y 的笛卡尔积(Cartesian product),又称直积,表示为 X×Y,第一个对象是X的成员而第二个对象是 Y 的所有可能有序对的其中一个成员。
例如 A={a,b}, B={0,1,2},则:
A×B={(a, 0), (a, 1), (a, 2), (b, 0), (b, 1), (b, 2)} B×A={(0, a), (0, b), (1, a), (1, b), (2, a), (2, b)}
示例
import numpy as npx = np.arange(32).reshape((8, 4))
print(x)
print(x[np.ix_([1, 5, 7, 2], [0, 3, 1, 2])])
打印
二. 广播
1.定义
广播(Broadcast)是 numpy 对不同形状(shape)的数组进行数值计算的方式, 对数组的算术运算通常在相应的元素上进行。
如果两个数组 a 和 b 形状相同,即满足 a.shape == b.shape,那么 a*b 的结果就是 a 与 b 数组对应位相乘。这要求维数相同,且各维度的长度相同。
示例:
import numpy as npa = np.array([1, 2, 3, 4])
b = np.array([10, 20, 30, 40])
c = a * b
print(c)
打印
当运算中的 2 个数组的形状不同时,numpy 将自动触发广播机制。
示例
import numpy as np a = np.array([[ 0, 0, 0],[10,10,10],[20,20,20],[30,30,30]])
b = np.array([0,1,2])
print(a + b)
打印
下面的图片展示了数组 b 如何通过广播来与数组 a 兼容。(参照菜鸟教程)
4x3 的二维数组与长为 3 的一维数组相加,等效于把数组 b 在二维上重复 4 次再运算:
示例
import numpy as npa = np.array([[0, 0, 0],[10, 10, 10],[20, 20, 20],[30, 30, 30]])
b = np.array([1, 2, 3])
bb = np.tile(b, (4, 1)) # 重复 b 的各个维度
print(a + bb)
print(a+b)
打印
2.规则
广播的规则:
- 让所有输入数组都向其中形状最长的数组看齐,形状中不足的部分都通过在前面加 1 补齐。
- 输出数组的形状是输入数组形状的各个维度上的最大值。
- 如果输入数组的某个维度和输出数组的对应维度的长度相同或者其长度为 1 时,这个数组能够用来计算,否则出错。
- 当输入数组的某个维度的长度为 1 时,沿着此维度运算时都用此维度上的第一组值。
简单理解:对两个数组,分别比较他们的每一个维度(若其中一个数组没有当前维度则忽略),满足:
- 数组拥有相同形状。
- 当前维度的值相等。
- 当前维度的值有一个是 1。
若条件不满足,抛出 "ValueError: frames are not aligned" 异常。
三.迭代数组
1.遍历顺序
NumPy 迭代器对象 numpy.nditer 提供了一种灵活访问一个或者多个数组元素的方式。
迭代器最基本的任务的可以完成对数组元素的访问。
实现最基本的打印 示例:
import numpy as npa = np.arange(6).reshape(2, 3)
print('原始数组是:')
print(a)
print('\n')
print('迭代输出元素:')
for x in np.nditer(a):print(x, end=", ")
print('\n')
打印
转置
以上实例不是使用标准 C 或者 Fortran 顺序,选择的顺序是和数组内存布局一致的,这样做是为了提升访问的效率,默认是行序优先(row-major order,或者说是 C-order)。
使用 np.nditer(a.T.copy(order='C'))
这反映了默认情况下只需访问每个元素,而无需考虑其特定顺序。我们可以通过迭代上述数组的转置来看到这一点,并与以 C 顺序访问数组转置的 copy 方式做对比,如下实例:
import numpy as npa = np.arange(6).reshape(2,3)
for x in np.nditer(a.T):print (x, end=", " )
print ('\n')for x in np.nditer(a.T.copy(order='C')):print (x, end=", " )
print ('\n')
打印
从上述例子可以看出,a 和 a.T 的遍历顺序是一样的,也就是他们在内存中的存储顺序也是一样的,但是 a.T.copy(order = 'C') 的遍历结果是不同的,那是因为它和前两种的存储方式是不一样的,默认是按行访问。
2.控制遍历顺序
for x in np.nditer(a, order='F'):
Fortran order,即是列序优先;for x in np.nditer(a.T, order='C'):
C order,即是行序优先;
import numpy as npa = np.arange(0,60,5)
a = a.reshape(3,4)
print ('原始数组是:')
print (a)
print ('\n')
print ('原始数组的转置是:')
b = a.T
print (b)
print ('\n')
print ('以 C 风格顺序排序:')
c = b.copy(order='C')
print (c)
for x in np.nditer(c): print (x, end=", " )
print ('\n')
print ('以 F 风格顺序排序:')
c = b.copy(order='F')
print (c)
for x in np.nditer(c): print (x, end=", " )
打印
可以通过显式设置,来强制 nditer 对象使用某种顺序
示例
import numpy as np a = np.arange(0,60,5)
a = a.reshape(3,4)
print ('原始数组是:')
print (a)
print ('\n')
print ('以 C 风格顺序排序:')
for x in np.nditer(a, order = 'C'): print (x, end=", " )
print ('\n')
print ('以 F 风格顺序排序:')
for x in np.nditer(a, order = 'F'): print (x, end=", " )
打印
3.修改数组中元素的值
nditer 对象有另一个可选参数 op_flags。 默认情况下,nditer 将视待迭代遍历的数组为只读对象(read-only),为了在遍历数组的同时,实现对数组元素值的修改,必须指定 readwrite 或者 writeonly 的模式。
import numpy as npa = np.arange(0,60,5)
a = a.reshape(3,4)
print ('原始数组是:')
print (a)
print ('\n')
for x in np.nditer(a, op_flags=['readwrite']): x[...]=2*x
print ('修改后的数组是:')
print (a)
打印
4.使用外部循环
nditer 类的构造器拥有 flags 参数,它可以接受下列值:
参数 | 描述 |
---|---|
c_index | 可以跟踪 C 顺序的索引 |
f_index | 可以跟踪 Fortran 顺序的索引 |
multi_index | 每次迭代可以跟踪一种索引类型 |
external_loop | 给出的值是具有多个值的一维数组,而不是零维数组 |
示例
import numpy as np
a = np.arange(0,60,5)
a = a.reshape(3,4)
print ('原始数组是:')
print (a)
print ('\n')
print ('修改后的数组是:')
for x in np.nditer(a, flags = ['external_loop'], order = 'F'):print (x, end=", " )
打印
5.广播迭代
如果两个数组是可广播的,nditer 组合对象能够同时迭代它们。 假设数组 a 的维度为 3X4,数组 b 的维度为 1X4 ,则使用以下迭代器(数组 b 被广播到 a 的大小)。
示例
import numpy as np a = np.arange(0,60,5)
a = a.reshape(3,4)
print ('第一个数组为:')
print (a)
print ('\n')
print ('第二个数组为:')
b = np.array([1, 2, 3, 4], dtype = int)
print (b)
print ('\n')
print ('修改后的数组为:')
for x,y in np.nditer([a,b]): print ("%d:%d" % (x,y), end=", " )
打印
四. 位运算
位运算是一种在二进制数字的位级别上进行操作的一类运算,它们直接操作二进制数字的各个位,而不考虑数字的整体值。
位运算在计算机科学中广泛应用于优化和处理底层数据。
NumPy "bitwise_" 开头的函数是位运算函数。
函数 | 描述 |
---|---|
bitwise_and | 按位与,对数组元素执行位与操作 |
bitwise_or | 按位或,对数组元素执行位或操作 |
bitwise_xor | 按位异或 |
bitwise_not | 按位取反 |
invert | 按位取反 |
left_shift | 左移位运算,向左移动二进制表示的位 |
right_shift | 右移位运算,向右移动二进制表示的位 |
示例
import numpy as nparr1 = np.array([True, False, True], dtype=bool)
arr2 = np.array([False, True, False], dtype=bool)result_and = np.bitwise_and(arr1, arr2)
result_or = np.bitwise_or(arr1, arr2)
result_xor = np.bitwise_xor(arr1, arr2)
result_not = np.bitwise_not(arr1)print("AND:", result_and) # [False, False, False]
print("OR:", result_or) # [True, True, True]
print("XOR:", result_xor) # [True, True, True]
print("NOT:", result_not) # [False, True, False]# 按位取反
arr_invert = np.invert(np.array([1, 2], dtype=np.int8))
print("Invert:", arr_invert) # [-2, -3]# 左移位运算
arr_left_shift = np.left_shift(5, 2)
print("Left Shift:", arr_left_shift) # 20# 右移位运算
arr_right_shift = np.right_shift(10, 1)
print("Right Shift:", arr_right_shift) # 5
打印
1. bitwise_and
两个数组进行和运算
import numpy as npprint('13 和 17 的二进制形式:')
a, b = 13, 17
print(bin(a), bin(b))
print('\n')print('13 和 17 的位与:')
print(np.bitwise_and(13, 17))
打印
2. bitwise_or
两个数组进行或运算
import numpy as np a,b = 13,17
print ('13 和 17 的二进制形式:')
print (bin(a), bin(b))print ('13 和 17 的位或:')
print (np.bitwise_or(13, 17))
打印
3. invert
invert() 函数对数组中整数进行位取反运算,即 0 变成 1,1 变成 0。
import numpy as np print ('13 的位反转,其中 ndarray 的 dtype 是 uint8:')
print (np.invert(np.array([13], dtype = np.uint8)))
print ('\n')
# 比较 13 和 242 的二进制表示,我们发现了位的反转print ('13 的二进制表示:')
print (np.binary_repr(13, width = 8))
print ('\n')print ('242 的二进制表示:')
print (np.binary_repr(242, width = 8))
打印
4. left_shift
left_shift() 函数将数组元素的二进制形式向左移动到指定位置,右侧附加相等数量的 0。
示例
import numpy as np print ('将 10 左移两位:')
print (np.left_shift(10,2))
print ('\n')print ('10 的二进制表示:')
print (np.binary_repr(10, width = 8))
print ('\n')print ('40 的二进制表示:')
print (np.binary_repr(40, width = 8))
# '00001010' 中的两位移动到了左边,并在右边添加了两个 0。
打印
5. right_shift
right_shift() 函数将数组元素的二进制形式向右移动到指定位置,左侧附加相等数量的 0。
代码
import numpy as np print ('将 40 右移两位:')
print (np.right_shift(40,2))
print ('\n')print ('40 的二进制表示:')
print (np.binary_repr(40, width = 8))
print ('\n')print ('10 的二进制表示:')
print (np.binary_repr(10, width = 8))
# '00001010' 中的两位移动到了右边,并在左边添加了两个 0。
打印
五. 字符串函数
以下函数用于对 dtype 为 numpy.string_ 或 numpy.unicode_ 的数组执行向量化字符串操作。 它们基于 Python 内置库中的标准字符串函数。
这些函数在字符数组类(numpy.char)中定义。
函数 | 描述 |
---|---|
add() | 对两个数组的逐个字符串元素进行连接 |
multiply() | 返回按元素多重连接后的字符串 |
center() | 居中字符串 |
capitalize() | 将字符串第一个字母转换为大写 |
title() | 将字符串的每个单词的第一个字母转换为大写 |
lower() | 数组元素转换为小写 |
upper() | 数组元素转换为大写 |
split() | 指定分隔符对字符串进行分割,并返回数组列表 |
splitlines() | 返回元素中的行列表,以换行符分割 |
strip() | 移除元素开头或者结尾处的特定字符 |
join() | 通过指定分隔符来连接数组中的元素 |
replace() | 使用新字符串替换字符串中的所有子字符串 |
decode() | 数组元素依次调用str.decode |
encode() | 数组元素依次调用str.encode |
1. numpy.char.add()
numpy.char.add() 函数依次对两个数组的元素进行字符串连接。
示例
import numpy as npa = np.array(['abc', 'def']) # 注意数组元素应该是列表形式
b = np.array(['yk', '123']) # 同样需要是列表形式
c = np.char.add(a, b)
print(c)
打印
2. numpy.char.multiply()
numpy.char.multiply() 函数执行多重连接。
示例
import numpy as npa = np.array(['abc', 'def']) # 注意数组元素应该是列表形式
b = np.array(['yk', '123']) # 同样需要是列表形式
c = np.char.add(a, np.char.multiply(['la', '123'], 5))
print(c)
打印
3. numpy.char.center()
numpy.char.center() 函数用于将字符串居中,并使用指定字符在左侧和右侧进行填充。
示例
import numpy as np# np.char.center(str , width,fillchar) :
# str: 字符串,width: 长度,fillchar: 填充字符
print(np.char.center('Runoob', 20, fillchar='*'))
打印
4. numpy.char.capitalize()
numpy.char.capitalize() 函数将字符串的第一个字母转换为大写:
示例
import numpy as np print (np.char.capitalize('runoob'))
打印
5. numpy.char.title()
numpy.char.title() 函数将字符串的每个单词的第一个字母转换为大写:
示例
import numpy as npprint(np.char.title('i like runoob'))
打印
6. numpy.char.lower()
numpy.char.lower() 函数对数组的每个元素转换为小写。它对每个元素调用 str.lower。
示例
import numpy as np #操作数组
print (np.char.lower(['RUNOOB','GOOGLE']))# 操作字符串
print (np.char.lower('RUNOOB'))
打印
7. numpy.char.upper()
numpy.char.upper() 函数对数组的每个元素转换为大写。它对每个元素调用 str.upper。
示例
import numpy as np #操作数组
print (np.char.upper(['runoob','google']))# 操作字符串
print (np.char.upper('runoob'))
打印
8. numpy.char.split()
numpy.char.split() 通过指定分隔符对字符串进行分割,并返回数组。默认情况下,分隔符为空格。
示例
import numpy as np # 分隔符默认为空格
print (np.char.split ('i like runoob?'))
# 分隔符为 .
print (np.char.split ('www.runoob.com', sep = '.'))
打印
9. numpy.char.splitlines()
numpy.char.splitlines() 函数以换行符作为分隔符来分割字符串,并返回数组。
\n,\r,\r\n 都可用作换行符。
示例
import numpy as np # 换行符 \n
print (np.char.splitlines('i\nlike runoob?'))
print (np.char.splitlines('i\rlike runoob?'))
打印
10. numpy.char.strip()
numpy.char.strip() 函数用于移除开头或结尾处的特定字符。
示例
import numpy as np # 移除字符串头尾的 a 字符
print (np.char.strip('ashok arunooba','a'))# 移除数组元素头尾的 a 字符
print (np.char.strip(['arunooba','admin','java'],'a'))
打印
11. numpy.char.join()
numpy.char.join() 函数通过指定分隔符来连接数组中的元素或字符串
示例
import numpy as np# 操作字符串
print(np.char.join(':', 'runoob'))# 指定多个分隔符操作数组元素
print(np.char.join([':', '-'], ['runoob', 'google']))
打印
12. numpy.char.replace()
numpy.char.replace() 函数使用新字符串替换字符串中的所有子字符串。
示例
import numpy as np print (np.char.replace ('i like runoob', 'oo', 'cc'))
打印
13. numpy.char.encode()
numpy.char.encode() 函数对数组中的每个元素调用 str.encode 函数。 默认编码是 utf-8,可以使用标准 Python 库中的编解码器。
示例
import numpy as np a = np.char.encode('runoob', 'cp500')
print (a)
打印
14. numpy.char.decode()
numpy.char.decode() 函数对编码的元素进行 str.decode() 解码。
示例
import numpy as np a = np.char.encode('runoob', 'cp500')
print (a)
print (np.char.decode(a,'cp500'))
打印