0. 前言
鉴于在卓越班暑期学习中,接触到机器学习的内容,索性深入研究一番,蹭一蹭机器学习的热度。
众所周知,学习机器学习之前,必须学习数据分析。而numpy
则是数据分析的第一道关。
numpy
的官网中,如此介绍:
NumPy是Python中科学计算的基础包。它是一个Python库,提供多维数组对象,各种派生对象(如掩码数组和矩阵),以及用于数组快速操作的各种API,有包括数学、逻辑、形状操作、排序、选择、输入输出、离散傅立叶变换、基本线性代数,基本统计运算和随机模拟等等。
由此可见,numpy
是一个以数组为基础,包含各种骚操作和数学运算的框架。
1. 对比
俗话说,没有对比就没有伤害。numpy
为何这么优秀呢?先让我们了解一下原生python
的不足:
-
无法用广播的方式操作数组,例如:
l = [1,2,3] print(l*2) # 输出: [1, 2, 3, 1, 2, 3],而不是[2,4,6] print(l+l) # 输出: [1, 2, 3, 1, 2, 3],而不是[2,4,6] print(list(map(lambda x: x * 2, l))) # 才输出: [2,4,6]
-
无法快速生成一个数组,如:
print(range(1, 100, 2)) # 输出:range(1, 100, 2) print(list(range(1, 100, 2))) # 才输出:[1,3...97,99]
对于大量数据的相乘处理,速度很慢。
等等,详情见官网。
为什么numpy
运算速度很快呢,因为numpy
底层采用预编译的c
语言程序运行,比如数组相乘。
另外,numpy与matlab对比。
2. 入门
numpy
数组的核心是ndarray
对象。
2.1. 数组创建
>>> import numpy as np
# 依据数组进行创建
>>> a = np.array([1,2,3])
>>> a
array([1, 2, 3])
# 自动决定数据类型
>>> a.dtype
dtype('int32')
# 创建时指定数据类型
>>> a = np.array( [ [1,2], [3,4] ], dtype=complex )
>>> a
array([[1.+0.j, 2.+0.j],
[3.+0.j, 4.+0.j]])
# 生成全0数组
>>> a = np.zeros((3,4))
>>> a
array([[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]])
# 全1数组
>>> a = np.ones((2,3,4))
>>> a
array([[[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.]],
[[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.]]])
# 生成等差数组arange(start, stop, step)
>>> a = np.arange(10,30,5)
>>> a
array([10, 15, 20, 25])
# 生成随机数
>>> a = np.random.random((3,4))
>>> a
array([[0.58929938, 0.54624629, 0.08792059, 0.76392006],
[0.44203064, 0.12489059, 0.90234191, 0.43714071],
[0.30633888, 0.71889312, 0.42413405, 0.66626242]])
# 生成服从标准正态分布的随机数。
>>> a = np.random.randn(10)
>>> a
array([ 0.70899314, -0.80225292, -1.03481739, 0.23374236, 1.37977021,
-1.68141055, 0.04312959, -1.2086538 , 0.83465968, -0.24310517])
# numpy.random.normal(loc, scale, size), loc均值、scale标准差、size个数,生成普通正态分布。
2.2. ndarray对象属性
>>> import numpy as np
>>> a = np.arange(10,30,1).reshape(2,10)
>>> a
array([[10, 11, 12, 13, 14, 15, 16, 17, 18, 19],
[20, 21, 22, 23, 24, 25, 26, 27, 28, 29]])
# 维度的个数,几维
>>> a.ndim
2
# 维度,如(2,10)代表2行10列
>>> a.shape
(2, 10)
# 数组元素个数
>>> a.size
20
# 元素类型
>>> a.dtype
dtype('int32')
2.3. 基础运算
2.3.1. 简单运算
>>> import numpy as np
>>> a = np.array( [20,30,40,50] )
>>> b = np.arange( 4 )
>>> a
array([20, 30, 40, 50])
>>> b
array([0, 1, 2, 3])
# 两个对象相减/相乘等,广播至数组的每一个元素
>>> a-b
array([20, 29, 38, 47])
>>> a*b
array([ 0, 30, 80, 150])
# 单个对象运算,广播操作至数组的每一个元素
>>> b**2
array([0, 1, 4, 9], dtype=int32)
# 逻辑运算
>>> a<35
array([ True, True, False, False])
# +=, *= 等运算
>>> a += 3
>>> a
array([23, 33, 43, 53])
2.3.2. 进阶数学运算
- 求和、最大值、最小值
>>> a = np.arange( 4 )
>>> a
array([0, 1, 2, 3])
# 所有元素求和
>>> a.sum()
6
# 所有元素最小值
>>> a.min()
0
# 所有元素最大值
>>> a.max()
3
>>> b = np.arange(12).reshape(3,4)
>>> b
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
# 第一维度/列 求和
>>> b.sum(axis=0)
array([12, 15, 18, 21])
# 第二维度/行 求最小值
>>> b.min(axis=1)
array([0, 4, 8])
>>> b = np.arange(12).reshape(3,2,2)
>>> b
array([[[ 0, 1],
[ 2, 3]],
[[ 4, 5],
[ 6, 7]],
[[ 8, 9],
[10, 11]]])
>>> b.sum(axis=0)
array([[12, 15],
[18, 21]])
>>> b.sum(axis=1)
array([[ 2, 4],
[10, 12],
[18, 20]])
>>> b.sum(axis=2)
array([[ 1, 5],
[ 9, 13],
[17, 21]])
- 矩阵运算
>>> A = np.array( [[1,1],
... [0,1]] )
>>> B = np.array( [[2,0],
... [3,4]] )
# 按元素运算
>>> A * B
array([[2, 0],
[0, 4]])
# dot() 矩阵运算,区别于按元素运算
>>> A.dot(B)
array([[5, 4],
[3, 4]])
- 正弦、余弦、e^x、均值、标准差、开根
>>> a = np.arange( 4 )
>>> a
array([0, 1, 2, 3])
# sin() 正弦函数
>>> np.sin(a)
array([0. , 0.84147098, 0.90929743, 0.14112001])
# cos() 余弦函数
>>> np.cos(a)
array([ 1. , 0.54030231, -0.41614684, -0.9899925 ])
# exp() e^x函数
>>> np.exp(a)
array([ 1. , 2.71828183, 7.3890561 , 20.08553692])
# mean() 均值函数,也可以a.mean()
>>> np.mean(a)
1.5
# std() 标准差函数,也可以a.std()
>>> np.std(a)
1.118033988749895
# sqrt() 开根函数
>>> np.sqrt(a)
array([0. , 1. , 1.41421356, 1.73205081])
2.4. 索引与切片
>>> import numpy as np
>>> a = np.arange(12).reshape(3,4)
>>> a
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
# 下标索引,与原生数组类似
>>> a[0]
>>> a[-1]
array([ 8, 9, 10, 11])
>>> a[0][1]
1
# 赋值 + 切片的运用。a[0][::2]表示:第一行中从头到尾遍历,每次加2
>>> a[0][::2] = -1
>>> a
array([[-1, 1, -1, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
# 输出指定的行或列,注意在同一中括号中,如:[0:1,1]
>>> a[0:1, 1]
array([1])
>>> a[0:2, 1]
array([1, 5])
>>> a[:, 1]
array([1, 5, 9])
2.5. 形状操控
>>> import numpy as np
>>> a = np.arange(12)
>>> a
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
# 修改形状,需要原形状匹配,比如:12 = 3x4
>>> a.reshape(3,4)
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
# 单纯调用函数,不会改变原数组
>>> a
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
# 重新赋值才会改变
>>> a = a.reshape(3,4)
>>> a
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
>>> a.shape
(3, 4)
# 变成一维
>>> a = a.ravel()
>>> a
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
>>> a = a.reshape(2,6)
>>> a
array([[ 0, 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10, 11]])
# 装置矩阵
>>> a.T
array([[ 0, 6],
[ 1, 7],
[ 2, 8],
[ 3, 9],
[ 4, 10],
[ 5, 11]])
# 自动整形
>>> a.reshape(3,-1)
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
2.6. 合并
>>> a = np.floor(10*np.random.random((2,2)))
>>> a
array([[ 8., 8.],
[ 0., 0.]])
>>> b = np.floor(10*np.random.random((2,2)))
>>> b
array([[ 1., 8.],
[ 0., 4.]])
# 垂直方向合并
>>> np.vstack((a,b))
array([[ 8., 8.],
[ 0., 0.],
[ 1., 8.],
[ 0., 4.]])
# 水平方向合并
>>> np.hstack((a,b))
array([[ 8., 8., 1., 8.],
[ 0., 0., 0., 4.]])
2.7. 转换
>>> import numpy as np
>>> a_list = [1,2,3,4,5]
>>> b_numpy = np.array(a_list) # python原生列表转numpy数组
>>> b_numpy
array([1, 2, 3, 4, 5])
>>> c_list = b_numpy.tolist() # numpy数组转列表
>>> c_list
[1, 2, 3, 4, 5]