1.多维数组对象
ndarray是一个快读、灵活的大型数据集容器,允许使用类似于标量的操作语法在整块数据上进行数学计算
import numpy as np
# 创建一个简单的numpy数组
data1 = [6.7, 5.5, 2.8, 9.1]
arr1 = np.array(data1)
print(arr1)
# out:
# [6.7 5.5 2.8 9.1]
# 嵌套序列,同等长度的列表,会自动转换成多维函数
data2 = [[1, 2, 3, 4], [6, 8, 9, 0]]
arr2 = np.array(data2)
print(arr2)
# out:
# [[1 2 3 4]
# [6 8 9 0]]
# 除非显示地指定,否则np.array会自动推断生成数组的数据类型,存储在特殊的元数据dtype中
print(arr1.dtype)
# out: float64
# 还有其他的函数也可以创建新数组
arr3 = np.zeros(10)
arr4 = np.zeros((3, 10)) # 创建3行10列的零数组
arr5 = np.ones(10)
arr6 = np.ones((2, 3))
arr_empty = np.empty((2, 9)) # 生成一个2行9列的空二维数组
arr9 = np.full((2, 2), 10) # 生成一个2行2列且元素全为10的二维数组
# *-*-*-*-*-*
arr11 = np.eye(10) # 生成单位矩阵 - 对角线都为1,其余为0
arr12 = np.identity(11)
print(arr11)
print(arr12)
# *-*-*-*-*-*
arr7 = np.ones_like(arr1) # 生成一个形状和arr1相同的全1数组
arr8 = np.zeros_like(arr1) # 生成一个形状和arr1相同的全0数组
arr_empty_size = np.empty_like(arr1)
arr10 = np.full_like(arr1, 10) # 生成一个形状和arr1相同的全为10的数组
# arange() - 类似于range()
print(np.arange(10))
# out:[0 1 2 3 4 5 6 7 8 9]
一个ndarray数组的每个元素都是相同类型,每一个数组都有一个shape属性,用来表征数组每一维度的数量
每一个数组都有一个dtype属性,用来表述数组的数据类型
import numpy as np
data = np.random.randn(2, 3)
print(data.shape)
print(data.dtype)
2.ndarray数组生成函数和数据类型
数组生成函数:https://blog.csdn.net/weixin_37887248/article/details/81779405
常用:array、asarray、arange、eye
数据类型:
bool_ | 布尔型数据类型(True 或者 False) |
int_ | 默认的整数类型(类似于 C 语言中的 long,int32 或 int64) |
intc | 与 C 的 int 类型一样,一般是 int32 或 int 64 |
intp | 用于索引的整数类型(类似于 C 的 ssize_t,一般情况下仍然是 int32 或 int64) |
int8 | 字节(-128 to 127) |
int16 | 整数(-32768 to 32767) |
int32 | 整数(-2147483648 to 2147483647) |
int64 | 整数(-9223372036854775808 to 9223372036854775807) |
uint8 | 无符号整数(0 to 255) |
uint16 | 无符号整数(0 to 65535) |
uint32 | 无符号整数(0 to 4294967295) |
uint64 | 无符号整数(0 to 18446744073709551615) |
float_ | float64 类型的简写 |
float16 | 半精度浮点数,包括:1 个符号位,5 个指数位,10 个尾数位 |
float32 | 单精度浮点数,包括:1 个符号位,8 个指数位,23 个尾数位 |
float64 | 双精度浮点数,包括:1 个符号位,11 个指数位,52 个尾数位 |
complex_ | complex128 类型的简写,即 128 位复数 |
complex64 | 复数,表示双 32 位浮点数(实数部分和虚数部分) |
complex128 | 复数,表示双 64 位浮点数(实数部分和虚数部分) |
3.数组算术、基础索引和切片
3.1数组算术
numpy允许对数组进行批量化操作而不是使用for循环,称这种特性为向量化
>>> import numpy as np
>>> arr = np.array([[1, 2, 3], [4, 5, 6]])
>>> arr
array([[1, 2, 3],
[4, 5, 6]])
>>> arr * arr
array([[ 1, 4, 9],
[16, 25, 36]])
>>> arr + arr
array([[ 2, 4, 6],
[ 8, 10, 12]])
>>> arr - arr
array([[0, 0, 0],
[0, 0, 0]])
带有标量计算的算术操作,会把计算参数传递给数组的每一个元素
>>> 1/arr
array([[1. , 0.5 , 0.33333333],
[0.25 , 0.2 , 0.16666667]])
>>> np.sqrt(arr)
array([[1. , 1.41421356, 1.73205081],
[2. , 2.23606798, 2.44948974]])
两个数组可以进行比较:
>>> arr > arr2
array([[False, False, False],
[False, False, False]])
>>> arr2 > arr
array([[ True, True, True],
[ True, True, True]])
3.2一维数组索引
数组的索引和python中对列表的操作类似
>>> import numpy as np
>>> arr = np.arange(10)
>>> arr
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> arr[5:8] = 12
>>> arr
array([ 0, 1, 2, 3, 4, 12, 12, 12, 8, 9])
所有的数组切片和重新赋值的操作都直接反映在原数组上,因为Numpy被设计成用来处理大量数据,因此执行复制操作有时候是不明智的
举例子:例子中的arr_slice[1]的改变直接会反映在arr1中
>>> arr_slice = arr1[5:8]
>>> arr_slice
array([5, 6, 7])
>>> arr_slice[1] = 100
>>> arr1
array([ 0, 1, 2, 3, 4, 5, 100, 7, 8, 9])
如果使用[:]是选中全部元素
>>> arr2 = np.arange(10)
>>> arr2
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> arr2[:] = 100
>>> arr2
array([100, 100, 100, 100, 100, 100, 100, 100, 100, 100])
如果要得到复制的数组,需要使用copy()
>>> arr_copy = arr2[5:8].copy()
>>> arr_copy
array([100, 100, 100])
3.3二维数组以及高维数组索引
索引的方式基本差不多
>>> arr2d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
>>> arr2d
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
>>> arr2d.shape
(3, 3)
>>> arr2d[1][2]
6
>>> arr2d[1, 2]
6
3.4二维数组的切片
索引中逗号前面代表行,后面代表列,然后是各行各列的起点和终点
注意:使用 0:总长 才能完整取到行或列的所有部分(或者直接使用一个冒号 : )
>>> arr2d
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
>>> arr2d[:2]
array([[1, 2, 3],
[4, 5, 6]])
>>> arr2d[1:]
array([[4, 5, 6],
[7, 8, 9]])
>>> arr2d[1, 1:2]
array([5])
>>> arr2d[1, 0:2]
array([4, 5])
>>> arr2d[2, 0:3]
array([7, 8, 9])
>>>
4.布尔索引
假设有一个序列是包含许多元素,其中含有相同的元素,要求查看每一个元素是不是所要求的一个元素
假设有一个name序列,可以通过布尔索引来得到一个真值序列
>>> import numpy as np
>>> name = np.array(['a', 'b', 'c', 'd', 'a', 'e', 'f', 'g'])
>>> name == 'a'
array([ True, False, False, False, True, False, False, False])
甚至还可以在索引数组的时候使用布尔索引,这样就可以将数组中的数据和另一个数组对应起来了
>>> data
array([[ 1.24499916, 1.09219008, 0.54067091, -0.54060987, -0.38934891],
[ 1.67435833, 1.25077416, -0.2711316 , 0.92815044, 0.25917165],
[-0.34178734, -0.32582264, -0.31516525, -0.50118741, -0.4396202 ],
[-1.00490801, -1.0432731 , -0.08440476, 0.34410518, 0.4288193 ],
[-0.19588292, -0.44508004, 1.29878205, 0.74319183, -1.21645021],
[ 0.07012634, -1.48510403, -0.50732563, -0.42672358, 0.85432296],
[-0.44631006, 0.44129148, -1.97539492, -0.46876121, -0.58529733],
[ 0.37695035, -0.48498234, 0.61066879, 1.42635512, -0.28060154]])
>>> data[name == 'a']
array([[ 1.24499916, 1.09219008, 0.54067091, -0.54060987, -0.38934891],
[-0.19588292, -0.44508004, 1.29878205, 0.74319183, -1.21645021]])
注意:最好保证在使用布尔索引对数组进行索引的时候,数组的长度要和布尔索引的数组的长度尽量保证一致
还可以使用其他条件表达式来对条件进行修改:!=、~
当同时满足多个条件的时候,可以使用 &、| 等逻辑操作符来表示(不能使用and和or)
布尔索引的结果总是生成数据的拷贝
5.神奇索引
神奇索引是NumPy中的术语,用于表述使用整数数组进行数据索引
利用神奇索引可以简单得到符合特定顺序的子集,甚至可以使用负的索引,将从尾部进行选择
>>> import numpy as np
>>> arr = np.empty((8, 4))
>>> for i in range(8):
arr[i] = i
>>> arr
array([[0., 0., 0., 0.],
[1., 1., 1., 1.],
[2., 2., 2., 2.],
[3., 3., 3., 3.],
[4., 4., 4., 4.],
[5., 5., 5., 5.],
[6., 6., 6., 6.],
[7., 7., 7., 7.]])
>>> arr[[4, 3, 0, 6]]
array([[4., 4., 4., 4.],
[3., 3., 3., 3.],
[0., 0., 0., 0.],
[6., 6., 6., 6.]])
>>> arr[[-1, -3, -4, -2]]
array([[7., 7., 7., 7.],
[5., 5., 5., 5.],
[4., 4., 4., 4.],
[6., 6., 6., 6.]])
如果传递多个数组,就会索引出相应位置的元素
>>> arr[[1, 2, 4, 3], [2, 3, 2 ,1]]
array([1., 2., 4., 3.])
利用神奇索引可以得到矩阵数组中行列的子集所形成的矩形区域
例如:按照顺序选择arr中的1,7,2,5行中的前三行,列按照0,3,1,2列的顺序进行排列
>>> arr
array([[0., 0., 0., 0.],
[1., 1., 1., 1.],
[2., 2., 2., 2.],
[3., 3., 3., 3.],
[4., 4., 4., 4.],
[5., 5., 5., 5.],
[6., 6., 6., 6.],
[7., 7., 7., 7.]])
>>> arr[[1, 7, 2, 5]][:3, [0, 3, 1, 2]]
array([[1., 1., 1., 1.],
[7., 7., 7., 7.],
[2., 2., 2., 2.]])
注意:神奇索引和切片不同,神奇索引总是返回数组的复制
6.数组的转置和换轴
对于简单的二维数组,可以直接使用T方法来得到转置数组
>>> arr
array([[ 2.59891831, 1.10909321, -0.26387971, 0.45109993, 0.38430929,
-0.17000843],
[-0.3513787 , -2.77342207, 0.82158585, -1.02533 , -0.10216791,
0.3577984 ],
[-1.33538454, 0.60345409, -0.03928757, -1.13104679, 1.59398506,
-0.39949191],
[ 2.6306111 , 0.17122034, 0.09058392, -1.21850954, -1.0320289 ,
0.61513253]])
>>> arr.T
array([[ 2.59891831, -0.3513787 , -1.33538454, 2.6306111 ],
[ 1.10909321, -2.77342207, 0.60345409, 0.17122034],
[-0.26387971, 0.82158585, -0.03928757, 0.09058392],
[ 0.45109993, -1.02533 , -1.13104679, -1.21850954],
[ 0.38430929, -0.10216791, 1.59398506, -1.0320289 ],
[-0.17000843, 0.3577984 , -0.39949191, 0.61513253]])
对于更高维度的数组,transpose方法可以接受包含轴编号的远足,用于置换轴
>>> arr = arr.reshape((2, 3, 4))
>>> arr
array([[[ 2.59891831, 1.10909321, -0.26387971, 0.45109993],
[ 0.38430929, -0.17000843, -0.3513787 , -2.77342207],
[ 0.82158585, -1.02533 , -0.10216791, 0.3577984 ]],
[[-1.33538454, 0.60345409, -0.03928757, -1.13104679],
[ 1.59398506, -0.39949191, 2.6306111 , 0.17122034],
[ 0.09058392, -1.21850954, -1.0320289 , 0.61513253]]])
>>> arr.transpose((1, 0, 2))
array([[[ 2.59891831, 1.10909321, -0.26387971, 0.45109993],
[-1.33538454, 0.60345409, -0.03928757, -1.13104679]],
[[ 0.38430929, -0.17000843, -0.3513787 , -2.77342207],
[ 1.59398506, -0.39949191, 2.6306111 , 0.17122034]],
[[ 0.82158585, -1.02533 , -0.10216791, 0.3577984 ],
[ 0.09058392, -1.21850954, -1.0320289 , 0.61513253]]])
使用.T进行转置是环洲的一个特殊案例,ndarray有一个swapaxes方法,接收一对轴编号作为参数,并且对轴进行调整
>>> arr.reshape(2, 2, 4)
array([[[ 0.09717629, -2.17543887, 0.09990871, 1.49023416],
[-1.27141933, -1.89522406, -0.02287714, -2.0027277 ]],
[[ 1.49565981, 0.16066713, -1.30763266, -0.18619576],
[ 0.98093828, -0.50549868, 0.29650228, -1.24413866]]])
>>> arr.swapaxes(0, 1)
array([[ 0.09717629, -1.27141933, 1.49565981, 0.98093828],
[-2.17543887, -1.89522406, 0.16066713, -0.50549868],
[ 0.09990871, -0.02287714, -1.30763266, 0.29650228],
[ 1.49023416, -2.0027277 , -0.18619576, -1.24413866]])