numpy——基础篇
tile(A,resp)
通过重复resp
结构次数来构造数组A
。就如tile
单词的意思一样,可以想象A
是一块砖,以resp
样式来就行铺设。
In [1]: import numpy as np
In [2]: a = np.array([1,2,3])
# 如果为数字,则在A基础上上重复
In [3]: np.tile(a,2)
Out[3]: array([1, 2, 3, 1, 2, 3])
# 元组(2,1)表示构建一个(2,1)的数组,并以A填充,下同
In [4]: np.tile(a,(2,1))
Out[4]:
array([[1, 2, 3],
[1, 2, 3]])
In [5]: np.tile(a,(2,2))
Out[5]:
array([[1, 2, 3, 1, 2, 3],
[1, 2, 3, 1, 2, 3]])
In [6]: np.tile(a,(1,2))
Out[6]: array([[1, 2, 3, 1, 2, 3]])
In [7]: np.tile(a,(3,2,1))
Out[7]:
array([[[1, 2, 3],
[1, 2, 3]],
[[1, 2, 3],
[1, 2, 3]],
[[1, 2, 3],
[1, 2, 3]]])
当resp
小于原本A
的维度时,则会在保留A
原有维度。
In [10]: b=np.arange(6).reshape([3,2,1])
In [11]: np.tile(b,(2,1))
Out[11]:
array([[[0],
[1],
[0],
[1]],
[[2],
[3],
[2],
[3]],
[[4],
[5],
[4],
[5]]])
数组在有的时候可能会存在无效的或者缺失值。当在这些数组上做一些操作时,我们希望去以我们希望的数值去填充掩盖这些无效的数据。
函数结构如下:
x = MaskedArray( data, mask=nomask, dtype=None, copy=False, subok=True, ndmin=0, fill_value=None, keep_mask=True, hard_mask=None, shrink=True, order=None)
常用参数 | 说明 |
---|---|
data | 数组类型的输入数据 |
mask | 数组形状的布尔类型的掩码 |
dtype | 输出数组元素的数据类型 |
copy | 是否复制输入数组的数据(默认False 为引用) |
fill_value | 必要时用于填充掩码值的值。如果为None,则使用基于数据类型的默认值。 |
keep_mask | 将“ mask”与输入数据的掩码(如果有的话)组合(真),将“ mask”用于输出(假)。默认值为True。 |
hard_msak | 是否使用强mask(不能取消mask),默认(False)不使用。 |
我们可以通过np.ma.masked_array
或np.ma.MaskedArray
创建带有掩码的MaskedArray数组。
In [1]: import numpy as np
In [3]: a = np.array([1,2,3,4,np.nan,6,7,np.nan,9])
In [4]: mask_a = np.ma.masked_array(a,np.isnan(a))
In [5]: mask_a
Out[5]:
masked_array(
data=[1.0, 2.0, 3.0, 4.0, --, 6.0, 7.0, --, 9.0],
mask=[False, False, False, False, True, False, False, True, False],
fill_value=1e+20)
copy,是否复制输入数组的数据(默认False 为引用)
# 默认是False,为引用
# 可以看到当mask_a修改时,a的值也同时修改了
In [3]: a
Out[3]: array([0, 1, 2, 3, 4])
In [4]: mask_a = np.ma.masked_array(a, a < 2)
In [5]: mask_a[0] = 5
In [6]: mask_a
Out[6]:
masked_array(
data=[5, --, 2, 3, 4],
mask=[False, True, False, False, False],
fill_value=999999)
In [7]: a
Out[7]: array([5, 1, 2, 3, 4])
# 现在我们将设为True,为a的副本
# 可以看到当mask_a修改时,a的值没有修改
In [8]: mask_a = np.ma.masked_array(a, a < 2,copy = True)
In [9]: mask_a[0] = 4
In [10]: mask_a
Out[10]:
masked_array(
data=[4, --, 2, 3, 4],
mask=[False, True, False, False, False],
fill_value=999999)
In [11]: a
Out[11]: array([5, 1, 2, 3, 4])
设置默认填充值。填充值不会参与计算
In [14]: a = np.arange(5)
In [15]: mask_a = np.ma.masked_array(a, a< 2, fill_value= 2)
In [16]: mask_a
Out[16]:
masked_array(
data=[--, --, 2, 3, 4],
mask=[ True, True, False, False, False],
fill_value=2)
In [17]: mask_a.mean()
Out[17]: 3.0
In [18]: mask_a.filled()
Out[18]: array([0, 1, 2, 3, 2])
clip(a, a_min, a_max, out=None, **kwargs)
裁剪(限制)数组中的值。
使用clip函数可以控制值的范围,将其限制在最大最小区间内,对于小于最小值和大于最大值的项以设置的最大最小值替代。
In [12]: a = np.arange(10)
In [13]: a
Out[13]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [14]: a.clip(3,7)
Out[14]: array([3, 3, 3, 3, 4, 5, 6, 7, 7, 7])
In [15]: np.clip(a,3,7)
Out[15]: array([3, 3, 3, 3, 4, 5, 6, 7, 7, 7])
In [16]: a
Out[16]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [17]: np.clip(a,3,7,out=a)
Out[17]: array([3, 3, 3, 3, 4, 5, 6, 7, 7, 7])
也可以使用多个不同的最大最小值结合限制数组
In [27]: a
Out[27]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [28]: a.clip([2,0,3,3,3,3,3,3,4,0],7)
Out[28]: array([2, 1, 3, 3, 4, 5, 6, 7, 7, 7])
方法 | 含义 |
---|---|
append | 将值附加到数组的末尾。 |
concatenate、ma.concatenate | 沿现有轴连接一系列数组。保存输入的mask。 |
stack | 沿新轴堆叠一系列数组。 |
block | 从块组合数组。 |
hstack | 沿水平折叠(沿第二维) |
vstack | 垂直顺序排列阵列(沿第一维) |
dstack | 按深度顺序排列数组(沿第三维) |
In [1]: import numpy as np
np.append(arr,values,axis=None)
append是将值添加到数组arr
副本的末尾,如果指定arr
,其中values
是和arr
相同形状的。如果未指定axis
则会默认展平为一维数组。值得注意的是append
不会就地发生,而是分配并填充了一个新数组。 因此,在速度上并不是很快。
默认情况下:
In [2]: a = np.arange(12).reshape(2,3,2)
In [3]: b = np.arange(3)
In [4]: np.append(a,b)
Out[4]: array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
11, 0, 1, 2])
有轴axis
的情况下:
我们可以看到如果制定了轴,上面的a
、b
合并时会报错。这是因为除了指定的轴外,b
上的其它轴必须一致才可以。
In [7]: np.append(a,b,axis = 1)
ValueError: all the input arrays must have same number of dimensions
# a的shape是(2,3,2)、所以如果在axis = 1上合并,
# 则b的shape必须是(2,x,2)的样式。
In [8]: b = np.arange(4).reshape(2,1,2)
In [9]: np.append(a,b,axis = 1)
Out[9]:
array([[[ 0, 1],
[ 2, 3],
[ 4, 5],
[ 0, 1]],
[[ 6, 7],
[ 8, 9],
[10, 11],
[ 2, 3]]])
# 例如下面定义a(1,2),则如果想在axis = 0插入,
# 则b邀为(x,2)的数组才可以
In [13]: a = np.arange(2).reshape(1,2)
In [14]: b = np.arange(4).reshape(2,2)
In [15]: np.append(a,b,axis = 0)
Out[15]:
array([[0, 1],
[0, 1],
[2, 3]])
concatenate((a1, a2, ...), axis=0, out=None)
其中,a1
、a2
等要级联的数组必须是有相同形状的,默认是假设这些数组是三维的,所以如果在轴axis=0
上进行级联,那么a1
、a2
等数组的形状必须是(x, _, _)
。其中只能x
位置可以为不相同的正整数外,其他位置必须一致。
# 默认的是axis = 0
In [13]: a = np.arange(2).reshape(1,2)
In [14]: b = np.arange(4).reshape(2,2)
In [18]: np.concatenate((a,b))
Out[18]:
array([[0, 1],
[0, 1],
[2, 3]])
# 如果想在axis = 1上级联,则是不可以的因为除了
# axis = 1外,形状并不相同。
In [19]: np.concatenate((a,b),axis = 1)
ValueError: all the input array dimensions except for
the concatenation axis must match exactly
# 因此我们将a转置一下就好了。
In [20]: np.concatenate((a.T,b), axis = 1)
Out[20]:
array([[0, 0, 1],
[1, 2, 3]])
当axis
为None
时,合并所有数组元素。
In [21]: np.concatenate((a.T,b),axis = None)
Out[21]: array([0, 1, 0, 1, 2, 3])
值得注意的是,如果你传入的是MaskedArrays
数组,那么使用np.concatenate
是不会保存mask
的。你需要使用np.ma.concatenate
。
In [23]: mask_a
Out[23]:
masked_array(
data=[0, 1, 2, 3, --],
mask=[False, False, False, False, True],
fill_value=2)
In [24]: mask_b
Out[24]:
masked_array(
data=[--, 6, 7, 8, 9],
mask=[True, False, False, False, False],
fill_value=5)
# 使用np.concatenate无法保存mask
In [25]: np.concatenate((mask_a,mask_b))
Out[25]:
masked_array(
data=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
mask=False,
fill_value=999999)
# 使用np.ma.concatenate可以保存mask 但依旧保存不了填充值
In [26]: np.ma.concatenate((mask_a,mask_b))
Out[26]:
masked_array(
data=[0, 1, 2, 3, --, --, 6, 7, 8, 9],
mask=[False, False, False, False, True, True, False, False, False, False],
fill_value=999999)
np.stack(arrays, axis=0, out=None)
沿新轴连接一系列数组。这里的每个数组必须要有相同的形状(沿轴)。axis
指定了新轴的位置。例如,a
和b
的形状都是(3,)。那么a
和b
堆叠后的结果就只能为沿axis=0
得到形状(2,3)或者沿axis=1
得到形状(3,2)这两种情况。
In [8]: a = np.arange(3)
In [9]: b = np.arange(3,6)
In [11]: np.stack((a,b),axis = 0)
Out[11]:
array([[0, 1, 2],
[3, 4, 5]])
In [12]: np.stack((a,b),axis = 1)
Out[12]:
array([[0, 3],
[1, 4],
[2, 5]])
再举一个例子,如果a
和b
是一个形状为(4,3)的数组,那么堆叠起来就有axis=0
,axis=1
,axis=2
分别对应形状(2,4,3),(4,2,3),(4,3,2)这三种。
In [13]: a = np.arange(12).reshape(4,3)
In [14]: b = np.arange(1,13).reshape(4,3)
In [15]: np.stack([a,b],axis = 0).shape
Out[15]: (2, 4, 3)
In [16]: np.stack([a,b],axis = 1).shape
Out[16]: (4, 2, 3)
In [17]: np.stack([a,b],axis = 2).shape
Out[17]: (4, 3, 2)
np.block(arrays)
函数block
就是将数组按块排版。就像下图所示的这样,对于矩阵 [ M ] \begin{bmatrix}M\end{bmatrix} [M],我们可以通过四小块构成: [ A B C D ] \begin{bmatrix} A&B\\ C&D \end{bmatrix} [ACBD]。
In [4]: a = np.arange(4).reshape(2,2)
In [5]: b = np.arange(6).reshape(2,3)
In [6]: c = np.arange(2).reshape(2,1)S
In [7]: d = np.arange(8).reshape(2,4)
In [8]: np.block([[a,b],[c,d]])
Out[8]:
array([[0, 1, 0, 1, 2],
[2, 3, 3, 4, 5],
[0, 0, 1, 2, 3],
[1, 4, 5, 6, 7]])
np.hstack(tup)
hstack
方法等价于concatenate
方法沿着axis=1
级联(1-D数组沿axis=0
)。
hstack
的意思是horizontal stack
即水平堆叠。假设对于两个形状分别为(3,)和(2,)的1-D数组,因此我们只需要在水平轴上拼接即可。得到一个形状为(5,)的数组。In [3]: a = np.arange(3)
In [4]: b = np.arange(2)
In [5]: np.hstack((a,b))
Out[5]: array([0, 1, 2, 0, 1])
a
,b
分别是形状为(2,2),(2,3)的数组,这样a
在水平上的两形状为(2,)的元素就可以和b
上的两个(3,)分别进行水平堆叠。In [33]: a = np.arange(4).reshape(2,2)
In [34]: b = np.arange(6).reshape(2,3)
In [35]: np.hstack((a,b))
Out[35]:
array([[0, 1, 0, 1, 2],
[2, 3, 3, 4, 5]])
如果在2-D以上叠加时,其实和2-D并无区别。我们可以把更高维度抽象为一个元素,只要这个元素的形状相同就能够使得其在水平上堆叠。总的来说在更高维度上水平堆叠时,仅需保持除axis=1
轴外形状相同即可。
In [5]: b = np.arange(24).reshape(2,3,4)
In [6]: a = np.arange(16).reshape(2,2,4)
In [7]: np.hstack((a,b))
Out[7]:
array([[[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]],
[[ 8, 9, 10, 11],
[12, 13, 14, 15],
[12, 13, 14, 15],
[16, 17, 18, 19],
[20, 21, 22, 23]]])
np.vstack(tup)
vstack
方法等价于concatenate
方法沿着axis=0
级联。
vstack
的意思是vertically stack
即垂直堆叠。假设对于两个形状分别为(3,)和(2,)的1-D数组,我们想要垂直堆叠是做不到的。a
,b
在np.vasack((a,b))
后就得到下右图所示现状为(2,3)的数组。
In [9]: a = np.arange(3)
In [10]: b = np.arange(3)
In [11]: np.vstack((a,b))
Out[11]:
array([[0, 1, 2],
[0, 1, 2]])
hstack
水平堆叠。我们可以将更高维度就行抽象,除axis=0
外,只要高层保持形状相同便可以进行堆叠。# 对于二维
In [4]: a = np.arange(6).reshape(2,3)
In [5]: b = np.arange(9).reshape(3,3)
In [6]: np.vstack((a,b))
Out[6]:
array([[0, 1, 2],
[3, 4, 5],
[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
# 对于三维
In [7]: b = np.arange(9).reshape(3,3,1)
In [8]: a = np.arange(6).reshape(2,3,1)
In [9]: np.vstack((a,b))
Out[9]:
array([[[0],
[1],
[2]],
[[3],
[4],
[5]],
[[0],
[1],
[2]],
[[3],
[4],
[5]],
[[6],
[7],
[8]]])
np.dstack(tup)
dstack
就是depth stack
,是沿着axis=2
进行堆叠的。
对于1-D形状为(M,)
的数组,会被重塑为(1,M,1)
的形状,来进行深度堆叠,对于2-D形状为(M.N)
的数组则会被重塑为(M,N,1)
的形状,来进行深度堆叠。
# 对于一维
In [14]: a = np.arange(3)
In [15]: b = np.arange(3)
In [16]: np.dstack((a,b))
Out[16]:
array([[[0, 0],
[1, 1],
[2, 2]]])
# 对于二维
In [18]: b = np.arange(6).reshape(2,3)
In [19]: a = np.arange(6).reshape(2,3)
In [20]: np.dstack((a,b))
Out[20]:
array([[[0, 0],
[1, 1],
[2, 2]],
[[3, 3],
[4, 4],
[5, 5]]])
这三个函数对三维的阵列是最有意义的。例如,对于具有高度(第一轴),宽度(第二轴)和深度(第三轴)的数据。我们只需要记住vstack
、hstack
、dstack
是分别对第一、二、三轴进行操作。
读者如果处理多维数据,建议使用函数concatenate
,stack
和block
提供的更常规的堆叠和串联操作。
方法 | 含义 |
---|---|
split | 将一个数组拆分为多个子数组。 |
array_split | 将一个数组拆分为大小相等或近似相等的多个子数组。 |
hsplit | 水平(按列)将数组拆分为多个子数组。 |
vsplit | 垂直(逐行)将数组拆分为多个子数组。 |
dsplit | 沿第3轴(深度)将数组拆分为多个子数组。 |
np.split(ary, indices_or_sections, axis=0)
如果indices_or_sections
是整型N
,则数组arr
会被切分成N
整份。如果不够切分则报错。
In [5]: a = np.arange(8)
# 切割成两份,够切
In [6]: np.split(a,2)
Out[6]: [array([0, 1, 2, 3]), array([4, 5, 6, 7])]
# 切割成三份,不够切 报错
In [7]: np.split(a,3)
ValueError: array split does not result in an equal division
如果indices_or_sections
是1-D数组,则会根据数组段来进行切分,举个例子;如果indices_or_sections
的值为[2,5],则会将arr
分为arr[:2]
、arr[2:5]
、arr[5:]
三个部分。当超出数组索引范围时,则会以空数组替代。
In [9]: a = np.arange(10)
# 未超出数组索引范围
In [10]: np.split(a,[2,5])
Out[10]: [array([0, 1]), array([2, 3, 4]), array([5, 6, 7, 8, 9])]
# 超出数组索引范围
In [13]: np.split(a,[2,5,10])
Out[13]:
[array([0, 1]),
array([2, 3, 4]),
array([5, 6, 7, 8, 9]),
array([], dtype=int32)]
np.array_split(ary, indices_or_sections, axis=0)
与split
不同的是,array_split
的indices_or_sections
参数只能为整型,且不够切分时N
等份时,最后一块则以len(arr)%N
保留,它的并无差别。
# 一维
In [4]: a = np.arange(8)
In [5]: np.array_split(a,3)
Out[5]: [array([0, 1, 2]), array([3, 4, 5]), array([6, 7])]
#二维
In [8]: b = np.arange(8).reshape(2,4)
In [9]: np.array_split(b,2,axis = 1)
Out[9]:
[array([[0, 1],
[4, 5]]),
array([[2, 3],
[6, 7]])]
np.hsplit(ary, indices_or_sections)
hsplit
是沿着axis=1
进行切分。indices_or_sections
详细切分使用过程与split
相似。In [24]: a = np.arange(12).reshape(2,6)
# 够切,则切
In [25]: np.hsplit(a,3)
Out[25]:
[array([[0, 1],
[6, 7]]), array([[2, 3],
[8, 9]]), array([[ 4, 5],
[10, 11]])]
# 不够,则报错
In [26]: np.hsplit(a,4)
ValueError: array split does not result in an equal division
# 按数组切分
In [28]: np.hsplit(a,[3,5])
Out[28]:
[array([[0, 1, 2],
[6, 7, 8]]),
array([[ 3, 4],
[ 9, 10]]),
array([[ 5],
[11]])]
hsplit
类似,这里不过多赘述。In [29]: a = np.arange(12).reshape(2,6)
# 够切,则切
In [30]: np.vsplit(a,2)
Out[30]: [array([[0, 1, 2, 3, 4, 5]]), array([[ 6, 7, 8, 9, 10, 11]])]
# 不够,则报错
In [31]: np.vsplit(a,3)
ValueError: array split does not result in an equal division
# 按数组切分
In [32]: np.vsplit(a,[0,1])
Out[32]:
[array([], shape=(0, 6), dtype=int32),
array([[0, 1, 2, 3, 4, 5]]),
array([[ 6, 7, 8, 9, 10, 11]])]
hsplit
类似,这里不过多赘述。In [37]: a = np.arange(20).reshape(2,2,6)
# 够切,则切
In [38]: np.dsplit(a,2)
Out[38]:
[array([[[ 0, 1, 2],
[ 6, 7, 8]],
[[12, 13, 14],
[18, 19, 20]]]),
array([[[ 3, 4, 5],
[ 9, 10, 11]],
[[15, 16, 17],
[21, 22, 23]]])]
# 不够,则报错
In [39]: np.dsplit(a,4)
ValueError: array split does not result in an equal division
# 按数组切分
In [40]: np.dsplit(a,[1,2])
Out[40]:
[array([[[ 0],
[ 6]],
[[12],
[18]]]),
array([[[ 1],
[ 7]],
[[13],
[19]]]),
array([[[ 2, 3, 4, 5],
[ 8, 9, 10, 11]],
[[14, 15, 16, 17],
[20, 21, 22, 23]]])]
eye(N, M=None, k=0, dtype=
返回一个二维数组,对角线上是1,其它地方为0。当k为正上移对象线,k为负时下移对角线。
In [3]: np.eye(2)
Out[3]:
array([[1., 0.],
[0., 1.]])
In [4]: np.eye(4,k=1)
Out[4]:
array([[0., 1., 0., 0.],
[0., 0., 1., 0.],
[0., 0., 0., 1.],
[0., 0., 0., 0.]])
In [5]: np.eye(4,k=-1)
Out[5]:
array([[0., 0., 0., 0.],
[1., 0., 0., 0.],
[0., 1., 0., 0.],
[0., 0., 1., 0.]])
identity(n, dtype=None)
与eye
不同的是identity
仅能创建对角矩阵。
In [10]: np.identity(3)
Out[10]:
array([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]])
set_printoptions(precision=None, threshold=None, edgeitems=None, linewidth=None, suppress=None, nanstr=None, infstr=None, formatter=None, sign=None, floatmode=None, *, legacy=None)
设置浮点数的精确度。
In [2]: np.set_printoptions(precision= 5)
In [3]: np.array([1.254831,0.235482])
Out[3]: array([1.25483, 0.23548])
折叠数组,默认值为1000
,当数组中的元素超过1000
时就会被折叠。下面设置treshold=7
,即超过7
项的数组会被折叠。当设置比6
小的数时并不一定会折叠,这是因为折叠至少需要6
个数
In [24]: np.set_printoptions(threshold= 7)
In [25]: np.arange(7)
Out[25]: array([0, 1, 2, 3, 4, 5, 6])
In [26]: np.arange(8)
Out[26]: array([0, 1, 2, ..., 5, 6, 7])
# 当设置的折叠数过小时
In [30]: np.set_printoptions(threshold= 5)
In [31]: np.arange(6)
Out[31]: array([0, 1, 2, 3, 4, 5])