numpy学习笔记

0. 前言

鉴于在卓越班暑期学习中,接触到机器学习的内容,索性深入研究一番,蹭一蹭机器学习的热度。

众所周知,学习机器学习之前,必须学习数据分析。而numpy则是数据分析的第一道关。

numpy的官网中,如此介绍:

NumPy是Python中科学计算的基础包。它是一个Python库,提供多维数组对象,各种派生对象(如掩码数组和矩阵),以及用于数组快速操作的各种API,有包括数学、逻辑、形状操作、排序、选择、输入输出、离散傅立叶变换、基本线性代数,基本统计运算和随机模拟等等。

由此可见,numpy是一个以数组为基础,包含各种骚操作和数学运算的框架。

1. 对比

俗话说,没有对比就没有伤害。numpy为何这么优秀呢?先让我们了解一下原生python的不足:

  • 无法用广播的方式操作数组,例如:

    1
    2
    3
    4
    5
    6
    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]
  • 无法快速生成一个数组,如:

    1
    2
    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. 数组创建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
>>> 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对象属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
>>> 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. 简单运算

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
>>> 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. 进阶数学运算

  • 求和、最大值、最小值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
>>> 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]])
  • 矩阵运算
1
2
3
4
5
6
7
8
9
10
11
12
13
14
>>> 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、均值、标准差、开根
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
>>> 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. 索引与切片

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
>>> 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. 形状操控

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
>>> 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. 合并

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
>>> 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. 转换

1
2
3
4
5
6
7
8
>>> 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]