上一篇主要介绍了ndarray对象的一些基本属性以及创建ndarray对象的一些非常常用的方法。接下来主要介绍ndarray对象比较常用的对象方法。需要注意的是,以下ndarray对象方法也是numpy中的函数:all, any, argmax, argmin, argpartition, argsort, choose, clip, compress, copy, cumprod, cumsum, diagonal, imag, max, mean, min, nonzero, partition, prod, ptp, put, ravel, real, repeat, reshape, round, searchsorted, sort, squeeze, std, sum, swapaxes, take, trace, transpose, var
。
1 数组转换方法
常用方法 | 功能 |
---|---|
ndarray.item(*args) | 复制数组中的一个元素,并返回 |
ndarray.tolist() | 将数组转换成python标准list |
ndarray.itemset(*args) | 修改数组中某个元素的值 |
ndarray.tostring([order]) | 构建一个包含ndarray的原始字节数据的字节字符串 |
ndarray.tobytes([order]) | 功能同tostring |
ndarray.byteswap(inplace) | 将ndarray中每个元素中的字节进行大小端转换 |
ndarray.copy([order]) | 复制数组并返回(深拷贝) |
ndarray.fill(value) | 使用值value填充数组 |
示例:
>>> a = np.random.randint(12, size=(3,4))
>>> a
array([[11, 1, 0, 11],
[11, 0, 4, 6],
[ 0, 1, 6, 7]])
>>> a.item(7) #获取第7个元素
6
>>> a.item((1, 2)) #获取元组对应的元素
4
>>> a.itemset(7, 111) #设置元素
>>> a
array([[ 11, 1, 0, 11],
[ 11, 0, 4, 111],
[ 0, 1, 6, 7]])
>>> a.itemset((1, 2), 12)
>>> a
array([[ 11, 1, 0, 11],
[ 11, 0, 12, 111],
[ 0, 1, 6, 7]])
>>> a.tolist() #返回python标准列表,
[[11, 1, 0, 11], [11, 0, 4, 6], [0, 1, 6, 7]]
>>> a.tostring()
'\x0b\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0b\x00\x00\x00\x00\x00\x00\x00\x0b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\x00\x00\x00\x00'
>>> b = a.copy() #深拷贝,b与a是两个无关的数组
>>> b[0,0] = 10
>>> b
array([[10, 1, 0, 11],
[11, 0, 4, 6],
[ 0, 1, 6, 7]])
>>> a
array([[11, 1, 0, 11],
[11, 0, 4, 6],
[ 0, 1, 6, 7]])
>>> b.fill(9)
>>> b
array([[9, 9, 9, 9],
[9, 9, 9, 9],
[9, 9, 9, 9]])
>>> a.byteswap() #元素大小端转换,a不变
array([[ 792633534417207296, 72057594037927936, 0,
792633534417207296],
[ 792633534417207296, 0, 864691128455135232,
7998392938210000896],
[ 0, 72057594037927936, 432345564227567616,
504403158265495552]])
>>> a
array([[ 11, 1, 0, 11],
[ 11, 0, 12, 111],
[ 0, 1, 6, 7]])
>>> a.byteswap(True) #原地转换,a被修改
array([[ 792633534417207296, 72057594037927936, 0,
792633534417207296],
[ 792633534417207296, 0, 864691128455135232,
7998392938210000896],
[ 0, 72057594037927936, 432345564227567616,
504403158265495552]])
>>> a
array([[ 792633534417207296, 72057594037927936, 0,
792633534417207296],
[ 792633534417207296, 0, 864691128455135232,
7998392938210000896],
[ 0, 72057594037927936, 432345564227567616,
504403158265495552]])
如下几个方法:ndarray.tofile, ndarray.dump, ndarray.dumps, ndarray.astype, ndarray.view, ndarray.getfield, ndarray.setflags
,还没有用过,暂时不对其进行详细介绍,等用到了在补充。关于这些方法的详细介绍可以查阅numpy的官方文档。
2 形状操作
常用方法 | 功能 |
---|---|
ndarray.reshape(shape[,order]) | 返回一个具有相同数据域,但shape不一样的视图 |
ndarray.resize(new_shape[,orefcheck]) | 原地修改数组的形状(需要保持元素个数前后相同) |
ndarray.transpose(*axes) | 返回数组针对某一轴进行转置的视图 |
ndarray.swapaxes(axis1, asix2) | 返回数组axis1轴与axis2轴互换的视图 |
ndarray.flatten([order]) | 返回将原数组压缩成一维数组的拷贝(全新的数组) |
ndarray.ravel([order]) | 返回将原数组压缩成一维数组的视图 |
ndarray.squeeze([axis]) | 返回将原数组中的shape中axis==1的轴移除之后的视图 |
注意事项!!!
上述方法中,除resize
、flatten
外其他的方法返回的都是原数组修改shape或者axes之后的视图,也就是说,对返回数组中的元素进行修改,原数组中对应的元素也会被修改(因为它们是公用同一个数据域的)。同时,resize
方法会修改原数组的shape属性,其他方法不会修改原数组任何内部数据。
示例:
>>> x = np.arange(0,12)
>>> x
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
>>> x_reshape = x.reshape((3,4))
>>> x_reshape
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
>>> x_reshape[0,0] = 10 #修改返回数组的元素,直接影响原数组中的元素值(数据域是相同的)
>>> x
array([10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
>>> x[0,0] = 0
>>> x.resize((3,4)) #resize没有返回值,会直接修改数组的shape,如下所示
>>> x
array([[10, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
>>> x_transpose = x.transpose() #对于二维数组,返回数组的转置
>>> x_transpose
array([[ 0, 4, 8],
[ 1, 5, 9],
[ 2, 6, 10],
[ 3, 7, 11]])
>>> x.resize(2,2,3)
>>> x
array([[[ 0, 1, 2],
[ 3, 4, 5]],
[[ 6, 7, 8],
[ 9, 10, 11]]])
>>> x.swapaxes(0,2) #本质上还是修改strides以及shape
array([[[ 0, 6],
[ 3, 9]],
[[ 1, 7],
[ 4, 10]],
[[ 2, 8],
[ 5, 11]]])
>>> x.swapaxes(0,2).strides #互换strides中第0、2位置上的数值
(8, 24, 48)
>>> x.strides
(48, 24, 8)
>>> x
array([[[ 0, 1, 2],
[ 3, 4, 5]],
[[ 6, 7, 8],
[ 9, 10, 11]]])
>>> y = x.flatten() #返回一个全新的数组
>>> y
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
>>> y[0] = 100
>>> y
array([100, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
>>> x #修改y中元素的值,不影响x中的元素
array([[[ 0, 1, 2],
[ 3, 4, 5]],
[[ 6, 7, 8],
[ 9, 10, 11]]])
>>> x_ravel = x.ravel() #与flatten类似,但是返回的是原数组的视图,数据域是相同的
>>> x_ravel
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
>>> x.resize((1,2,2,3,1))
>>> x
array([[[[[ 0],
[ 1],
[ 2]],
[[ 3],
[ 4],
[ 5]]],
[[[ 6],
[ 7],
[ 8]],
[[ 9],
[10],
[11]]]]])
>>> x.squeeze() #移除shape中值为1的项
array([[[ 0, 1, 2],
[ 3, 4, 5]],
[[ 6, 7, 8],
[ 9, 10, 11]]])
>>> x.shape
(1, 2, 2, 3, 1)
>>> x.squeeze().shape
(2, 2, 3)
tips: transpose
-
transpose
的本质是按照参数axes
修改了strides
以及shape
属性(自己的理解):
1)提供axes,按照axes中提供的各个轴的新位置调整strides
属性中对应位置上的值
2)不提供axes,取原strides
的对称形式作为返回数组的strides
属性
3)shape
属性也是按照上述方式修改
示例:
>>> x #先看二维的情形
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
>>> x.transpose() #不提供axes,等同于x.transpose((1, 0))
array([[ 0, 4, 8],
[ 1, 5, 9],
[ 2, 6, 10],
[ 3, 7, 11]])
>>> x.strides
(32, 8)
>>> x.transpose().strides
(8, 32)
>>> x.transpose((0,1)) #提供axes,各个轴的位置没有变化,结果与x是一样的
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
>>> x.transpose((0,1)).strides #strides参数也没有变化
(32, 8)
>>> y #再看三维的情形
array([[[ 0, 1, 2],
[ 3, 4, 5]],
[[ 6, 7, 8],
[ 9, 10, 11]]])
>>> y.transpose() #不带axes参数,等同于y.transpose((2,1,0))
array([[[ 0, 6],
[ 3, 9]],
[[ 1, 7],
[ 4, 10]],
[[ 2, 8],
[ 5, 11]]])
>>> y.transpose().strides
(8, 24, 48)
>>> y.strides
(48, 24, 8)
>>> y.transpose((2,0,1)) #带axes参数
array([[[ 0, 3],
[ 6, 9]],
[[ 1, 4],
[ 7, 10]],
[[ 2, 5],
[ 8, 11]]])
>>> y.transpose((2,0,1)).strides #注意strides各个参数的位置与原来strides参数的位置,正好是转置时axes的对应位置
(8, 48, 24)
- 不提供axes参数时,转换前后shape、strides以及数据有如下关系:
1)转置前a.shape=(i[0], i[1], ..., i[n-2], i[n-1])
,转置后的:a.transpose().shape=(i[n-1], i[n-2], ..., i[1], i[0])
2)转置前``a.strides=(j[0], j[1], ..., j[n-2], j[n-1]),转置后:
a.transpose().strides=(j[n-1], j[n-2], ..., j[1], j[0])3)数据:
a[i[0], i[1], ..., i[n-2], i[n-1]] == a.transpose()[i[n-1], i[n-2], ..., i[1], i[0]]` - 思考提供axes参数时,上述关系是怎样的?
3 计算
关于ndarray对象的很多计算方法都有一个axis
参数,它有如下作用:
- 当
axis=None
(默认)时,数组被当成一个一维数组,对数组的计算操作是对整个数组进行的,比如sum
方法,就是求数组中所有元素的和; - 当
axis
被指定为一个int整数时,对数组的计算操作是以提供的axis
轴进行的。
示例:
>>> a
array([[[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]],
[[12, 13, 14, 15],
[16, 17, 18, 19],
[20, 21, 22, 23]]])
>>> a.sum(0) #等价于a[0,:,:] + a[1,:,:]
array([[12, 14, 16, 18],
[20, 22, 24, 26],
[28, 30, 32, 34]])
>>> a.sum(1) #等价于a[:,0,:] + a[:,1,:] + a[:,2,:]
array([[12, 15, 18, 21],
[48, 51, 54, 57]])
>>> a.sum(2) #等价于a[:,:,0]+a[:,:,1]+a[:,:,2]+a[:,:,3]
array([[ 6, 22, 38],
[54, 70, 86]])
常用方法 | 功能 |
---|---|
ndarray.max([axis, out, keepdims]) | 返回根据指定的axis计算最大值 |
ndarray.argmax([axis, out]) | 返回根据指定axis计算最大值的索引 |
ndarray.min([axis, out, keepdims]) | 返回根据指定的axis计算最小值 |
ndarray.argmin([axis, out]) | 返回根据指定axis计算最小值的索引 |
ndarray.ptp([axis, out]) | 返回根据指定axis计算最大值与最小值的差 |
ndarray.clip([min, max, out]) | 返回数组元素限制在[min, max]之间的新数组(小于min的转为min,大于max的转为max) |
ndarray.round([decimals, out]) | 返回指定精度的数组(四舍五入) |
ndarray.trace([offset, axis1, axis2, dtype, out]) | 返回数组的迹(对角线元素的和) |
ndarray.sum([axis, dtype, out, keepdims]) | 根据指定axis计算数组的和,默认求所有元素的和 |
ndarray.cumsum([axis, dtype, out]) | 根据指定axis计算数组的累积和 |
ndarray.mean([axis, dtype, out, keepdims]) | 根据指定axis计算数组的平均值 |
ndarray.var([axis, dtype, out, ddof, keepdims]) | 根据指定的axis计算数组的方差 |
ndarray.std([axis, dtype, out, ddof, keepdims]) | 根据指定axis计算数组的标准差 |
ndarray.prod([axis, dtype, out, keepdims]) | 根据指定axis计算数组的积 |
ndarray.cumprod([axis, dtype, out]) | 根据指定axis计算数据的累计积 |
ndarray.all([axis, dtype, out]) | 根据指定axis判断所有元素是否全部为真 |
ndarray.any([axis, out, keepdims]) | 根据指定axis判断是否有元素为真 |
>>> a
array([[2, 3, 4, 9],
[8, 7, 6, 5],
[4, 3, 5, 8]])
>>> a.max()
9
>>> a.max(axis=0) #shape=(4,),即原shape去掉第0个axis
array([8, 7, 6, 9])
>>> a.max(axis=1) #shape=(3,),即原shape去掉第1个axis
array([9, 8, 8])
>>> a.argmax()
3
>>> a.argmax(axis=0)
array([1, 1, 1, 0])
>>> a.argmax(axis=1)
array([3, 0, 3])
>>> b = a.flatten()
>>> b
array([2, 3, 4, 9, 8, 7, 6, 5, 4, 3, 5, 8])
>>> b.clip(3, 5) #数组元素限定在[3, 5]之间
array([3, 3, 4, 5, 5, 5, 5, 5, 4, 3, 5, 5])
>>> a.resize((2,2,3))
>>> a
array([[[2, 3, 4],
[9, 8, 7]],
[[6, 5, 4],
[3, 5, 8]]])
>>> a.trace(0,axis=0, axis=1) #等同于[trace(a[:,:,0]), trace(a[:,:,1], trace(a[:,:,2])];shape=(3,),即原shape去掉第0,1个axis
array([ 5, 8, 12])
>>> np.eye(3).trace() #对角线元素的和
3.0
>>> b.reshape((3,4))
array([[2, 3, 4, 9],
[8, 7, 6, 5],
[4, 3, 5, 8]])
>>> b.reshape((3,4)).std(0)
array([ 2.49443826, 1.88561808, 0.81649658, 1.69967317])
>>> b.reshape((3,4)).std(1)
array([ 2.6925824 , 1.11803399, 1.87082869])
>>> x = np.arange(8)
>>> x
array([0, 1, 2, 3, 4, 5, 6, 7])
>>> x.cumsum() #累计和
array([ 0, 1, 3, 6, 10, 15, 21, 28])
>>> x = np.arange(1,9)
>>> x
array([1, 2, 3, 4, 5, 6, 7, 8])
>>> x.cumprod() #累计积
array([ 1, 2, 6, 24, 120, 720, 5040, 40320])
4 选择元素以及操作
常用方法 | 方法功能 |
---|---|
ndarray.take(indices[, axis, out, model]) | 从原数组中根据指定的索引获取对应元素,并构成一个新的数组返回 |
ndarray.put(indices, values[, mode]) | 将数组中indices指定的位置设置为values中对应的元素值 |
ndarray.repeat(repeats[, axis]) | 根据指定的axis重复数组中的元素 |
ndarray.sort([axis, kind, order]) | 原地对数组元素进行排序 |
ndarray.argsort([axis, kind, order]) | 返回对数组进行升序排序之后的索引 |
ndarray.partition(kth[, axis, kind, order]) | 将数组重新排列,所有小于kth的值在kth的左侧,所有大于或等于kth的值在kth的右侧 |
ndarray.argpartition(kth[, axis, kind, order]) | 对数组执行partition之后的元素索引 |
ndarray.searchsorted(v[, side, sorter]) | 若将v插入到当前有序的数组中,返回插入的位置索引 |
ndarray.nonzero() | 返回数组中非零元素的索引 |
ndarray.diagonal([offset, axis1, axis2]) | 返回指定的对角线 |
>>> a
array([2, 3, 4, 9, 8, 7, 6, 5, 4, 3, 5, 8])
>>> a.take([0,3,6])
array([2, 9, 6])
>>> a.take([[2, 5], [3,6]]) #返回数组的形状与indices形状相同
array([[4, 7],
[9, 6]])
>>> a.put([0, -1], [0, 111])
>>> a
array([ 0, 3, 4, 9, 8, 7, 6, 5, 4, 3, 5, 111])
>>> a.sort() #原地排序
>>> a
array([ 0, 3, 3, 4, 4, 5, 5, 6, 7, 8, 9, 111])
>>> b
array([ 0, 3, 4, 9, 8, 7, 6, 5, 4, 3, 5, 111])
>>> b_idx = b.argsort() #获取排序索引
>>> b_idx
array([ 0, 1, 9, 2, 8, 7, 10, 6, 5, 4, 3, 11])
>>> b[b_idx] #根据排序索引获取b中元素,正好是排序好的
array([ 0, 3, 3, 4, 4, 5, 5, 6, 7, 8, 9, 111])
>>> c
array([ 0, 3, 4, 9, 8, 7, 6, 5, 4, 3, 5, 111])
>>> c.partition(5)
>>> c
array([ 3, 4, 4, 0, 3, 5, 6, 5, 7, 8, 9, 111])
>>> a
array([ 0, 3, 3, 4, 4, 5, 5, 6, 7, 8, 9, 111])
>>> a.searchsorted(2)
1
>>> a.searchsorted(10)
11
>>> a.searchsorted(3) #side默认为lift
1
>>> a.searchsorted(3, side="right")
3
>>> e = np.eye(4)
>>> e
array([[ 1., 0., 0., 0.],
[ 0., 1., 0., 0.],
[ 0., 0., 1., 0.],
[ 0., 0., 0., 1.]])
>>> e.nonzero()
(array([0, 1, 2, 3]), array([0, 1, 2, 3]))
>>> e[e.nonzero()]
array([ 1., 1., 1., 1.])
>>> a = np.arange(4).reshape(2,2)
>>> a
array([[0, 1],
[2, 3]])
>>> a.diagonal() #二维数组取对角线元素
array([0, 3])
>>> a = np.arange(8).reshape(2,2,2)
>>> a
array([[[0, 1],
[2, 3]],
[[4, 5],
[6, 7]]])
>>> a.diagonal(offset=0, axis1=0, axis2=1) #三维数组根据指定axis取对角线,本质是取下面两个二维数组的对角线
array([[0, 6],
[1, 7]])
>>> a[:,:,0] #对角线[0, 6]
array([[0, 2],
[4, 6]])
>>> a[:,:,1] #对角线[1, 7]
array([[1, 3],
[5, 7]])
>>> a.diagonal(offset=0, axis1=0, axis2=2)
array([[0, 5],
[2, 7]])
>>> a[:,0,:]
array([[0, 1],
[4, 5]])
>>> a[:,1,:]
array([[2, 3],
[6, 7]])
>>> a.diagonal(offset=0, axis1=1, axis2=2)
array([[0, 3],
[4, 7]])
>>> a[0,:,:]
array([[0, 1],
[2, 3]])
>>> a[1,:,:]
array([[4, 5],
[6, 7]])