numpy

Numpy

1
%timeit [i**5 for i in range(10000)]
2.28 ms ± 34.8 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
1
%magic
1
!ls
lesson1.ipynb
1
!pwd
/home/xiaojia/Jupyter notebook
1
2
l=list(range(10))
l
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
1
import numpy as np
1
np.array([1,4,2,5,3])
array([1, 4, 2, 5, 3])
  • numpy要求数组必须包含同一类型的数据,如果不匹配,则会向上转换(如果可行)
1
np.array([3.14,4,2,3])
array([3.14, 4.  , 2.  , 3.  ])
1
np.array([1,2,3,4],dtype='float32')
array([1., 2., 3., 4.], dtype=float32)
1
np.array([range(i,i+3) for i in [2,4,6]])
array([[2, 3, 4],
       [4, 5, 6],
       [6, 7, 8]])
1
2
3
# 创建一个长度为10的数组,数组的值都是0

np.zeros(10,dtype='int')
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
1
2
3
# 创建一个3×5的浮点型数组,数组的值都是1

np.ones((3,5),dtype='float')
array([[1., 1., 1., 1., 1.],
       [1., 1., 1., 1., 1.],
       [1., 1., 1., 1., 1.]])
1
2
3
# 创建一个3×5的浮点型数组,数组的值都是3.14

np.full((3,5),3.14)
array([[3.14, 3.14, 3.14, 3.14, 3.14],
       [3.14, 3.14, 3.14, 3.14, 3.14],
       [3.14, 3.14, 3.14, 3.14, 3.14]])
1
2
3
# 创建一个3×5的浮点型数组,数组的值是一个线性序列
# 从0开始,到20结束,步长为2
np.arange(0,20,2)
array([ 0,  2,  4,  6,  8, 10, 12, 14, 16, 18])
1
2
3
# 创建一个5个元素的数组,这5个数均匀的分配到0~1

np.linspace(0,1,5)
array([0.  , 0.25, 0.5 , 0.75, 1.  ])
1
2
# 创建一个3×3的,在0~1均匀分布的随机数组成的数组
np.random.random((3,3))
array([[0.41803761, 0.26574943, 0.54544734],
       [0.80726465, 0.67950099, 0.4894307 ],
       [0.52957533, 0.15683473, 0.93671831]])
1
2
# 创建一个3×3的,均值为0,方差为1的正态分布的随机数数组
np.random.normal(0,1,(3,3))
array([[ 1.2054708 , -0.57884674, -0.38873164],
       [ 0.1203952 ,  0.78128962, -0.18781644],
       [ 0.70170648, -1.2019464 ,  1.46245566]])
1
2
# 创建一个3×3的,[0,10)区间的随机整型数组
np.random.randint(0,10,(3,3))
array([[1, 8, 2],
       [5, 5, 3],
       [8, 7, 1]])
1
2
# 创建一个3×3的单位矩阵
np.eye(3)
array([[1., 0., 0.],
       [0., 1., 0.],
       [0., 0., 1.]])
1
2
3
# 创建一个由3个整型数组成的未初始化的数组
# 数组的值是内存空间中的任意值
np.empty(3)
array([1., 1., 1.])
数据类型 描述
bool_ 布尔型数据类型(True 或者 False)
int_ 默认的整数类型(类似于 C 语言中的 long,int32 或 int64)
intc 与 C 的 int 类型一样,一般是 int32 或 int 64
intp 用于索引的整数类型(类似于 C 的 ssize_t,一般情况下仍然是 int32 或 int64)
int8 字节(-128 to 127)
int16 整数(-32768 to 32767)
int32 整数(-2147483648 to 2147483647)
int64 整数(-9223372036854775808 to 9223372036854775807)
uint8 无符号整数(0 to 255)
uint16 无符号整数(0 to 65535)
uint32 无符号整数(0 to 4294967295)
uint64 无符号整数(0 to 18446744073709551615)
float_ float64 类型的简写
float16 半精度浮点数,包括:1 个符号位,5 个指数位,10 个尾数位
float32 单精度浮点数,包括:1 个符号位,8 个指数位,23 个尾数位
float64 双精度浮点数,包括:1 个符号位,11 个指数位,52 个尾数位
complex_ complex128 类型的简写,即 128 位复数
complex64 复数,表示双 32 位浮点数(实数部分和虚数部分)
complex128 复数,表示双 64 位浮点数(实数部分和虚数部分)

numpy 的数值类型实际上是 dtype 对象的实例,并对应唯一的字符,包括 np.bool_,np.int32,np.float32,等等。

1
np.zeros(10,dtype='int16')
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0], dtype=int16)
1
np.zeros(10,dtype=np.int16)
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0], dtype=int16)

numpy数组基础

1
import numpy as np
1
np.random.seed(0) # 设置随机数种子
1
2
3
4
x1=np.random.randint(10,size=6) # 一维数组
x2=np.random.randint(10,size=(3,4)) # 二维数组
x3=np.random.randint(10,size=(3,4,5)) # 三维数组
x3
array([[[2, 1, 3, 4, 1],
        [1, 0, 7, 8, 4],
        [3, 5, 6, 3, 2],
        [9, 8, 1, 4, 0]],

       [[8, 3, 9, 5, 5],
        [1, 7, 8, 6, 4],
        [7, 3, 5, 3, 6],
        [4, 7, 3, 0, 5]],

       [[9, 3, 7, 5, 5],
        [8, 0, 8, 3, 6],
        [9, 3, 2, 7, 0],
        [3, 0, 3, 6, 1]]])
1
2
3
print('x3 ndim:',x3.ndim)
print('x3 shape:',x3.shape)
print('x3 size:',x3.size)
x3 ndim: 3
x3 shape: (3, 4, 5)
x3 size: 60
1
x1
array([4, 5, 0, 3, 1, 4])
1
x1[0]
4
1
x1[-1]
4
1
x1[-3]
3
1
x2
array([[4, 4, 0, 0],
       [8, 4, 6, 9],
       [3, 3, 2, 1]])
1
x2[0,0]
4
1
x2[2,0]
3
1
x2[0,0]=12
1
x2
array([[12,  4,  0,  0],
       [ 8,  4,  6,  9],
       [ 3,  3,  2,  1]])

切片

1
2
x=np.arange(10)
x
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
1
x[:5]
array([0, 1, 2, 3, 4])
1
x[5]
5
1
x[5:]
array([5, 6, 7, 8, 9])
1
x[5:7]
array([5, 6])
1
x[::2]
array([0, 2, 4, 6, 8])
1
x[1::2]
array([1, 3, 5, 7, 9])
1
x[::-1] # 逆序
array([9, 8, 7, 6, 5, 4, 3, 2, 1, 0])
1
x[5::-2]
array([5, 3, 1])
1
x2
array([[12,  4,  0,  0],
       [ 8,  4,  6,  9],
       [ 3,  3,  2,  1]])
1
x2[:2,:3]
array([[12,  4,  0],
       [ 8,  4,  6]])
1
x2[:3,::2]
array([[12,  0],
       [ 8,  6],
       [ 3,  2]])
1
x2[::-1,::-1]
array([[ 1,  2,  3,  3],
       [ 9,  6,  4,  8],
       [ 0,  0,  4, 12]])
1
print(x2[:,0])
[12  8  3]
1
x2[0,:]
array([12,  4,  0,  0])
1
print(x2[0])# 等于x2[0,:]
[12  4  0  0]
创建数组的视图

numpy数组切片返回的是数组数据的视图,而不是副本,这一点跟Python列表切片不同

1
x2_sub=x2[:2,:2]
1
x2_sub
array([[12,  4],
       [ 8,  4]])
1
x2_sub[0,0]=99
1
x2_sub
array([[99,  4],
       [ 8,  4]])
1
x2
array([[99,  4,  0,  0],
       [ 8,  4,  6,  9],
       [ 3,  3,  2,  1]])

这种默认的处理方式实际上非常有用:它意味着在处理非常大的数据集时,可以获取或处理这些数据集的片段,而不用复制底层的数据缓存

创建数组的副本
1
2
x2_sub_copy=x2[:2,:2].copy()
x2_sub_copy
array([[99,  4],
       [ 8,  4]])
1
2
x2_sub_copy[0,0]=33
x2_sub_copy
array([[33,  4],
       [ 8,  4]])
1
x2
array([[99,  4,  0,  0],
       [ 8,  4,  6,  9],
       [ 3,  3,  2,  1]])
1
grid=np.arange(1,10).reshape((3,3))
1
grid
array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]])
1
x=np.array([1,2,3])
1
2
# 通过变形获得的行向量
x.reshape((1,3))
array([[1, 2, 3]])
1
2
# 通过newaxis获得的行向量
x[np.newaxis,:]
array([[1, 2, 3]])
1
x.reshape((3,1))
array([[1],
       [2],
       [3]])
1
2
# 通过newaxis获得的列向量
x[:,np.newaxis]
array([[1],
       [2],
       [3]])

数组拼接和分裂

1
2
3
x=np.array([1,2,3])
y=np.array([3,2,1])
np.concatenate([x,y])
array([1, 2, 3, 3, 2, 1])
1
2
z=[99,99,99]
print(np.concatenate([x,y,z]))
[ 1  2  3  3  2  1 99 99 99]
1
grid=np.array([[1,2,3],[4,5,6]])
1
grid
array([[1, 2, 3],
       [4, 5, 6]])
1
2
# 沿着第一个轴拼接
np.concatenate([grid,grid],axis=0)
array([[1, 2, 3],
       [4, 5, 6],
       [1, 2, 3],
       [4, 5, 6]])
1
2
# 沿着第二个轴拼接(从0开始索引)
np.concatenate([grid,grid],axis=1)
array([[1, 2, 3, 1, 2, 3],
       [4, 5, 6, 4, 5, 6]])
1
2
x=np.array([1,2,3])
grid=np.array([[9,8,7],[6,5,4]])
1
np.vstack([x,grid])
array([[1, 2, 3],
       [9, 8, 7],
       [6, 5, 4]])
1
y=np.array([[99],[99]])
1
np.hstack([[9,8,7,99],[6,5,4,99]])
array([ 9,  8,  7, 99,  6,  5,  4, 99])

与之类似,np.dstack将沿着第三个维度拼接数组

1
x=[1,2,3,99,99,3,2,1]
1
2
x1,x2,x3=np.split(x,[3,6])
print(x1,x2,x3)
[1 2 3] [99 99  3] [2 1]
1
2
grid=np.arange(16).reshape((4,4))
grid
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [12, 13, 14, 15]])
1
2
3
upper,lower=np.vsplit(grid,[2])
print(upper)
print(lower)
[[0 1 2 3]
 [4 5 6 7]]
[[ 8  9 10 11]
 [12 13 14 15]]
1
2
3
left,right=np.hsplit(grid,[2])
print(left)
print(right)
[[ 0  1]
 [ 4  5]
 [ 8  9]
 [12 13]]
[[ 2  3]
 [ 6  7]
 [10 11]
 [14 15]]

同样,np.dsplit将数组沿着第三个维度分裂

1
import numpy as np

numpy数组的计算:通用函数

1
2
3
4
5
6
7
x=np.arange(4)
print(x)
print(x+5)
print(x-5)
print(x*2)
print(x/2)
print(x//2)
[0 1 2 3]
[5 6 7 8]
[-5 -4 -3 -2]
[0 2 4 6]
[0.  0.5 1.  1.5]
[0 0 1 1]
1
2
3
print(-x)
print(x**2)
print(x%2)
[ 0 -1 -2 -3]
[0 1 4 9]
[0 1 0 1]

numpy实现的算术运算符

运算符 对应的通用函数 描述
+ np.add 加法
- np.subtract 减法
- np.negative 负数
* np.multiply 乘法
/ np.divide 除法
// np.floor_divide 地板除法
** np.power 指数
% np.mod 取模
1
2
x=np.array([-2,-1,0,1,2])
abs(x)
array([2, 1, 0, 1, 2])
1
np.abs(x)
array([2, 1, 0, 1, 2])

三角函数

1
theta=np.linspace(0,np.pi,3)
1
theta
array([0.        , 1.57079633, 3.14159265])
1
np.sin(theta)
array([0.0000000e+00, 1.0000000e+00, 1.2246468e-16])
1
np.cos(theta)
array([ 1.000000e+00,  6.123234e-17, -1.000000e+00])
1
np.tan(theta)
array([ 0.00000000e+00,  1.63312394e+16, -1.22464680e-16])
1
x=[-1,0,1]
1
np.arcsin(x)
array([-1.57079633,  0.        ,  1.57079633])
1
np.arccos(x)
array([3.14159265, 1.57079633, 0.        ])
1
np.arctan(x)
array([-0.78539816,  0.        ,  0.78539816])

指数和对数

1
2
3
4
5
x=[1,2,3]
print(x)
print("e^x=",np.exp(x))
print("2^x=",np.exp2(x))
print("3^x=",np.power(3,x))
[1, 2, 3]
e^x= [ 2.71828183  7.3890561  20.08553692]
2^x= [2. 4. 8.]
3^x= [ 3  9 27]
1
2
3
4
5
x=[1,2,4,10]
print(x)
print("ln(x) =",np.log(x))
print("log2(x) =",np.log2(x))
print("log10(x) =",np.log10(x))
[1, 2, 4, 10]
ln(x)    = [0.         0.69314718 1.38629436 2.30258509]
log2(x)  = [0.         1.         2.         3.32192809]
log10(x) = [0.         0.30103    0.60205999 1.        ]
高级的通用函数特性
1
2
3
4
5
# 1.指定输出
x=np.arange(5)
y=np.empty(5)
np.multiply(x,10,out=y)
print(y)
[ 0. 10. 20. 30. 40.]
1
2
3
# 2.聚合
x=np.arange(1,6)
np.add.reduce(x)
15
1
np.add.accumulate(x) # 取中间结果
array([ 1,  3,  6, 10, 15])
1
2
3
4
# 3.外积
# 两个数组所有元素对的函数运算结果
x=np.arange(1,6)
np.multiply.outer(x,x)
array([[ 1,  2,  3,  4,  5],
       [ 2,  4,  6,  8, 10],
       [ 3,  6,  9, 12, 15],
       [ 4,  8, 12, 16, 20],
       [ 5, 10, 15, 20, 25]])
函数名称 NaN安全版本 描述
np.sum np.nansum
np.prod np.nanprod
np.mean np.nanmean 平均
np.std np.nanstd 标准差
np.var np.nanvar 方差
np.min np.nanmin 最小值
np.max np.nanmax 最大值
np.argmin np.nanargmin 最小值索引
np.argmax np.nanargmax 最大值索引
np.median np.nanmedian 中位数
np.percentile np.nanpercentile 计算基于元素排序的统计值
np.any N/A 验证任何一个元素是否为真
np.all N/A 验证所有元素是否为真

案例:美国总统的身高是多少

1
2
import numpy as np
import pandas as pd
1
2
3
data=pd.read_csv('president_heights.csv')
heights=np.array(data['height(cm)'])
print(heights)
[189 170 189 175 178 187 173 179 176 177 182 189 175 197 168 169 165 179
 168 179 187 190 193 179 176 177 179 180 171]
1
2
3
4
print("Mean height:        ",heights.mean())
print("Standard deviation: ",heights.std())
print("Minimum height: ",heights.min())
print("Maximun height: ",heights.max())
Mean height:         179.17241379310346
Standard deviation:  8.000297259637819
Minimum height:      165
Maximun height:      197
1
2
3
print("25th percentile:",np.percentile(heights,25))
print("Median: ",np.median(heights))
print("75th percentile:",np.percentile(heights,75))
25th percentile: 175.0
Median:          179.0
75th percentile: 187.0
1
2
3
%matplotlib inline
import matplotlib.pyplot as plt
import seaborn;seaborn.set()
1
2
3
4
plt.hist(heights)
plt.title('Height Distribution of US Presidents')
plt.xlabel('height(cm)')
plt.ylabel('number')
Text(0, 0.5, 'number')

BanhHP.png

广播的规则

规则1:如果两个数组的维度数不相同,那么小维度数组的形状将会在最左边补1

规则2:如果两个数组的形状在任何一个维度上都不匹配,那么数组的形状会沿着维度为1的维度扩展以匹配另外一个数组的形状

规则3:如果两个数组的形状在任何一个维度上都不匹配并且没有任何一个维度等于1,那么会引发异常

运算符 对应的通用函数
== np.equal
!= np.not_equal
< np.less
<= np.less_equal
> np.greater
>= np.greater_equal
1
np.random.rand(10)
array([0.2966421 , 0.75422969, 0.36115914, 0.41785061, 0.13693578,
       0.88023   , 0.49370674, 0.82085892, 0.45881335, 0.40433942])
1
rand=np.random.RandomState(42)
1
rand.randint(100,size=10)
array([51, 92, 14, 71, 60, 20, 82, 86, 74, 74])

numpy中的快速排序:np.sort和np.argsort

1
2
3
# 不修改原数组
x=np.array([2,1,4,5,7])
np.sort(x)
array([1, 2, 4, 5, 7])
1
2
3
# 如果希望用排好序的数组代替原数组,用x.sort()
x.sort()
x
array([1, 2, 4, 5, 7])
1
2
3
4
# np.argsort()返回的是原始数组排好序的索引值
x=np.array([2,1,4,5,7])
i=np.argsort(x)
i
array([1, 0, 2, 3, 4])
1
2
x=np.array([7,2,3,1,6,5,4])
np.partition(x,3)
array([2, 1, 3, 4, 6, 5, 7])

numpy结构化数据

1
2
3
data=np.zeros(3,dtype={'names':('name','age','weight'),
'formats':('U10','i4','f8')})
print(data.dtype)
[('name', '<U10'), ('age', '<i4'), ('weight', '<f8')]
1
2
3
name=['张三','李四','王五']
age=[24,18,19]
weight=[55,85,61]
1
2
3
data['name']=name
data['age']=age
data['weight']=weight
1
data
array([('张三', 24, 55.), ('李四', 18, 85.), ('王五', 19, 61.)],
      dtype=[('name', '<U10'), ('age', '<i4'), ('weight', '<f8')])
1
data['name']
array(['张三', '李四', '王五'], dtype='<U10')
1
data[0]
('张三', 24, 55.)
1
data[-1]['name']
'王五'
1
data[data['age']<20]['name']
array(['李四', '王五'], dtype='<U10')