Numpy简介

什么时候使用Numpy?

  1. 需要批量处理数据的时候
  2. 机器学习,人工智能这些需要进行海量数据运算处理的地方
  3. 写游戏里面的物体运行逻辑时,经常涉及到矩阵、向量运算
  4. 机器人模拟环境,背后的环境反馈信息,全是靠批量数据算出来的
  5. 任何需要做统计的时候(爬虫爬完了信息后)
  6. 画图表之前,要对数据做一轮批量处理
  7. Blah blah

List 和 Numpy array 共同点

存储和提取:

List:

1
2
my_list = [1,2,3]
print(my_list[0])

Numpy Array:

1
2
my_array = np.array([1,2,3])
print(my_array[0])

对内部值进行修改

1
2
3
4
my_list[0] = -1
my_array[0] = -1
print(my_list)
print(my_array)

Numpy 的优势

Numpy的核心优势:运算快。Numpy 用电脑内存中连续的一块物理地址存储数据,因为都是连号,找到前后的号,不用跑很远, 非常迅速。而 Python 的 List 并不是连续存储的,它的数据是分散在不同的物理空间,在批量计算的时候,连号的肯定比不连号的算起来更快。因为找他们的时间更少了。

而且 Numpy Array 存储的数据格式也有限制,尽量都是同一种数据格式,这样也有利于批量的数据计算。 所以只要是处理大规模数据的批量计算,Numpy 肯定会比 Python 的原生 List 要快。

基本操作

创建数据

  • np.array()

  • array.ndim

添加数据

  • np.concatenate()

  • np.expand_dims()

合并数据

  • np.concatenate()

  • np.vstack()

  • np.hstack()

观察形态

  • array.size

  • array.shape

创建多维数据

1
2
3
4
import numpy as np

cars = np.array([5, 10, 12, 6])
print("数据:", cars, "\n维度:", cars.ndim) #cars.ndim 会返回给你一个维度的属性

创建二维数据

1
2
3
4
5
6
7
cars = np.array([
[5, 10, 12, 6],
[5.1, 8.2, 11, 6.3],
[4.4, 9.1, 10, 6.6]
])

print("数据:\n", cars, "\n维度:", cars.ndim)

创建三维数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
cars = np.array([
[
[5, 10, 12, 6],
[5.1, 8.2, 11, 6.3],
[4.4, 9.1, 10, 6.6]
],
[
[6, 11, 13, 7],
[6.1, 9.2, 12, 7.3],
[5.4, 10.1, 11, 7.6]
],
])

print("总维度:", cars.ndim)
print("场地 1 数据:\n", cars[0], "\n场地 1 维度:", cars[0].ndim)
print("场地 2 数据:\n", cars[1], "\n场地 2 维度:", cars[1].ndim)

添加数据

添加一维

1
2
3
4
5
cars1 = np.array([5, 10, 12, 6])
cars2 = np.array([5.2, 4.2])
cars = np.concatenate([cars1, cars2])
print(cars)
#输出结果:[ 5. 10. 12. 6. 5.2 4.2]

添加二维

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
test1 = np.array([5, 10, 12, 6])
test2 = np.array([5.1, 8.2, 11, 6.3])

# 首先需要把它们都变成二维,下面这两种方法都可以加维度
test1 = np.expand_dims(test1, 0)
test2 = test2[np.newaxis, :]

print("test1加维度后 ", test1)
print("test2加维度后 ", test2)

# 然后再在第一个维度上叠加
all_tests = np.concatenate([test1, test2])
print("括展后\n", all_tests)

#输出结果:
test1加维度后 [[ 5 10 12 6]]
test2加维度后 [[ 5.1 8.2 11. 6.3]]
括展后
[[ 5. 10. 12. 6. ]
[ 5.1 8.2 11. 6.3]]

合并数据

1
2
print("第一维度叠加:\n", np.concatenate([all_tests, all_tests], axis=0))
print("第二维度叠加:\n", np.concatenate([all_tests, all_tests], axis=1))

只要维度能够对齐,就可以在任意维度上进行合并操作。注意,有些数据维度是对不齐的,这样没办法合并。比如:

1
2
3
4
5
6
7
8
9
10
11
a = np.array([
[1,2,3],
[4,5,6]
])
b = np.array([
[7,8],
[9,10]
])

print(np.concatenate([a,b], axis=1)) # 这个没问题
# print(np.concatenate([a,b], axis=0)) # 这个会报错

除了 np.concatenate(),还有两个在二维数据上可以方便调用的功能,分别是 np.vstack()和np.hstack().可以将数据横向合并,也可以将数据竖向合并。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
a = np.array([
[1,2],
[3,4]
])
b = np.array([
[5,6],
[7,8]
])
print("竖直合并\n", np.vstack([a, b]))
print("水平合并\n", np.hstack([a, b]))

#运行结果
竖直合并
[[1 2]
[3 4]
[5 6]
[7 8]]
水平合并
[[1 2 5 6]
[3 4 7 8]]

观察形态

除了 np.ndim 来查看数据的形态,还需要了解数据的细节问题,比如这个数据的大小,规格。方便我们管理这些数据。

获取总个数:使用 cars.size

1
2
3
4
print("总共多少测试数据:", cars.size)

#输出结果
总共多少测试数据: 12

更进一步,我不光想知道总数据,我还想知道当前有多少次测试(第一个维度,行),和在多少辆车上测试了(第二个维度,列)

1
2
3
4
5
6
7
8
print("第一个维度:", cars.shape[0])
print("第二个维度:", cars.shape[1])
print("所有维度:", cars.shape)

#运行结果
第一个维度: 3
第二个维度: 4
所有维度: (3, 4)

数据选择

  • 单个选取
    • array[1]
    • array[1,2,3]
    • array[1][1]
  • 切片划分
    • array[:3]
    • array[2:4, 1:3]
  • 条件筛选
    • array[array<0]
    • np.where(array, array < 0)

单个选取:单个单个的选择

1
2
3
4
5
6
7
8
import numpy as np

a = np.array([1, 2, 3])
print("a[0]:", a[0])
print("a[1]:", a[1])
#运行结果
a[0]: 1
a[1]: 2

一次性选择多个:实际上选择的逻辑还是一个个拎出来的逻辑

1
2
3
4
5
6
7
8
print("a[[0,1]]:\n", a[[0,1]])
print("a[[1,1,0]]:\n", a[[1,1,0]])
#运行结果
a[[0,1]]:
[1 2]
a[[1,1,0]]:
[2 2 1]

总结:索引到具体的数上,就能拎出这个数具体的值

切片划分

1
2
3
4
5
6
7
8
9
10
11
a = np.array([1, 2, 3])
print("a[0:2]:\n", a[0:2])
print("a[1:]:\n", a[1:])
print("a[-2:]:\n", a[-2:])
#运行结果
a[0:2]:
[1 2]
a[1:]:
[2 3]
a[-2:]:
[2 3]

使用 : 就能让你跨着取数字,而且一次取一批。

注意:在 Numpy 中一次取一批和一个个拎起来,拎了一批,是不同的概念

条件筛选

按位置选:请这队同学中,第 2 号到第 6 号的同学出列

按数条件:请这队同学中,身高高于 1.5 米的同学出列

1
2
3
4
5
6
7
8
9
a = np.array([
[1,2,3,4],
[5,6,7,8],
[9,10,11,12]
])

print(a[a>7]) #选取的是 a 数据中,大于 7 的数据
#运行结果
[ 8 9 10 11 12]

除了这种直接用[]的形式,在 Numpy 中,还可以用np.where()函数来做数据筛选。这种筛选更强大,它还能做筛选结果的替换工作。 它可已将满足条件的位置变成你设定的数字。下面满足条件的,都改成 -1,不满足的,都还是 a 里面的数字。

1
2
3
4
5
6
condition = a > 7
print(np.where(condition, -1, a))
#运行结果
[[ 1 2 3 4]
[ 5 6 7 -1]
[-1 -1 -1 -1]]

或者,不仅是满足条件的 condition,不满足条件的,也能变成你期望的数字。

1
2
3
4
5
6
condition = a > 7
print(np.where(condition, -1, 2))
#运行结果
[[ 2 2 2 2]
[ 2 2 2 -1]
[-1 -1 -1 -1]]

还能让它和另外一个数据做条件上的整合

1
2
3
4
5
6
7
condition = a > 7
b = -a - 1
print(np.where(condition, a, b))
#运行结果
[[-2 -3 -4 -5]
[-6 -7 -8 8]
[ 9 10 11 12]]

基础运算

  • 加减乘除
    • +-*/
    • np.dot()
  • 数据统计分析
    • np.max() np.min() np.sum() np.prod() np.count()
    • np.std() np.mean() np.median()
  • 特殊运算符号
    • np.argmax() np.argmin()
    • np.ceil() np.floor() np.clip()

加减乘除

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import numpy as np

a = np.array([150, 166, 183, 170])
print(a + 3)
#运算结果
[153 169 186 173]


print("a + 3:", a + 3)
print("a - 3:", a - 3)
print("a * 3:", a * 3)
print("a / 3:", a / 3)
#运算结果
a + 3: [153 169 186 173]
a - 3: [147 163 180 167]
a * 3: [450 498 549 510]
a / 3: [50. 55.33333333 61. 56.66666667]

矩阵点积运算:1)直接用一个矩阵 dot 另一个;2)用 np.dot(a, b) 把两个矩阵包起来

1
2
3
4
5
6
7
8
9
10
11
a = np.array([
[1, 2],
[3, 4]
])
b = np.array([
[5, 6],
[7, 8]
])

print(a.dot(b))
print(np.dot(a, b))

其他矩阵运算:

np.outer() 矩阵外积,np.inner() 矩阵内积 (可以理解成 np.dot(a, b)= np.inner(a, b.T), 把 b 做一次转置)

数据统计分析

  1. np.max() np.min() np.sum() np.prod() np.count()#最大,最小,累加,累乘,计数。
  2. np.std() np.mean() np.median()#标准差,平均值,中位数。

特殊运算符号

  • np.argmax() np.argmin()#最大最小值所对应的序号
  • np.ceil() np.floor() np.clip()#取天花板的值还是地板的值,上下界限的值截取

改变数据形态

  • 改变形态
    • array[np.newaxis, :]
    • array.reshape()
    • array.ravel(), array.flatten()
    • array.transpose()
  • 合并
    • np.column_stack(), np.row_stack()
    • np.vstack(), np.hstack(), np.stack()
    • np.concatenate()
  • 拆解
    • np.vsplit(), np.hsplit(), np.split()