Numpy 和 Python List 的差别

在 Numpy 中,我们会一直使用到它的一种 Array 数据。List 和 Numpy array 共同点, 存储并且可以按顺序提取出来, 对内部的一个值进行修改也是同样的逻辑。

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

1
1

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

[-1, 2, 3]
[-1 2 3]

Numpy 的优势

Numpy的核心优势:运算快。用专业的语言描述的话,Numpy 喜欢用电脑内存中连续的一块物理地址存储数据,因为都是连号的嘛,找到前后的号,不用跑很远, 非常迅速。而 Python 的 List 并不是连续存储的,它的数据是分散在不同的物理空间,在批量计算的时候,连号的肯定比不连号的算起来更快。因为找他们的时间更少了。而且 Numpy Array 存储的数据格式也有限制,尽量都是同一种数据格式,这样也有利于批量的数据计算。 所以只要是处理大规模数据的批量计算,Numpy 肯定会比 Python 的原生 List 要快。
numpy_list.png

  1. import time
  2. t0 = time.time()
  3. # python list
  4. l = list(range(100))
  5. for _ in range(10000):
  6. for i in range(len(l)):
  7. l[i] += 1
  8. t1 = time.time()
  9. # numpy array
  10. a = np.array(l)
  11. for _ in range(10000):
  12. a += 1
  13. print("Python list spend {:.3f}s".format(t1-t0))
  14. print("Numpy array spend {:.3f}s".format(time.time()-t1))

Python list spend 0.102s
Numpy array spend 0.012s
Numpy Array 和 Python List 在很多使用场景上是可以互换的,不过在大数据处理的场景下,而且你的数据类型又高度统一, 那么 Numpy 绝对是你不二的人选,能提升的运算速度也是杠杠的~

创建数据

np.array(),array.ndim

1维
  1. >>> import numpy as np
  2. >>>
  3. >>> cars = np.array([5, 10, 12, 6])
  4. >>> print("数据:", cars, "\n维度:", cars.ndim)
  5. 数据: [ 5 10 12 6]
  6. 维度: 1

2维
  1. >>> cars = np.array([
  2. ... [5, 10, 12, 6],
  3. ... [5.1, 8.2, 11, 6.3],
  4. ... [4.4, 9.1, 10, 6.6]
  5. ... ])
  6. >>>
  7. >>> print("数据:\n", cars, "\n维度:", cars.ndim)
  8. 数据:
  9. [[ 5. 10. 12. 6. ]
  10. [ 5.1 8.2 11. 6.3]
  11. [ 4.4 9.1 10. 6.6]]
  12. 维度: 2

3维
  1. cars = np.array([
  2. [
  3. [5, 10, 12, 6],
  4. [5.1, 8.2, 11, 6.3],
  5. [4.4, 9.1, 10, 6.6]
  6. ],
  7. [
  8. [6, 11, 13, 7],
  9. [6.1, 9.2, 12, 7.3],
  10. [5.4, 10.1, 11, 7.6]
  11. ],
  12. ])
  13. print("总维度:", cars.ndim)
  14. print("场地 1 数据:\n", cars[0], "\n场地 1 维度:", cars[0].ndim)
  15. print("场地 2 数据:\n", cars[1], "\n场地 2 维度:", cars[1].ndim)
  16. print("场地 1 数据,第一行:", cars[0][0])
  17. print("场地 1 数据,第一行,第一个元素:", cars[0][0][0])

总维度: 3
场地 1 数据:
[[ 5. 10. 12. 6. ]
[ 5.1 8.2 11. 6.3]
[ 4.4 9.1 10. 6.6]]
场地 1 维度: 2
场地 2 数据:
[[ 6. 11. 13. 7. ]
[ 6.1 9.2 12. 7.3]
[ 5.4 10.1 11. 7.6]]
场地 2 维度: 2
场地 1 数据,第一行: [ 5. 10. 12. 6.]
场地 1 数据,第一行,第一个元素: 5.0

添加数据

np.concatenate(), np.expand_dims()

一维添加元素
  1. cars1 = np.array([5, 10, 12, 6])
  2. cars2 = np.array([5.2, 4.2])
  3. cars = np.concatenate([cars1, cars2])
  4. print(cars)
  5. [ 5. 10. 12. 6. 5.2 4.2]

添加维度
  1. test1 = np.array([5, 10, 12, 6])
  2. test2 = np.array([5.1, 8.2, 11, 6.3])
  3. print("test1加维度前 ", test1)
  4. print("test2加维度前 ", test2)
  5. # 首先需要把它们都变成二维,下面这两种方法都可以加维度
  6. test1 = np.expand_dims(test1, 0)
  7. test2 = test2[np.newaxis, :]
  8. print("test1加维度后 ", test1)
  9. print("test2加维度后 ", test2)
  10. # 然后再在第一个维度上叠加
  11. all_tests = np.concatenate([test1, test2])
  12. print("括展后\n", all_tests)

test1加维度前 [ 5 10 12 6]
test2加维度前 [ 5.1 8.2 11. 6.3]
test1加维度后 [[ 5 10 12 6]]
test2加维度后 [[ 5.1 8.2 11. 6.3]]
括展后
[[ 5. 10. 12. 6. ]
[ 5.1 8.2 11. 6.3]]

合并数据

np.concatenate() 矩阵行列合并

在第二个维度上叠加, 只需要巧妙给 np.concatenate 一个参数就好。

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

注意,有些数据维度是对不齐的,这样没办法合并。

  1. a = np.array([
  2. [1,2,3],
  3. [4,5,6]
  4. ])
  5. b = np.array([
  6. [7,8],
  7. [9,10]
  8. ])
  9. print(np.concatenate([a,b], axis=1)) # 这个没问题
  10. print(np.concatenate([a,b], axis=0)) # 这个会报错

[[ 1 2 3 7 8]
[ 4 5 6 9 10]]
ValueError: all the input array dimensions for the concatenation axis must match exactly, but along dimension 1, the array at index 0 has size 3 and the array at index 1 has size 2

np.vstack(); np.hstack() 两个比较好用的在二维数据上可以方便调用的合并函数

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

观察数据形态

除了 np.ndim 来查看数据的形态,其实我们有时候还想更加了解数据的细节问题,比如这个数据的大小,规格。方便我们管理这些数据。比如当我想知道到底有多少车辆测试数据时,你可能会通过遍历的方法来计数。

array.size; array.shape

  1. cars = np.array([
  2. [5, 10, 12, 6],
  3. [5.1, 8.2, 11, 6.3],
  4. [4.4, 9.1, 10, 6.6]
  5. ])
  6. print("总共多少测试数据:", cars.size)
  7. print("第一个维度:", cars.shape[0])
  8. print("第二个维度:", cars.shape[1])
  9. print("所有维度:", cars.shape)

总共多少测试数据: 12
第一个维度: 3
第二个维度: 4
所有维度: (3, 4)