list、ndarray、series、dataframe区分:
numpy中的ndarray,相当于python自带的list。
而pandas中对不同维度的数组有区分:series相当于一维数组,dataframe是多维数组。这部分下一篇再做记录,这里不再赘述。
本文记录numpy中的一些常见数据操作。
1. array()方法创建数组
首先厘清一个概念:array是一个函数,用来创建数组对象,创建出的对象类型为ndarray。
>>> a = np.array([1,2,3])
>>> b = np.array([4,5,6],[7,8,9])
>>> c = np.array([a,a**2])
>>> d = c.T # 转置
>>> c
array([[1, 2, 3],
[1, 4, 9]])
>>> d
array([[1, 1],
[2, 4],
[3, 9]])
>>> type(a)
<class 'numpy.ndarray'>
查看数组的维度、数据类型:
>>> a.shape
(3,)
>>> b.shape
(2, 3)
>>> d.dtype
dtype('int64')
>>> d = d.astype('f') # 修改数据类型
>>> d
array([[1., 1.],
[2., 4.],
[3., 9.]], dtype=float32)
2. 常见基本数值计算
加减乘除、乘方、对数(+-*/% ^ log)
>>> a+b[0]
array([5, 7, 9])
>>> a-b[0]
array([-3, -3, -3])
>>> a*b[0]
array([ 4, 10, 18])
>>> a/b[0]
array([0.25, 0.4 , 0.5 ])
>>> a%b[0] # 取余
array([1, 2, 3])
>>> a**2
array([1, 4, 9])
>>> a.dot(b[0]) # 点积
32
>>> np.log(a)
array([0. , 0.69314718, 1.09861229])
sum( )、max( )、min( )、mean( )、std( ) 等
>>> a.sum()
6
>>> a.max()
3
>>> a.min()
1
>>> a.mean()
2.0
>>> a.std()
0.816496580927726
>>> a.argmax() # 最大值的索引
2
>>> a.argmin() # 最小值的索引
0
3. 数组扩充
复制数组内容并扩充n倍/重复n遍:
方法一:tile(),整体重复
>>> np.tile(b,(2,1)) # 纵向扩充为2倍,横向不扩充。也可写作[2,1]。
array([[4, 5, 6],
[7, 8, 9],
[4, 5, 6],
[7, 8, 9]])
>>> np.tile(b,(1,2)) # 纵向不扩充,横向扩充为2倍。也可写作[1,2]。
array([[4, 5, 6, 4, 5, 6],
[7, 8, 9, 7, 8, 9]])
方法二:repeat(),选择性重复
>>> b.repeat([1,2],axis=0) # 数组第一行1次,第二行2次。axis=0纵向。
array([[4, 5, 6],
[7, 8, 9],
[7, 8, 9]])
>>> b.repeat([1,2,3],axis=1) # 数组第一列1次,第二列2次,第三列3次。axis=1横向。
array([[4, 5, 5, 6, 6, 6],
[7, 8, 8, 9, 9, 9]])
4. 数组拼接
方法一:concatenate()
很喜欢这个函数,因为行/列拼接,一维/多维数据拼接都可以完成,而且只需要改axis一个参数,好记又简洁。
# 一维数组拼接
>>> np.concatenate(([1,2],[3,4]),axis=0) # 一维数组只有一个维度,axis只能为0
array([1, 2, 3, 4])
# 二维数组纵向拼接
>>> np.concatenate(([[1,2]],[[3,4],[5,6]]),axis=0)
array([[1, 2],
[3, 4],
[5, 6]])
# 二维数组横向拼接
>>> np.concatenate(([[1,2],[5,6]],[[3,4],[7,8]]),axis=1)
array([[1, 2, 3, 4],
[5, 6, 7, 8]])
使用这个函数有一点要注意:参与拼接的数组维度要统一。
比如下面这个报错乍一看很迷惑,明明列数一样啊?其实就是维度的问题。所以把第一个输入的一维数组改成一个只有一行的二维数组就可以啦。
>>> np.concatenate(([1,2],[[3,4],[5,6]]),axis=0)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<__array_function__ internals>", line 6, in concatenate
ValueError: all the input arrays must have same number of dimensions, but the array at index 0 has 1 dimension(s) and the array at index 1 has 2 dimension(s)
>>> np.concatenate(([[1,2]],[[3,4],[5,6]]),axis=0)
array([[1, 2],
[3, 4],
[5, 6]])
方法二:vstack()与hstack()
这两个一个是纵向拼接一个横向拼接。和concatenate()不一样在于:
- vstack()可以把一维和二维的数组拼接(就是不会有上面报错的那个问题);
- 拼接一维数组用hstack(),相当于list操作中的extend。
# a = np.array([1,2,3])
# b = np.array([4,5,6],[7,8,9])
# c = np.array([a,a**2])
>>> np.vstack([a,b])
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
>>> np.hstack([[1,2],[1,2,3]])
array([1, 2, 1, 2, 3])
>>> np.hstack([b,c])
array([[4, 5, 6, 1, 2, 3],
[7, 8, 9, 1, 4, 9]])
5. 一些特殊数组的生成
首先排一个坑:
empty()生成的并不是空数组,而是一些random出来的值。使用起来需要手动修改数组中的每个值,所以一般不用这个来初始化,而是初始化为全1或全0。
但如果一定想创建一个空数组也有个办法,就是用空list创建。
>>> d = np.empty(shape=(1,3))
>>> d
array([[2.00000047e+00, 7.81250187e-03, 2.62144063e+05]])
>>> d = np.array([])
>>> d
array([], dtype=float64)
全1、全0矩阵、随机数矩阵。
>>> b0 = np.ones(8)
>>> b0
array([1., 1., 1., 1., 1., 1., 1., 1.])
>>> a1 = np.ones((2,3),dtype=int)
>>> a1
array([[1, 1, 1],
[1, 1, 1]])
>>> a2 = np.zeros((3,2))
>>> a2
array([[0., 0.],
[0., 0.],
[0., 0.]])
>>> a3 = np.random.randint(0,10,(3,4)) # 范围0~10 ,矩阵形状3行4列
>>> a3
array([[9, 6, 7, 8],
[1, 9, 8, 7],
[8, 3, 5, 7]])
对角矩阵:
>>> a3 = np.eye(3)
>>> a3
array([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]])
# a = np.array([1,2,3])
>>> np.diag(a)
array([[1, 0, 0],
[0, 2, 0],
[0, 0, 3]])
等距的一维数组:
>>> b1 = np.arange(0,20,2)
>>> b1
array([ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18])
>>> b2 = np.linspace(0,10,5) # 包含首0尾10,分为5等分。
>>> b2
array([ 0. , 2.5, 5. , 7.5, 10. ])
重定义数组形状:
- reshape()不会改变原数组,resize()改变原数组。
# b0 = np.ones(8)
>>> b0.reshape(2,4)
array([[1., 1., 1., 1.],
[1., 1., 1., 1.]])
>>> b0
array([1., 1., 1., 1., 1., 1., 1., 1.])
>>> b0.resize(2,4)
>>> b0
array([[1., 1., 1., 1.],
[1., 1., 1., 1.]])
6. 数组切片
一维数组切片:
# >>> b1 = np.arange(0,20,2)
# >>> b1
# array([ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18])
>>> b1[1:4]
array([2, 4, 6])
>>> b1[-6:]
array([ 8, 10, 12, 14, 16, 18])
>>> b1[:]
array([ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18])
# 可以给切片部分赋值
>>> b1[2:6] = 1
>>> b1
array([ 0, 2, 1, 1, 1, 1, 12, 14, 16, 18])
>>> b1[2:6] = [1,2,3,4]
>>> b1
array([ 0, 2, 1, 2, 3, 4, 12, 14, 16, 18])
二维数组切片:
# >>> b1 = np.arange(0,24,2)
# >>> b1.resize(3,4)
# >>> b1
# array([[ 0, 2, 4, 6],
# [ 8, 10, 12, 14],
# [16, 18, 20, 22]])
>>> b1[:2,1:] # 取0、1行的2、3、4列
array([[ 2, 4, 6],
[10, 12, 14]])
>>> b1[-2:,-2:] # 取后两行的后两列
array([[12, 14],
[20, 22]])
>>> b1[-1,::2] # 最后一行中,从第一列开始,每2列取一个。
array([16, 20])
>>> b1[::2,1] # 第2列中,每2行取一个
array([ 2, 18])
>>> b1[:,2] # 第3列整列
array([ 4, 12, 20])
>>> b1[b1>10] # 数组中所有大于10的值
array([12, 14, 16, 18, 20, 22])
>>> b1[b1>10]=0 # 数组中所有大于10的值=1
>>>> b1
array([ 0, 2, 4, 6, 8, 10, 1, 1, 1, 1, 1, 1])
切片操作是浅拷贝:
>>> b22 = b1[:2,:2] # 并没有开辟新的存储空间,只是指向了b1的切片部分。
>>> b22[:] = 0
>>> b1 # 因此修改b22本质上仍是修改b1
array([[ 0, 0, 4, 6],
[ 0, 0, 12, 14],
[16, 18, 20, 22]])
7. 其他操作
where(条件,if True,if False)
# b = np.array([4,5,6],[7,8,9])
>>> np.where(b > 5, np.log(b), 0) # b中的值,若大于5,取对数;否则,置0。
array([[0. , 0. , 1.79175947],
[1.94591015, 2.07944154, 2.19722458]])
先记录这么多,之后想起来再补充啦。