Python学习笔记(4):Numpy 数据结构
文章导读
- 课程难度:★★☆☆☆
- 预计学习时间:1小时
- 简介:本节主要讲解了Numpy数据结构相关的基本操作及使用功能等,包括:(1)创建数组;(2)数组的数据格式;(3)数组的运算;(4)三种数组的访问与修改方法;(5)数组的重塑、拼接与拆分;
- 重点涉及的函数和内容:np.array()、astype()、tolist()、reshape()和resize()、ravel()和flatten()、np.concatenate()、np.vstack和np.hstack、np.r_和np.c_、np.split()
前言
Numpy库是Python中用于科学计算的核心库,它提供了一个强大的多维数组及相关运算等功能。接下来将分别从数组的创建、格式、运算、访问和修改等方面对数组进行系统地学习和了解。本节将分别从数组的创建、数据格式、运算、访问与修改、重塑与拼接等五个方面来对numpy的数组进行详细地介绍。
一、创建数组
导入numpy库:
import numpy as np
创建数组
我们可以利用np.array()
函数把列表、元组或range
对象直接转换为numpy数组;或者使用np.zeros()
、np.ones()
、np.full()
等函数初始化一个一定形状的数组,后续根据需要再对其元素进行修改,该方法对于一维数组的初始化直接传入一个数值即可,而多维数组则可以传入元组以确定初始化数组的形状。具体示例如下:
np.array([1,2,3,4]) #把列表转换为数组
np.array((1,2,3,4)) #把元组转换为数组
np.array(range(4)) #把range对象转换为数组
np.array([[1,2,3,4],[5,6,7,8]]) #二维数组
np.zeros(3) #全0的一维数组
np.zeros((3,4)) #3×4的全0二维数组
np.ones((1,3)) #1×3的全1二维数组
np.full((2,3),4) #常量数组,2×3的全4数组
np.empty((1,3)) #1×3的空数组,只申请空间,不初始化
np.eye(4) #4×4的单位方阵
np.eye(2,3) #2×3的单位矩阵
np.identity(4) #4×4的单位矩阵,该方法只能创建行数与列数相等的单位方阵
np.arange(0,1,0.2) #等差数组,0——1(不包括1),步长为0.2
np.linspace(0,10,5) #等差数组,0——10,5个元素
#构建相同形状的数组
a = np.array([[1,2,4],[3,4,5]])
b= np.ones_like(a) #使b的形状与a相同,元素全为1
print(b)
输出结果如下:
array([1, 2, 3, 4])
array([1, 2, 3, 4])
array([0, 1, 2, 3])
array([[1, 2, 3, 4],
[5, 6, 7, 8]])
array([0., 0., 0.])
array([[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]])
array([[1., 1., 1.]])
array([[4, 4, 4],
[4, 4, 4]])
array([[0., 0., 0.]])
array([[1., 0., 0., 0.],
[0., 1., 0., 0.],
[0., 0., 1., 0.],
[0., 0., 0., 1.]])
array([[1., 0., 0.],
[0., 1., 0.]])
array([[1., 0., 0., 0.],
[0., 1., 0., 0.],
[0., 0., 1., 0.],
[0., 0., 0., 1.]])
array([0. , 0.2, 0.4, 0.6, 0.8])
array([ 0. , 2.5, 5. , 7.5, 10. ])
[[1 1 1]
[1 1 1]]
二、数组的数据格式
1、 数据类型介绍
int:整数
float:浮点数
complex:复数
bool:布尔类型,存储TRUE和FALSE值
object : Python对象
string:字符串
2、 查看数组
a = np.array([[1,2,3,4,5],[6,7,8,9,10],[13,5,6,8,2]])
print(a.dtype) #数组中元素的数据类型
print(a.shape) #数组尺寸
print(a.ndim) #数组的维度
print(len(a)) #数组的长度
print(a.size) #数组中的元素个数
输出结果如下:
int32
(3, 5)
2
3
15
转换数组内元素的类型:astype()
,该方法不改变原数组
print(a.dtype)
a.astype('float')
print(a.astype('float').dtype) # 转换后的元素类型
print(a.dtype) #转换后原数组的元素类型
输出结果如下:
int32
array([[ 1., 2., 3., 4., 5.],
[ 6., 7., 8., 9., 10.],
[13., 5., 6., 8., 2.]])
float64
int32
将数组转换为列表:tolist()
,该方法不改变原数组
print(a.tolist())
print(a)
输出结果如下:
[[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [13, 5, 6, 8, 2]]
[[ 1 2 3 4 5]
[ 6 7 8 9 10]
[13 5 6 8 2]]
3、 补充及注意事项
1.一个numpy数组只能有一个数据格式,建立该对象的原数据若是有多个数据,它会自动将数据类型转换为能满足所有数据的最为精确的数据类型。
a = np.array([1, 2, 3.3])
print(a.dtype)
b = np.array([1, 2, 3.3, 'alpha'])
print(b.dtype)
输出结果如下:
float64
<U32
例如在这里,对于一个数组如果能归结为int
型,就不用float
,如果能归结为float
型,就不用字符串。这个u32
是unicode 32的意思。
- 在一个待建立的numpy数组里面,同一层级里面的数据必须全部是元素,或者全部是序列(列表、元组)
c = np.array([1, 2, 3, [4, 5]]) # 这是会报错的
d = np.array([(1, 2, 3), [4, 'beta']]) # 即便两种不同的序列也能建立,返回object。
print(d, d.dtype)
输出结果如下:
【错误】ValueError: setting an array element with a sequence.
[(1, 2, 3) list([4, 'beta'])] object
- 若是想要建立一个多维numpy数组,每一维度的元素必须等长,否则会建立一个由
python object
数据类型构成的numpy数组
e = np.array([[1, 2, 3], [4, 5, 6]]) # 二维数组的正确建立方式
print(e, e.dtype)
f = np.array([[1, 2, 3], [4, 5, ]]) # 如果元素不等长,建立的数据类型就是object
print(f, f.dtype)
输出结果如下:
[[1 2 3]
[4 5 6]] int32
[list([1, 2, 3]) list([4, 5])] object
三、数组的运算
先定义几个如下数组:
a = np.array([1, 2, 3, 4, 5, 6])
b = np.array([1, 2, 3, 4])
c = np.array([1, 2, 3])
d = np.array(['alpha', 'beta', 'gamma'])
- 一个数组做各种算术操作,是一个数组的所有元素进行一次计算(这里需要仔细注意的是,列表的
+
和numpy数组的+
有明显的不同,列表中表示两个列表的拼接,而numpy数组则是两个等长的数组进行一对一的求和运算。其区别还在乘法中体现。)但是,字符串的数组并不支持类似于+
、*
之类的操作
print(a + 1) # 数组中每个值加1
print(a * 3) # 数组中每个值乘3
print(a > 3) # 将3与数组中每个值做比较,返回布尔数组
print(1 / a) # 用1除以每个元素,即计算每个元素的倒数
print(2 - a) # 将2与数组中每个值做差
print(2 ** a) # 对数组中每个元素tmp,求2的tmp次方
输出结果如下:
[2 3 4 5 6 7]
[ 3 6 9 12 15 18]
[False False False True True True]
[1. 0.5 0.33333333 0.25 0.2 0.16666667]
[ 1 0 -1 -2 -3 -4]
[ 2 4 8 16 32 64]
如果想要将numpy的字符串数组的每个元素与特定字符串做拼接,会报如下的错误:
d += '_Add' # 报错1:循环numpy数组运算时不允许字符串的拼接
- 数组运算也可以结合赋值运算符,做成
+=
、%=
等形式
a = np.array([1, 2, 3, 4, 5, 6])
a *= 2
print(a)
a = np.array([1, 2, 3, 4, 5, 6])
a %= 2
print(a)
输出结果如下:
[ 2 4 6 8 10 12]
[1 0 1 0 1 0]
- 一个numpy数组和其他numpy数组做算术运算时,是元素间一一对应计算
a = np.array([1, 2, 3, 4, 5, 6])
b = np.array([-1, 1, 3, 5, 7, 9])
c = np.array([1, 2, 3])
d = np.array(['alpha', 'beta', 'gamma'])
e = np.array(['one', 'two', 'three'])
这种计算发生在元素的一一对应之间,同时也可以进行比较运算。因为一维数组之间的运算多,我们重点提它。两个一维numpy数组的计算必须要求其具有相等的形状,且对应元素要能发生相互的计算
print(a + b) # 算数运算会返回一串一一对应计算的数值数组
print(a * b)
print(a >= b) # 比较运算会返回一串一一对应比较布尔值数组。
print(a == b)
输出结果如下:
[ 0 3 6 9 12 15]
[-1 2 9 20 35 54]
[ True True True False False False]
[False False True False False False]
如下两种情况就会报错,报错的信息如下:
print(a + c) # 报错1,两个数组不等长,即便是a和c存在倍数关系
print(d + e) # 报错2,如前所述,numpy的字符串数组之间不能用+进行拼接
报错1【ValueError: operands could not be broadcast together with shapes (6,) (3,)】
报错2【TypeError: ufunc 'add' did not contain a loop with signature matching types dtype('<U5') dtype('<U5') dtype('<U5')】
- 对于高维度数组,有一种广播机制,能让不同形状的数组乘到一起。这里举一个高维乘一维的例子:
a_2d = np.array([[1, 2, 3], [4, 5, 6]]) # 一个(2, 3)的数组
a_3d = np.array([[[3, 4, 5],[3, 4, 5]],
[[5, 6, 7], [5, 6, 7]]]) # 一个(2, 2, 3)的数组
c = np.array([1, 2, 3]) # 一个(3, )的数组
print(a_2d * c)
print(a_3d * c)
输出结果如下:
[[ 1 4 9]
[ 4 10 18]]
[[[ 3 8 15]
[ 3 8 15]]
[[ 5 12 21]
[ 5 12 21]]]
从上面的运算结果可以总结,高维数组乘一维数组的运算方式是,高维数组中最后一维对应乘以一维数组的各元素,要求一维数组的长度等于高维数组的最后一维的长度,更复杂的它的广播机制在此略过,此知识点用的较少。
四、数组的访问与修改
对于数组的访问可以通过基于下标与切片、整数列表以及逻辑索引等三种方法。
1、基于下标与切片
数据的访问与切片和列表中的访问的十分相似。
一维数组的访问:与列表的访问方式相同
a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
print(a[2]) # 访问元素
print(a[3:5]) # 访问一个切片,给出了起点和终点
print(a[2:]) # 访问一个切片,只给出了起点,起点被设置为数组的开始。
print(a[:]) # 访问一个没有起点和终点的切片,等同于访问原数组。
输出结果如下:
3
[4 5]
[ 3 4 5 6 7 8 9 10]
[ 1 2 3 4 5 6 7 8 9 10]
高维数组的访问:直观上来看,只用一个中括号[]
访问所有维度的值,各个维度之间用逗号,
分隔,而不是像列表先访问高维、再访问低维度一样,逐级地分步访问,尽管这种方式也是可行的。具体示例如下:
b = np.array(([1,2,3,4],
[5,6,7,8],
[9,10,11,12]))
print(b[0, 1]) # 访问某个特定元素,需要传递行值和列值,用逗号分隔。访问第1行第2列
print(b[0]) # 如果没有后续维度,返回结果就是我们的这个维度的切片。访问第一行
print(b[0:1, :]) # 想要访问某些行,就将列只写一个冒号,表示访问所有列。访问第1行
print(b[:, 1:4]) # 想要访问某些列,就将行只写一个冒号,表示访问所有行。访问第2列到第4列
输出结果如下:
2
[1 2 3 4]
[[1 2 3 4]]
[[ 2 3 4]
[ 6 7 8]
[10 11 12]]
接下来,将介绍基于下标与切片的方式修改数组,对于单个元素或是一个切片,我们都可以直接进行修改。对于元素,我们通过下标将之访问后,赋予新值即可。对于一个切片,将之访问出来之后,可以只传一个值替换掉切片中的所有值,也可以传一组等形状的值对应替换掉原值,具体示例如下:
一维数组的修改:
a = np.array([1,2,3,4,5,6,7,8,9,10])
a[0] =0 #用一个值替换一个值
a[1:3] = [0] #用一个值替换切片
a[3:9] = [1,2,3,4,5,6] #用切片替换切片
print(a)
输出结果如下:
[ 0 0 0 1 2 3 4 5 6 10]
多维数组的修改:用值替换单个元素或切片,示例如下:
b = np.array(([1,2,3,4],
[5,6,7,8],
[9,10,11,12]))
b[:2,:3]=0 # 前2行、前3的元素用0替换
b[2,1] =-10 #第3行第二列的元素用-10替换
b
输出结果如下:
array([[ 0, 0, 0, 4],
[ 0, 0, 0, 8],
[ 9, -10, 11, 12]])
同样地,也可以用切片替换切片,需要注意的是,传入数组的形状要与访问的一致,具体示例如下:
b = np.array(([1,2,3,4],
[5,6,7,8],
[9,10,11,12]))
b[:2,:3] = [[0,0,0],[1,1,1]]
b
输出结果如下:
array([[ 0, 0, 0, 4],
[ 1, 1, 1, 8],
[ 9, 10, 11, 12]])
2、基于整数列表
numpy数组支持通过传递一个列表来进行多个元素的访问。
一维数组
a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
print(a[[0,2,3,7]])
输出结果如下:
[1 3 4 8]
多维数组
可以通过传入切片和列表来访问某些行、某些列的元素,具体示例如下:
b = np.array([[1, 2, 3, 4, 5, 6 ],
[7, 8, 9, 10, 11, 12 ],
[13, 14, 15, 16, 17, 18 ],
[19, 20, 21, 22, 23, 24]])
print(b[[0, 2, 3]]) #访问行下标为0、2、3所在行的所有元素,即第1、3、4行。
#等价于 b[[0,2,3],:],不指定列下标表示所有列
print(b[:,[1,3,4]]) #访问第2、4、5列,不指定行下表表示所有行
print(b[1:3,[0,2]]) #访问行下标为[1,3)、列下标为0、2的元素,即:第2、3行第1、3列的元素
print(b[[0,3],[1,2]]) #访问固定元素,b[0,1]、b[3,2]
输出结果如下:
[[ 1 2 3 4 5 6]
[13 14 15 16 17 18]
[19 20 21 22 23 24]]
[[ 2 4 5]
[ 8 10 11]
[14 16 17]
[20 22 23]]
[[ 7 9]
[13 15]]
[ 2 21]
3、基于逻辑索引
该方法的原理为:数组和标量或等长数组进行关系运算可以返回布尔型数组,以此可以作为下标访问其中的元素,返回True
对应位置上元素组成的数组。具体示例如下:
(1)单一条件筛选
a = np.array([1, 2, 3, 4, 5, 6])
b = np.array([-1, 1, 3, 5, 7, 9])
print(a >= b) #数组之间的比较会返回一串布尔型数值
print(a[ a >= b ]) #在数组a中筛选出所有对应元素里a比b大的值
输出结果如下:
[ True True True False False False]
[1 2 3]
(2)多条件筛选
利用布尔数组的时候,逻辑条件的拼接需要用逻辑运算符&
、|
、和 ~
,而不能用and
、or
、not
,同时,每一个逻辑条件需要用括号括起来。具体案例如下:
下面是一串消费记录,关于每个人进行的历次消费的情境,name和purchase一一对应,为了想要找到所有Joe超过3元的消费记录,代码如下:
name = np.array(['Bob', 'Joe', 'Joe', 'Joe','Will', 'Will', 'Alex'])
purchase = np.array([3.3, 6.9, 2.1, 4.2, 5.5, 3.9, 3.0])
print(purchase[(name=='Joe')&(purchase>3)])
输出结果如下:
[6.9 4.2]
~
实际上是位运算的取反符号,可以接整型数据和布尔型数据,选取不是Joe的所有消费金额代码如下:
print(purchase[~(name=='Joe')])
输出结果如下:
[3.3 5.5 3.9 3. ]
接着,既然可以基于布尔值访问元素,我们同样也能基于布尔值修改元素。
b = np.array([[1, 2, 3, 4, 5, 6],
[7, 8, 9, 10, 11, 12],
[13, 14, 15, 16, 17, 18]])
b[b > 10] = 10
print(b)
输出结果如下:
[[ 1 2 3 4 5 6]
[ 7 8 9 10 10 10]
[10 10 10 10 10 10]]
这是一个非常直观的基于条件对数组筛选的形式,因此在数据分析中常常使用。
五、数组的重塑、拼接与拆分
1、重塑
(1).reshape()函数:
该方法接收的是一个元组,对数组进行重塑之后,原值不会发生改变,返回值是重塑后的数据,首先来看一下该方法的实现过程,示例如下:
a =np.arange(12)
a_34 = a.reshape(3,4)
print(a)
print(a_34)
输出结果如下:
[ 0 1 2 3 4 5 6 7 8 9 10 11]
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
其次,可以给待重塑数组的某一维度传-1,此时系统将自动给定大小:
a_x3 = a.reshape(-1,3)
print(a_x3)
输出结果如下:
[[ 0 1 2]
[ 3 4 5]
[ 6 7 8]
[ 9 10 11]]
另外,可以利用其他数组的shape
属性,重塑数组,具体示例如下:
b = np.array([[1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12]])
a_b = a.reshape(b.shape)
print(a_b)
输出结果如下:
[[ 0 1 2 3 4 5]
[ 6 7 8 9 10 11]]
最后,需要注意的是,对.reshape()
操作后的返回值进行修改,此时也修改原数组中对应的值,例如:
a = np.arange(12)
a_34 = a.reshape(3, 4)
a_34[1, 2] = -1
print(a)
输出结果如下:
[ 0 1 2 3 4 5 -1 7 8 9 10 11]
(2).resize()函数:
与re.shape()
相似,.resize()
函数也接收一个元组。区别是resize()
会直接改变原数组,而没有返回值:
a = np.arange(12)
a_26 = a.resize(2, 6)
print(a_26)
print(a)
输出结果如下:
None # a_26作为resize()函数的返回值为None,表示函数无返回值
[[ 0 1 2 3 4 5]
[ 6 7 8 9 10 11]]
(3).ravel()、.flatten()函数
使数组扁平化,一是可以使用reshape
、resize
函数,二是使用ravel
、flatten
函数。
reshape
和resize
函数对数组实现扁平化的方法如下:
b = np.array([[1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12]])
b_1d = b.reshape(12)
print(b_1d)
输出结果如下:
[ 1 2 3 4 5 6 7 8 9 10 11 12]
使用ravel()、flatten()
函数,两者都不会在原值上进行修改,但是两者是有区别的。区别就在于对.ravel()
的返回值如果进行修改,修改会反映到原值上,就像.reshape()
一样。而对.flatten()
的返回值进行修改则不会。
b = np.array([[1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12]])
b_1d = b.ravel()
print(b_1d)
print(b)
b_1d[3] = -1
print(b)
输出结果如下:
[ 1 2 3 4 5 6 7 8 9 10 11 12]
[[ 1 2 3 4 5 6]
[ 7 8 9 10 11 12]]
[[ 1 2 3 4 5 6]
[ 7 8 9 10 11 12]]
2、拼接
列表的拼接用的是 +
和.extend()
。但数组的拼接是把数组直接横向或纵向接在另一个数组上。数组的拼接主要使用np.concatenate()
函数,还有np.vstack
、np.hstack()
,以及np.r_[]
、np.c[]
等三组函数。
(1)np.concatenate()函数
该方法待拼接的数据要写成列表的形式,同时还需要补充拼接的轴向axis,axis = 0
代表横向,axis = 1
代表纵向:
a = np.arange(24).reshape(4, 6)
b = np.ones(18).reshape(3, 6)
c = np.zeros(16).reshape(4, 4)
a_b = np.concatenate([a, b], axis = 0) #将a、b进行横线拼接
a_c = np.concatenate([a, c], axis = 1) #将a、c进行纵向拼接
print(a_b, '\n')
print(a_c, '\n')
输出结果如下:
[[ 0. 1. 2. 3. 4. 5.]
[ 6. 7. 8. 9. 10. 11.]
[12. 13. 14. 15. 16. 17.]
[18. 19. 20. 21. 22. 23.]
[ 1. 1. 1. 1. 1. 1.]
[ 1. 1. 1. 1. 1. 1.]
[ 1. 1. 1. 1. 1. 1.]]
[[ 0. 1. 2. 3. 4. 5. 0. 0. 0. 0.]
[ 6. 7. 8. 9. 10. 11. 0. 0. 0. 0.]
[12. 13. 14. 15. 16. 17. 0. 0. 0. 0.]
[18. 19. 20. 21. 22. 23. 0. 0. 0. 0.]]
拼接是有顺序的,若是将[a, b]的拼接改成了[b, a],,b的数据就会在前面(上面)。类似的,c的数据就会在左边。另外,数据拼接之后,对新数据进行修改不会影响到原数据:
a_c[0]=100
print(a_c,'\n\n',a,'\n\n',c)
输出结果如下:
[[100. 100. 100. 100. 100. 100. 100. 100. 100. 100.]
[ 6. 7. 8. 9. 10. 11. 0. 0. 0. 0.]
[ 12. 13. 14. 15. 16. 17. 0. 0. 0. 0.]
[ 18. 19. 20. 21. 22. 23. 0. 0. 0. 0.]]
[[ 0 1 2 3 4 5]
[ 6 7 8 9 10 11]
[12 13 14 15 16 17]
[18 19 20 21 22 23]]
[[0. 0. 0. 0.]
[0. 0. 0. 0.]
[0. 0. 0. 0.]
[0. 0. 0. 0.]]
(2)np.vstack()、np.hstack()函数
这组函数可以看成是np.concatenate()
的简版,两个函数分别对数组进行横向(轴0)、纵向(轴1)拼接:
a = np.arange(24).reshape(4, 6)
b = np.ones(18).reshape(3, 6)
print(np.vstack([a, b]), '\n')
print(np.hstack([a, c]), '\n')
输出结果如下:
[[ 0. 1. 2. 3. 4. 5.]
[ 6. 7. 8. 9. 10. 11.]
[12. 13. 14. 15. 16. 17.]
[18. 19. 20. 21. 22. 23.]
[ 1. 1. 1. 1. 1. 1.]
[ 1. 1. 1. 1. 1. 1.]
[ 1. 1. 1. 1. 1. 1.]]
[[ 0. 1. 2. 3. 4. 5. 0. 0. 0. 0.]
[ 6. 7. 8. 9. 10. 11. 0. 0. 0. 0.]
[12. 13. 14. 15. 16. 17. 0. 0. 0. 0.]
[18. 19. 20. 21. 22. 23. 0. 0. 0. 0.]]
(3)np.r_[]、np.c_[]
np.r_[]
、np.c_[]
,这组方法效果分别等同于np.vstack()
和np.hstack()
,只是,这两个方法是直接通过中括号[]
接收numpy数组并进行拼接,并不作为函数接收一个待拼接的数组列表
我们展示其应用效果如下:
a = np.arange(24).reshape(4, 6)
b = np.ones(18).reshape(3, 6)
print(np.r_[a, b], '\n')
print(np.c_[a, c], '\n')
输出结果如下:
[[ 0. 1. 2. 3. 4. 5.]
[ 6. 7. 8. 9. 10. 11.]
[ 12. 13. 14. 15. 16. 17.]
[ 18. 19. 20. 21. 22. 23.]
[ 1. 1. 1. 1. 1. 1.]
[ 1. 1. 1. 1. 1. 1.]
[ 1. 1. 1. 1. 1. 1.]]
[[ 0. 1. 2. 3. 4. 5. 0. 0. 0. 0.]
[ 6. 7. 8. 9. 10. 11. 0. 0. 0. 0.]
[ 12. 13. 14. 15. 16. 17. 0. 0. 0. 0.]
[ 18. 19. 20. 21. 22. 23. 0. 0. 0. 0.]]
据此,对二维数组中np.vstack()
和np.r_[]
功能相同,np.hstack()
和np.c_[]
功能相同,横纵向拼接的功能都能用np.concatenate()
实现。但对一维数组的拼接中,三组功能有一些不同,我们用一个例子集中展现:
a_1d = np.array([1, 2, 3])
b_1d = np.array([4, 5, 6])
print(np.concatenate([a_1d, b_1d], axis = 0), '\n')
print(np.hstack([a_1d, b_1d]))
print(np.vstack([a_1d, b_1d]) , '\n')
print(np.r_[a_1d, b_1d])
print(np.c_[a_1d, b_1d])
三组数据拼接方法的输出结果如下:
[1 2 3 4 5 6]
[1 2 3 4 5 6]
[[1 2 3]
[4 5 6]]
[1 2 3 4 5 6]
[[1 4]
[2 5]
[3 6]]
从此我们可以看见对于一维数组,np.concatenate()
(一维数组的axis仅有0)、np.hstack()
和np.r_[]
都是进行数组的横向扩展,而np.vstack()
将两个数组看成两行、做了横向堆叠,np.c_[]
将两个数组看成两列、做了纵向堆叠,二者互为转置。这数种拼接方法的一些区别需要理顺。
3、拆分
与np.concatenate()
函数相对应的是np.split()
,将数组沿某个轴进行拆分,拆分是以均等的方式拆分,份数必须被轴的长度整除,具体参考如下代码示例:
(1)np.split()函数
a = np.arange(24).reshape(4, 6)
print(np.split(a, 4, axis = 0), '\n') # 将a沿横向(轴0)拆成4份
print(np.split(a, 3, axis = 1), '\n') # 将a沿横向(轴1)拆成3份
输出结果如下:
[array([[0, 1, 2, 3, 4, 5]]), array([[ 6, 7, 8, 9, 10, 11]]), array([[12, 13, 14, 15, 16, 17]]), array([[18, 19, 20, 21, 22, 23]])]
[array([[ 0, 1],
[ 6, 7],
[12, 13],
[18, 19]]), array([[ 2, 3],
[ 8, 9],
[14, 15],
[20, 21]]), array([[ 4, 5],
[10, 11],
[16, 17],
[22, 23]])]
(2)np.vsplit()、np.hsplit()函数
相似的也有np.vsplit()
和np.hsplit()
函数,作为np.split()
的简版,两个函数分别对数组进行横向(轴0)、纵向(轴1)的拆分:
print(np.vsplit(a, 2),'\n') # 将a沿横向拆成2份
print(np.hsplit(a, 2)) # 将a沿纵向拆成3份
输出结果如下:
[array([[ 0, 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10, 11]]), array([[12, 13, 14, 15, 16, 17],
[18, 19, 20, 21, 22, 23]])]
[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]])]
以上就是numpy数组的主要内容。
对于缺乏Python基础的同仁,可以通过免费专栏🔥《Python学习笔记(基础)》从零开始学习Python
结语
请始终相信“Done is better than perfect”
,不要过分追求完美,即刻行动就是最好的开始, 一个模块一个模块地积累和练习,必将有所收获。
还有其他的问题欢迎在评论区留言📝!
[版权申明] 非商业目的注明出处可自由转载,转载请标明出处!!!
博客:butterfly_701c