NumPy数据类型体系
前面我们说过用dtype来指定数据的类型,有时我们会查看一个数组是属于哪一类,我们可以利用np.issubdtype函数来查看这个值是否属于这一类,而且还可以利用mro方法来查看其所有父类。
test = np.ones(5,dtype=np.int32)
print(np.issubdtype(test.dtype,np.signedinteger))
print(np.int32.mro())
#True
#[<class 'numpy.int32'>, <class 'numpy.signedinteger'>, <class 'numpy.integer'>, <class 'numpy.number'>, <class 'numpy.generic'>, <class 'object'>]
NumPy的dtype体系如下。
高级数组操作
数组重塑
前面已经介绍了reshape函数,用于重新排列一个矩阵。这里需要注意两点,1、作为参数的形状的其中一维可以是-1,它表示该维度的大小由数据本身推断而来;2、由于数组的shape属性是一个元组,由此它可以被传入reshape。
test = np.random.randn(15)
arr = test.reshape(5,-1)
print(np.shape(arr)) #(5, 3)
test2 = np.ones((3,5))
arr2 = test.reshape(test2.shape)
print(np.shape(arr2)) #(3, 5)
与reshape相反的是将数组扁平化(flattening)或散开(raveling)。
ravel()与flatten()都是将多维数组展开成一维数组,不同之处在于ravel不会复制数据,对于展开数据的修改会影响到源数据;flatten会复制数据,对展开数据的修改不会影响到源数据。
test = np.random.randn(4)
arr = test.reshape(2,-1)
print(np.shape(arr))
#(2, 2)
arr2 = arr.ravel()
print(np.shape(arr2))
print(arr2)
arr2[1] = 100
print(arr2)
print(arr)
# (4,)
# [-0.87697998 0.81408269 0.61206994 -3.11872329]
# [ -0.87697998 100. 0.61206994 -3.11872329]
# [[ -0.87697998 100. ]
# [ 0.61206994 -3.11872329]]
arr3 = arr.flatten()
print(np.shape(arr3))
arr3[0] = 1000
print(arr3)
print(arr)
# (4,)
# [ 1.00000000e+03 1.00000000e+02 6.12069936e-01 -3.11872329e+00]
# [[ -0.87697998 100. ]
# [ 0.61206994 -3.11872329]]
数组的合并与拆分
numpy.concatenate可以按指定轴将一个由数组组成的序列(如元组、列表等)连接到一起。主要就是按照行方向或列方向的区别。
arr1 = np.array([[1,2,3],[4,5,6]])
arr2 = np.array([[7,8,9],[3,4,5]])
print(np.concatenate([arr1,arr2],axis=0))
print(np.concatenate([arr1,arr2],axis=1))
print(np.vstack((arr1,arr2)))
print(np.hstack((arr1,arr2)))
# [[1 2 3]
# [4 5 6]
# [7 8 9]
# [3 4 5]]
# [[1 2 3 7 8 9]
# [4 5 6 3 4 5]]
# [[1 2 3]
# [4 5 6]
# [7 8 9]
# [3 4 5]]
# [[1 2 3 7 8 9]
# [4 5 6 3 4 5]]
元素的重复操作:tile和repeat
arr = np.arange(3)
print(arr)
print(arr.repeat(3))
print(arr.repeat([1,3,9]))
print(np.tile(arr,2))
# [0 1 2]
# [0 0 0 1 1 1 2 2 2]
# [0 1 1 1 2 2 2 2 2 2 2 2 2]
# [0 1 2 0 1 2]
花式索引的等价函数:take和put
arr = np.arange(6)*10
inds = [5,1,3,0]
print(arr[inds])
print(arr.take(inds))
print(arr)
np.put(arr,inds,666)
print(arr)
# [50 10 30 0]
# [50 10 30 0]
# [ 0 10 20 30 40 50]
# [666 666 20 666 40 666]
广播
广播指的是不同形状的数组之间的算术运算的执行方式。当两者的形状相同时,就会每个对应的值进行运算,当不同的形状运算时,就会出发广播机制。
如果两个数组的后缘维度(trailing dimension,即从末尾开始算起的维度)的轴长度相符,或其中的一方的长度为1,则认为它们是广播兼容的。广播会在缺失和(或)长度为1的维度上进行。
广播主要发生在两种情况,一种是两个数组的维数不相等,但是它们的后缘维度的轴长相符,另外一种是有一方的长度为1。
结构化和记录式数组
目前看到的ndarray都是每个数组都是存放同一类型的数据。那么ndarray怎么存放不同的数据呢?它的结构类似于C语言的结构体,如下所示。
dtype = [('x',np.float64),('y',np.int32)]
sarr = np.array([(1.6,3),(np.pi,-2)],dtype=dtype )
print(sarr)
print(sarr[0])
print(sarr['x'])
print(sarr[0]['y'])
# [(1.6 , 3) (3.14159265, -2)]
# (1.6, 3)
# [1.6 3.14159265]
# 3
《利用python进行数据分析》