Numpy入门学习

Numpy, Numerical Python 是Python数值计算最重要的基础包,大部分科学计算包将 Numpy 作为数组构建基础,如 Pandas。

参考:《利用Python进行数据分析·第2版》第4章 NumPy基础 简书@SeanCheney

一、ndarray N维数组对象

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

# 产生 (2行, 3列) 正态分布随机数组
data = np.random.randn.(2, 3)
data
# array([[ 0.69788267, 0.52382967, 1.56062842],
# [-0.25449538, 0.7578153 , -0.88770831]])

# 数学运算
## 将所有的元素都 *10
data = data * 10
## 将元素自加
data = data + data

ndarray 中所有元素必须是相同类型的,每个数组都有一个 shape(一个表示各维度大小的元组)和一个 dtype(一个用于说明数组数据类型的对象)

1
2
3
4
print('data shape:', data.shape)
print('data dtype:', data.dtype)
# data shape: (2, 3)
# data dtype: float64

1 创建 ndarry

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
# 使用 array 创建
arr1 = np.array([1, 2, 3, 4.0])
print(arr1) # [ 1. 2. 3. 4.]

# 嵌套序列
arr2 = np.array([[1, 2, 3, 4], [5, 6, 7, 8]])
print(arr2)
# [[1 2 3 4]
# [5 6 7 8]]
# 查看 维度 和 shape
print(arr2.ndim) # n dim
print(arr2.shape) # shape
# 2
# (2, 4)

# 创建全 0 数组
np.zeros(10) # [ 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
np.zeros((3, 6))
# [[ 0. 0. 0. 0. 0. 0.]
# [ 0. 0. 0. 0. 0. 0.]
# [ 0. 0. 0. 0. 0. 0.]]

np.ones(3) # [ 1. 1. 1.]

# empty 分配内存空间
np.empty((2, 3, 2))
# [[[ 4.68935542e-310 0.00000000e+000]
# [ 0.00000000e+000 0.00000000e+000]
# [ 0.00000000e+000 0.00000000e+000]]

# [[ 0.00000000e+000 0.00000000e+000]
# [ 0.00000000e+000 0.00000000e+000]
# [ 0.00000000e+000 0.00000000e+000]]]

# 序列
np.arange(15) # [ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14]
  • dtype 自动选择合适的数据类型保存
  • 若不不指定,一般数据类型为 float64

2 ndarray 数据类型

1
2
3
4
5
6
7
arr1 = np.array([1, 2, 3], dtype=np.float64) # 设定 dtype float64
arr2 = np.array([1, 2, 3], dtype=np.int32) # 设定 dtype int32

# dtype 类型转换
arr = np.array([1, 2, 3, 4, 5]) # int64
float_arr = arr.astype(np.float64) # 使用 astype 将 int64 --> float64
# 如果将浮点数转换成整数,则小数部分将会被截取删除

3 NumPy 数组的运算

1
2
3
4
5
6
7
8
9
arr = np.array([[1., 2., 3.], [4., 5., 6.]])
print(arr)
print(arr * arr)
print(arr - arr)
# 数组与标量的算术运算会将标量值传播到各个元素
print(1 / arr)
print(arr ** 0.5)

# 大小相同的数组可以进行比较,并返回布尔值

4 数组广播

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
a = np.array([[0.0,0.0,0.0],[10.0,10.0,10.0],[20.0,20.0,20.0],[30.0,30.0,30.0]]) 
b = np.array([1.0,2.0,3.0])
print ('第一个数组:')
print (a)
print ('\n第二个数组:')
print (b)
print ('\n第一个数组加第二个数组:')
print (a + b)

# out
第一个数组:
[[ 0. 0. 0.]
[ 10. 10. 10.]
[ 20. 20. 20.]
[ 30. 30. 30.]]
第二个数组:
[ 1. 2. 3.]
第一个数组加第二个数组:
[[ 1. 2. 3.]
[ 11. 12. 13.]
[ 21. 22. 23.]
[ 31. 32. 33.]]

数组广播:数组 b 向 a 兼容填充

5 索引与切片

切片

1
2
3
4
5
6
7
8
9
10
11
# 产生十个序列值
arr = np.arange(10)
print (arr) # [0 1 2 3 4 5 6 7 8 9]
print (arr[5]) # arr的第6个元素
print (arr[5:8]) # arr的第6-8个元素,[5:8]左闭右开

arr[5:8] = 12 # 将 5-8 区间值设置 12,[ 0 1 2 3 4 12 12 12 8 9]
arr[5:8].copy() # copy

arr_slice = arr[5:8] # 设置一个 slice 设置到 [5:8]
arr_slice[1] = 12345 # slice[1] = arr[6]
  • 切片沿着一个轴向选取元素

布尔索引

1
2
3
4
5
6
7
8
9
10
names = np.array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'])
data = np.random.randn(7, 4)

print(names) # ['Bob' 'Joe' 'Will' 'Bob' 'Will' 'Joe' 'Joe']
print(data)
print(names == 'Bob') # [ True False False True False False False]
print(data[names == 'Bob'])
# out 返回 Bob 为 True 所在的维度
[[ 0.65351776 0.05222893 0.90505454 0.7626202 ]
[ 0.79504143 -1.44998811 -1.78426926 0.76580967]]

还可以使用常见布尔运算进行索引操作

  • ==
  • !=
  • ~
  • &
  • |

Fancy indexing 花式索引

花式索引(Fancy indexing)利用整数数组进行索引

1
2
3
4
5
6
7
8
arr = np.empty((8, 4))
for i in range(8):
arr[i] = i
print(arr[[-3, -5, -7]])
# out
[[ 5. 5. 5. 5.]
[ 3. 3. 3. 3.]
[ 1. 1. 1. 1.]]
  • 花式索引跟切片不一样,它总是将数据复制到新数组中。

6 数组转置和轴对换

转置

  • .T
  • transpose
  • swapaxes

二、通用函数

1 一元 ufunc

1
2
3
4
5
6
7
8
arr = np.arange(10)
print(np.sqrt(arr)) # sqrt
print(np.exp(arr)) # exp 指数e^x

# 二元元祖
x = np.random.randn(8)
y = np.random.randn(8)
print(np.maximum(x, y)) # 返回 (x, y) 中的最大值

1532335445187_0BKZZm1lJ0

1532335458652_RFShN0l2xv

2 二元 ufunc

1532335470408_8FbemgBmjb

##3 数据处理

1
2
points = np.arange(-5, 5, 0.01) # 1000 equally spaced points
xs, ys = np.meshgrid(points, points) # np.meshgrid 函数接受两个一维数组,并产生两个二维矩阵

###条件表达式

1
2
3
4
5
6
7
8
9
10
11
arr = np.random.randn(4, 4)
print(np.where(arr > 0, 2, -2)) # arr>0 为真返回 2,为假返回 -2
# out
[[ True False False False]
[ True False False True]
[ True False False False]
[ True True False True]]
[[ 2 -2 -2 -2]
[ 2 -2 -2 2]
[ 2 -2 -2 -2]
[ 2 2 -2 2]]

基本数组统计

1532337399414_zsVEc9M3uj

1532337427579_xUM07e2Pab

  • sum() 常常用来统计布尔值
  • any() 用于测试数组中是否存在一个或多个 True
  • all() 则检查数组中所有值是否都是 True

排序

numpy.sort()

1
2
3
4
5
# np.sort(a, axis, kind, order)
# a 要排序的数组
# axis 沿着它排序数组的轴,如果没有数组会被展开,沿着最后的轴排序
# kind 默认为'quicksort'(快速排序)
# order 如果数组包含字段,则是要排序的字段

numpy.argsort()

对输入数组沿给定轴执行间接排序,并使用指定排序类型返回数据的索引数组。

1
2
3
4
5
x = np.array([3,  1,  2])  
print (x) # [3 1 2]
y = np.argsort(x)
print (y) # [1 2 0]
print (x[y]) # [1 2 3]

numpy.lexsort()

函数使用键序列执行间接排序

1
2
3
4
5
nm =  ('raju','anil','ravi','amar') 
dv = ('f.y.', 's.y.', 's.y.', 'f.y.')
ind = np.lexsort((dv,nm))
print (ind) # [3 1 0 2]
print ([nm[i] + ", " + dv[i] for i in ind]) # ['amar, f.y.', 'anil, s.y.', 'raju, f.y.', 'ravi, s.y.']

删除重复值

numpy.unique()

1
2
3
4
names = np.array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'])
print(np.unique(names)) # ['Bob' 'Joe' 'Will']
ints = np.array([3, 3, 3, 2, 2, 1, 1, 4, 4])
print(np.unique(ints)) # [1 2 3 4]

1532344723859_4h6GNbxSX0

4 文件IO

数据以未压缩原始的二进制文件存储在 .npy 文件中

  • np.save() 数据保存
  • np.load() 数据加载
  • np.savez_compressed() 数据压缩
1
2
3
arr = np.arange(10)
np.save('some_array', arr)
print(np.load('some_array.npy')) # [0 1 2 3 4 5 6 7 8 9]

5 线性代数

1532395494278_3HFijr6hp1

6 伪随机数生成

1
2
3
4
5
6
7
8
9
# 产生 normal 正态分布 4x4 样本随机数
samples = np.random.normal(size=(4, 4))

# 随机数生成种子
np.random.seed()

# 创建隔离的随机数生成器
rng = np.random.RandomState(1234)
print(rng.randn(10))

1532396098921_nPO32YQSPz

1532396134795_xoavwwVypd