NumPy的核心特征之一就是N-维数组对象—— ndarray。ndarray是Python中一个快速、灵活的大型数据集容器,数组允许你使用类似于标量的操作语法在整块数据上进行数学计算。
一个ndarray是一个通用的多维同类数据容器,也就是说,它包含的每一个元素均为相同类型。每一个数组都有一个shape
属性,用来表征数组每一维度的数量;每一个数组都有一个dtype
属性,用来描述数组的数据类型。
“数组”、“NumPy数组”或“ndarray”时,他们都表示同一个对象:ndarray对象。
一、生成ndarray
生成数组最简单的方式就是使用array
函数。array函数接收任意的序列型对象(当然也包括其他的数组),生成一个新的包含传递数据的NumPy数组:
data = [1, 2, 3, 4, 5]
arr = np.array(data)
arr # 结果:array([1, 2, 3, 4, 5])
如果是嵌套序列,例如同等长度的列表,将会自动转换成多维数组:
data = [[1, 2, 3, 4, 5], [1, 2, 3, 4, 5]]
arr = np.array(data)
arr # 结果:array([[1, 2, 3, 4, 5],
[1, 2, 3, 4, 5]])
arr.shape # 结果:(2, 5)
除了np.array
,还有很多其他函数可以创建新数组。例如,给定长度及形状后,zeros
可以一次性创造全0数组,ones
可以一次性创造全1数组。empty
则可以创建一个没有初始化数值的数组。
arange
是Python内建函数range
的数组版:
np.arange(10) # 结果:array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
二、ndarray的数据类型
数据类型,即dytpe,是一个特殊的对象,它包含了ndarray需要为某一种类型数据所申明的内存块信息(也称为元数据,即表示数据的数据):
data = [[1, 2, 3, 4, 5], [1, 2, 3, 4, 5]]
arr = np.array(data, dtype='float')
arr.dtype # 结果:dtype('float64')
可以使用astype
方法显式地转换数组的数据类型:
data = [[1, 2, 3, 4, 5], [1, 2, 3, 4, 5]]
arr1 = np.array(data, dtype='float')
arr2 = arr1.astype(np.int32)
arr2.dtype # 结果:dtype('int32')
要注意,传入astype
的最好是np.int32
之类的,而不是np.int
,否则会有警告。
三、索引和切片
3.1 一维数组的索引
一维数组比较简单,看起来和Python的列表很类似,但数组的切片是原数组的视图,这意味着数据并不是被复制了,任何对于视图的修改都会反映到原数组上:
a = np.array([1, 2, 3, 4])
b = a[0:2]
b[0] = 0
a # 结果:array([0, 2, 3, 4])
如果想要一份数组切片的拷贝而不是一份视图的话,必须使用copy
显式地复制这个数组:
a = np.array([1, 2, 3, 4])
b = a[0:2].copy()
b[0] = 0
a # 结果:array([1, 2, 3, 4]),未改变原数组
b # 结果:array([0, 2])
3.2 多维数组的索引
在一个二维数组中,每个索引值对应的元素不再是一个值,而是一个一维数组:
a = np.array([[1, 2, 3, 4], [3, 4, 5, 6]])
a # 结果:array([[1, 2, 3, 4],
[3, 4, 5, 6]])
a[0] # 结果:array([1, 2, 3, 4])
有两种方法获取单个元素:
a = np.array([[1, 2, 3, 4], [3, 4, 5, 6]])
a # 结果:array([[1, 2, 3, 4],
[3, 4, 5, 6]])
a[0][2] # 结果:3
a[0, 2] # 结果:3
也可以进行多组切片:
a = np.array([[1, 2, 3, 4], [3, 4, 5, 6], [5, 6, 7, 8]])
a # 结果:array([[1, 2, 3, 4],
[3, 4, 5, 6],
[5, 6, 7, 8]])
a[:2, 1:] # 结果:array([[2, 3, 4],
[4, 5, 6]])
3.3 布尔索引
在索引数组时可以传入布尔值数组,布尔值数组的长度必须和数组轴索引长度一致(当布尔值数组的长度不正确时,布尔值选择数据的方法并不会报错):
a = np.array([[1, 2, 3, 4], [3, 4, 5, 6], [5, 6, 7, 8], [7, 8, 9, 10]])
a # 结果:array([[ 1, 2, 3, 4],
[ 3, 4, 5, 6],
[ 5, 6, 7, 8],
[ 7, 8, 9, 10]])
b = np.array(['dog', 'cat', 'dog', 'pig']) # 如果此处不用数组的话,下面的只会输出False
b == 'dog' # 结果:array([ True, False, True, False])
a[b == 'dog'] # 结果:array([[1, 2, 3, 4],
[5, 6, 7, 8]])
可以在条件表达式前使用~
对条件取反:
a[~(b == 'dog')] # 结果:array([[ 3, 4, 5, 6],
[ 7, 8, 9, 10]])
如果有多个布尔值条件,可以用数学操作符如&(表示并)、|(表示或)连接(每个布尔值条件要用小括号),但不能用and或or:
a[(b == 'dog') | (b == 'pig')] # 结果:array([[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 7, 8, 9, 10]])
也可以基于常识来设置布尔值数组的值,比如将小于5的数都变为5:
a[a < 5] = 5
a # 结果:array([[ 5, 5, 5, 5],
[ 5, 5, 5, 6],
[ 5, 6, 7, 8],
[ 7, 8, 9, 10]])