numpy、pandas、matplotlib总结

numpy & pandas

优点

  • 运算速度快:numpy 和 pandas 都是采用 C 语言编写, pandas 又是基于 numpy, 是 numpy 的升级版本。
  • 消耗资源少:采用的是矩阵运算,会比 python 自带的字典或者列表快好多

numpy

官方参考文档(2021-4-18引用)

https://numpy.org/doc/stable/reference/

numpy 的属性

  • ndim:维度
  • shape:行数和列数
  • size:元素个数

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import numpy as np
array = [[1, 2, 3], [2, 3, 4]]
print(type(array),'\n',array)
#<class 'list'>
#[[1, 2, 3], [2, 3, 4]]
# 列表转化为矩阵
array = np.array(array)
print(type(array),'\n',array)
#<class 'numpy.ndarray'>
# [[1 2 3]
# [2 3 4]]
print('number of dim:',array.ndim) # 维度
# number of dim: 2
print('shape :',array.shape) # 行数和列数
# shape : (2, 3)
print('size:',array.size) # 元素个数
# size: 6

创建array的形式

形式包括:

  • array:创建数组
  • dtype:指定数据类型
  • zeros:创建数据全为0
  • ones:创建数据全为1
  • empty:创建数据接近0
  • arrange:按指定范围创建数据
  • linspace:创建线段

创建数组

1
2
3
a = np.array([2, 23, 4])
print(a)
# [ 2 23 4]

指定数据dtype

1
2
3
4
5
a = np.array([2, 23, 4], dtype=np.int)
print(a.dtype)
# int32
# dtype类型包括{int64:int64,int32:int32,float:float64,float32:float32}
# int我用的pycharm2020 3.3默认32

创建特定数据(全0、全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
# 手动创建特定数据
a = np.array([[2, 23, 4], [2, 32, 4]]) # 2d 矩阵 2行3列
print(a)
'''
[[ 2 23 4]
[ 2 32 4]]
'''


# 创建全零数组
a = np.zeros((3, 4)) # 数据全为0,3行4列

# 创建全一数组, 同时也能指定这些特定数据的 dtype
a = np.ones((3, 4), dtype=np.int) # 数据全为1,3行4列

# 创建全空数组, 其实每个值都是接近于零的数
a = np.empty((3, 4)) # 数据为empty,3行4列

# 用 arange 创建连续数组
a = np.arange(10, 20, 2) # 10-19 的数据,2步长,步长默认为1

# 使用 reshape 改变数据的形状
a = np.arange(12).reshape((3, 4)) # 3行4列,0到11,左闭右开

# 用 linspace 创建线段型数据
a = np.linspace(1, 10, 20) # 开始端1,结束端10,且分割成20个数据,生成线段

# 同样也能进行 reshape 工作
a = np.linspace(1, 10, 20).reshape((5, 4)) # 更改shape

矩阵基本运算

矩阵的加减乘法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import numpy as np
a=np.array([10,20,30,40]) # array([10, 20, 30, 40])
b=np.arange(4) # array([0, 1, 2, 3])
# 两个矩阵之间的加减乘(矩阵对应元素的相加减和相乘)
print(a-b) #[10 19 28 37]
print(a+b) #[10 21 32 43]
print(a*b) #[ 0 20 60 120]

# 各个元素的乘方
print(b**2) #[0 1 4 9]

# 数学函数工具
#sin函数等,用法相同
10*np.sin(a)
# array([-5.44021111, 9.12945251, -9.88031624, 7.4511316 ])

# 逻辑判断
print(b<3) # [ True True True False]

矩阵相乘和矩阵点乘(对应元素乘法)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import numpy as np
a=np.array([[10,20],[30,40]])
b=np.arange(4).reshape(2,2)
print(np.dot(a,b)) #标准矩阵乘法,方式1
print(a.dot(b)) #标准矩阵乘法,方式2
'''
[[ 40 70]
[ 80 150]]
'''
print(a*b) #矩阵点乘(对应元素相乘)
'''
[[ 0 20]
[ 60 120]]
'''

对矩阵中所有元素进行求和,寻找最小值,寻找最大值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import numpy as np
a=np.array([[10,20],[30,40]])
b=np.arange(4).reshape(2,2)
print(np.sum(a)) #100
print(np.min(a)) #10
print(np.max(a)) #40
'''
需要对行或者列进行查找运算,就需要在上述代码中为 axis 进行赋值。
当axis的值为0的时候,将会以列作为查找单元, 当axis的值为1的时候,将会以行作为查找单元。
'''
print("sum =",np.sum(a,axis=1))
# sum = [30 70]
print("min =",np.min(a,axis=0))
# min = [10 20]
print("max =",np.max(a,axis=1))
# max = [20 40]

查找矩阵对应元素的索引

argmin()argmax() 两个函数分别对应着求矩阵中最小元素和最大元素的索引

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

A = np.arange(2, 14).reshape((3, 4))

# array([[ 2, 3, 4, 5]
# [ 6, 7, 8, 9]
# [10,11,12,13]])

print(np.argmin(A)) # 0
print(np.argmax(A)) # 11

求矩阵的平均值和中位数

mean和average都是计算均值的函数,在不指定权重的时候average和mean是一样的。指定权重后,average可以计算一维的加权平均值。

1
2
3
4
5
6
# 平均值
print(np.mean(A)) # 7.5,mean的形式1
print(A.mean()) # 7.5 mean的形式2
print(np.average(A)) # 7.5
# 中位数
print(A.median()) # 7.5

矩阵的累加和累减用法(cumsum和diff)

1
2
3
4
5
6
7
8
9
10
# 生成的每一项矩阵元素均是从原矩阵首项累加到对应项的元素之和。
# 比如元素9,在cumsum()生成的矩阵中序号为3,即原矩阵中2,3,4三个元素的和。
print(np.cumsum(A)) # [2 5 9 14 20 27 35 44 54 65 77 90]
# diff函数计算的便是每一行中后一项与前一项之差。故一个3行4列矩阵通过函数计算得到的矩阵便是3行3列的矩阵。
print(np.diff(A))
'''
# [[1 1 1]
# [1 1 1]
# [1 1 1]]
'''

将非零元素的行和列分开(nonzero)

将所有非零元素的行与列坐标分割开,重构成两个分别关于行和列的矩阵。

1
2
3
# 将非零元素的行列值分开
print(np.nonzero(A))
# (array([0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2], dtype=int64), array([0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3], dtype=int64))

行排序(sort)

1
2
3
4
5
import numpy as np

A = np.arange(14, 2,-1).reshape((3, 4))
# 对每行进行排序
print(np.sort(A))

矩阵的转置

矩阵的转置有两种表示方法

1
2
3
4
5
import numpy as np

A = np.arange(14, 2,-1).reshape((3, 4))
print(np.transpose(A))
print(A.T)

元素在最大最小值外的替换(clip)

Array指的是将要被执行用的矩阵,而后面的最小值最大值则用于让函数判断矩阵中元素是否有比最小值小的或者比最大值大的元素,
并将这些指定的元素转换为最小值或者最大值。比最小的小就是最小值,比最大值大替换为最大值。

1
2
3
4
5
6
print(np.clip(A,5,9))
'''
[[9 9 9 9]
[9 9 8 7]
[6 5 5 5]]
'''

Numpy 索引和迭代输出

矩阵访问对应元素与其余编程语言基本一致。如print(A[1, 1]) ,访问二维数组第二行第二列的元素。

切片输出(逐行和逐列打印):

1
2
3
4
5
6
# 逐行进行打印操作
for row in A:
print(row)
# 逐列打印(将原矩阵转置输出)
for column in A.T:
print(column)

迭代输出

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

A = np.arange(3, 15).reshape((3, 4))

print(A.flatten())
# array([3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14])

for item in A.flat:
print(item)

# 3,4,...14

脚本中的flatten是一个展开性质的函数,将多维的矩阵进行展开成1行的数列。而flat是一个迭代器,本身是一个object属性。

矩阵合并

垂直合并(vstack)

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

A = np.array([1, 1, 1])
B = np.array([2, 2, 2])

print(np.vstack((A, B))) # vertical stack
"""
[[1,1,1]
[2,2,2]]
"""

水平合并(hstack)

1
2
3
4
5
6
7
D = np.hstack((A,B))       # horizontal stack

print(D)
# [1,1,1,2,2,2]

print(A.shape,D.shape)
# (3,) (6,)

增加维度(newaxis)

如果面对如同前文所述的A序列, 转置操作便很有可能无法对其进行转置(因为A并不是矩阵的属性),此时就需要我们借助其他的函数操作进行转置。newaxis可以给原数组增加一个维度。

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

A = np.array([1, 1, 1])
# x[newaxis, :]等同于和:x[newaxis]x[None]
print(A[np.newaxis,:])
# [[1 1 1]]
print(A[:,np.newaxis])
'''
[[1]
[1]
[1]]
'''

矩阵转置问题:

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

A = np.array([1, 1, 1])
# 转置例子
print(np.transpose(A).shape)
# (3,)
print(np.transpose(A[np.newaxis,:]))
print(np.transpose(A[np.newaxis,:]).shape)
'''
[[1]
[1]
[1]]
(3, 1)
'''

合并多个矩阵或序列(concatenate)

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
import numpy as np

A = np.array([1,1,1])[:,np.newaxis]
B = np.array([2,2,2])[:,np.newaxis]
'''
[[1]
[1]
[1]]
[[2]
[2]
[2]]
'''
# 按行合并
C = np.concatenate((A,B,B,A),axis=0)
print(C)
'''
[[1]
[1]
[1]
[2]
[2]
[2]
[2]
[2]
[2]
[1]
[1]
[1]]
'''
# 列合并
D = np.concatenate((A,B,B,A),axis=1)

print(D)
"""
array([[1, 2, 2, 1],
[1, 2, 2, 1],
[1, 2, 2, 1]])
"""

矩阵分割

纵向和横向分割

此方法如果不是均等分割会报错

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import numpy as np
A=np.arange(12).reshape(3,4)
'''
[[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]
'''
# 按列等间隔分割
print(np.split(A,2,axis=1))
'''
[array([[0, 1],
[4, 5],
[8, 9]]), array([[ 2, 3],
[ 6, 7],
[10, 11]])]
'''
# 按行等间隔分割
print(np.split(A, 3, axis=0))
# [array([[0, 1, 2, 3]]), array([[4, 5, 6, 7]]), array([[ 8, 9, 10, 11]])]

不等量的分割

不等量分割计算:假如按列分四组,列元素有6个,每组可分6/4=1个元素。多了的元素处理:6%4为2,前2行分+1个元素。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import numpy as np
A=np.arange(12).reshape(2,6)
print(A)
'''
[[ 0 1 2 3 4 5]
[ 6 7 8 9 10 11]]
'''
print(np.array_split(A, 4, axis=1))
"""
[array([[0, 1],
[6, 7]]), array([[2, 3],
[8, 9]]), array([[ 4],
[10]]), array([[ 5],
[11]])]
"""

在Numpy里还有np.vsplit()与横np.hsplit()方式可用

1
2
print(np.vsplit(A, 3)) #等于 print(np.split(A, 3, axis=0))
print(np.hsplit(A, 2)) #等于 print(np.split(A, 2, axis=1))

Numpy的浅拷贝和深拷贝(copy)

等号赋值会有关联性,相当于起引用起别名,原数据改变会引起关联变量值改变。而copy() 的赋值方式没有关联性。

1
2
b = a.copy()    # deep copy
# 此时a与b已经没有关联。

Pandas

官方文档(2021-4-20)

https://pandas.pydata.org/pandas-docs/stable/reference/frame.html

Numpy 是列表形式的,没有数值标签,而 Pandas 就是字典形式。Pandas是基于Numpy构建的,让Numpy为中心的应用变得更加简单。

Series

Series的字符串表现形式为:索引在左边,值在右边。由于我们没有为数据指定索引。于是会自动创建一个0到N-1(N为长度)的整数型索引。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import pandas as pd
import numpy as np
# 如果定义的index在原字典中已经存在,那么该索引会一直对应原字典的值,如果index对应不到原字典的值,则会返回NaN

a=pd.Series({'a':1,'b':3},index = ['b','a','c'])
print(a)
'''
b 3.0
a 1.0
c NaN
dtype: float64
'''
# 索引不指定会自动创建
a=pd.Series([1,3,6,np.nan,44,1])
print(a)
'''
0 1.0
1 3.0
2 6.0
3 NaN
4 44.0
5 1.0
dtype: float64
'''

DataFrame

DataFrame是一个表格型的数据结构,它包含有一组有序的列,每列可以是不同的值类型(数值,字符串,布尔值等)。DataFrame既有行索引也有列索引, 它可以被看做由Series组成的大字典。没有给定行标签和列标签的数据,会采取默认的从0开始 index。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import pandas as pd
import numpy as np
dates = pd.date_range('20160101',periods=6)
df = pd.DataFrame(np.random.randn(6,4),index=dates,columns=['a','b','c','d'])
print(df)
"""
a b c d
2016-01-01 -0.253065 -2.071051 -0.640515 0.613663
2016-01-02 -1.147178 1.532470 0.989255 -0.499761
2016-01-03 1.221656 -2.390171 1.862914 0.778070
2016-01-04 1.473877 -0.046419 0.610046 0.204672
2016-01-05 -1.584752 -0.700592 1.487264 -1.778293
2016-01-06 0.633675 -1.414157 -0.277066 -0.442545
"""

常用属性查看

  • dtype查看数据类型
  • index查看列的序号
  • columns查看数据行的名称
  • values查看值
  • describe查看总的描述

数据排序

1
2
3
4
# 按index排序
print(df.sort_index(axis=1,ascending=False))
# 按values排序
print(df2.sort_values(by='列名'))

数据选择

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 pandas as pd
import numpy as np
dates = pd.date_range('20160101',periods=6)
df = pd.DataFrame(np.random.randn(6,4),index=dates,columns=['a','b','c','d'])
'''
a b c d
2016-01-01 -0.482295 -0.474567 0.066334 -0.111646
2016-01-02 -1.359595 1.895219 -0.035587 -0.049728
2016-01-03 0.746566 0.439931 0.118921 -0.183519
2016-01-04 -1.468278 1.530795 -0.864718 -0.489982
2016-01-05 0.461041 0.985116 1.614093 -0.635298
2016-01-06 0.097487 -0.082434 -0.917420 0.793434
'''
print(df['a'])#其余筛选与python数组截取类似
'''
2016-01-01 -0.482295
2016-01-02 -1.359595
2016-01-03 0.746566
2016-01-04 -1.468278
2016-01-05 0.461041
2016-01-06 0.097487
Freq: D, Name: a, dtype: float64
'''
# 跨列和跨行
print(df[0:3])
print(df['2016-01-01 ':'2016-01-06'])
根据标签 loc

我们可以使用标签来选择数据 loc, 本例子主要通过标签名字选择某一行数据, 或者通过选择某行或者所有行(:代表所有行)然后选其中某一列或几列数据。

1
2
3
4
# 其中几行
print(df.loc['2016-01-04':'2016-01-06'])
# 其中几列
print(df.loc[:,['a','b']])
根据序列 iloc

另外我们可以采用位置进行选择 iloc, 在这里我们可以通过位置选择在不同情况下所需要的数据例如选某一个,连续选或者跨行选等操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
print(df.iloc[3:5,1:3])
"""
b c
2016-01-04 -0.409077 -0.485776
2016-01-05 -0.231562 1.317709
"""

print(df.iloc[[1,3,5],1:3])
"""
b c
2016-01-02 1.573411 -0.335548
2016-01-04 -0.409077 -0.485776
2016-01-06 0.359269 -0.271838

"""

当然我们可以采用混合选择 ix, 其中选择’A’和’C’的两列,并选择前三行的数据。已经不建议使用

通过判断的筛选

我们可以采用判断指令 (Boolean indexing) 进行选择. 我们可以约束某项条件然后选择出当前所有数据.

1
print(df.a>0)

值的设置

根据位置设置 loc 和 iloc

可以利用索引或者标签确定需要修改值的位置

1
2
df.iloc[2,2] = 1111
df.loc['2016-01-05','a'] = 2222
根据条件设置
1
df.b[df.a>0] = 0
按行或列设置
1
2
# 整列操作
df['a'] = np.nan
添加数据
1
df['e'] = pd.Series([1,2,3,4,5,6], index=pd.date_range('2016-01-01',periods=6))

处理丢失数据

去掉有 NaN 的行或列(dropna)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import pandas as pd
import numpy as np
dates = pd.date_range('20130101', periods=6)
df = pd.DataFrame(np.arange(24).reshape((6,4)),index=dates, columns=['A','B','C','D'])
df.iloc[0,1] = np.nan
df.iloc[1,2] = np.nan
"""
A B C D
2013-01-01 0 NaN 2.0 3
2013-01-02 4 5.0 NaN 7
2013-01-03 8 9.0 10.0 11
2013-01-04 12 13.0 14.0 15
2013-01-05 16 17.0 18.0 19
2013-01-06 20 21.0 22.0 23
"""
df.dropna(
axis=0, # 0: 对行进行操作; 1: 对列进行操作
how='any' # 'any': 只要存在 NaN 就 drop 掉; 'all': 必须全部是 NaN 才 drop
)
用其他值代替(fillna)
1
df.fillna(value=0)
判断有无缺失(isnull)

判断是否有缺失数据 NaN, 为 True 表示缺失数据。

检测在数据中是否存在 NaN, 如果存在就返回 True

1
2
print(df.isnull())
print(np.any(df.isnull()) == True)

导入导出

pandas可以读取与存取的资料格式有很多种,像csvexceljsonhtmlpickle

1
2
3
4
# 读取csv
data = pd.read_csv('student.csv')
# 将资料存取成pickle
data.to_pickle('student.pickle')

合并( concat)

合并方向(axis)

axis=0是预设值,因此未设定任何参数时,函数默认axis=0

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import pandas as pd
import numpy as np

#定义资料集
df1 = pd.DataFrame(np.ones((3,4))*0, columns=['a','b','c','d'])
df2 = pd.DataFrame(np.ones((3,4))*1, columns=['a','b','c','d'])
df3 = pd.DataFrame(np.ones((3,4))*2, columns=['a','b','c','d'])

#concat纵向合并
res = pd.concat([df1, df2, df3], axis=0)

#打印结果
print(res)
# a b c d
# 0 0.0 0.0 0.0 0.0
# 1 0.0 0.0 0.0 0.0
# 2 0.0 0.0 0.0 0.0
# 0 1.0 1.0 1.0 1.0
# 1 1.0 1.0 1.0 1.0
# 2 1.0 1.0 1.0 1.0
# 0 2.0 2.0 2.0 2.0
# 1 2.0 2.0 2.0 2.0
# 2 2.0 2.0 2.0 2.0
重置 index(ignore_index)
1
res = pd.concat([df1, df2, df3], axis=0, ignore_index=True)

结果的index变0, 1, 2, 3, 4, 5, 6, 7, 8。

join 合并方式

join='outer'为预设值,因此未设定任何参数时,函数默认join='outer'。此方式是依照column来做纵向合并,有相同的column上下合并在一起,其他独自的column个自成列,原本没有值的位置皆以NaN填充。

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

#定义资料集
df1 = pd.DataFrame(np.ones((3,4))*0, columns=['a','b','c','d'], index=[1,2,3])
df2 = pd.DataFrame(np.ones((3,4))*1, columns=['b','c','d','e'], index=[2,3,4])

#纵向"外"合并df1与df2
res = pd.concat([df1, df2], axis=0, join='outer')

print(res)
# a b c d e
# 1 0.0 0.0 0.0 0.0 NaN
# 2 0.0 0.0 0.0 0.0 NaN
# 3 0.0 0.0 0.0 0.0 NaN
# 2 NaN 1.0 1.0 1.0 1.0
# 3 NaN 1.0 1.0 1.0 1.0
# 4 NaN 1.0 1.0 1.0 1.0

inner内合并

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#纵向"内"合并df1与df2
res = pd.concat([df1, df2], axis=0, join='inner')

#打印结果
print(res)
# b c d
# 1 0.0 0.0 0.0
# 2 0.0 0.0 0.0
# 3 0.0 0.0 0.0
# 2 1.0 1.0 1.0
# 3 1.0 1.0 1.0
# 4 1.0 1.0 1.0

#重置index并打印结果
res = pd.concat([df1, df2], axis=0, join='inner', ignore_index=True)
print(res)
# b c d
# 0 0.0 0.0 0.0
# 1 0.0 0.0 0.0
# 2 0.0 0.0 0.0
# 3 1.0 1.0 1.0
# 4 1.0 1.0 1.0
# 5 1.0 1.0 1.0
join_axes (已失效)
添加数据(append )

append只有纵向合并,没有横向合并。

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
import pandas as pd
import numpy as np

#定义资料集
df1 = pd.DataFrame(np.ones((3,4))*0, columns=['a','b','c','d'])
df2 = pd.DataFrame(np.ones((3,4))*1, columns=['a','b','c','d'])
df3 = pd.DataFrame(np.ones((3,4))*1, columns=['a','b','c','d'])
s1 = pd.Series([1,2,3,4], index=['a','b','c','d'])

#将df2合并到df1的下面,以及重置index,并打印出结果
res = df1.append(df2, ignore_index=True)
print(res)
# a b c d
# 0 0.0 0.0 0.0 0.0
# 1 0.0 0.0 0.0 0.0
# 2 0.0 0.0 0.0 0.0
# 3 1.0 1.0 1.0 1.0
# 4 1.0 1.0 1.0 1.0
# 5 1.0 1.0 1.0 1.0

#合并多个df,将df2与df3合并至df1的下面,以及重置index,并打印出结果
res = df1.append([df2, df3], ignore_index=True)
print(res)
# a b c d
# 0 0.0 0.0 0.0 0.0
# 1 0.0 0.0 0.0 0.0
# 2 0.0 0.0 0.0 0.0
# 3 1.0 1.0 1.0 1.0
# 4 1.0 1.0 1.0 1.0
# 5 1.0 1.0 1.0 1.0
# 6 1.0 1.0 1.0 1.0
# 7 1.0 1.0 1.0 1.0
# 8 1.0 1.0 1.0 1.0

#合并series,将s1合并至df1,以及重置index,并打印出结果
res = df1.append(s1, ignore_index=True)
print(res)
# a b c d
# 0 0.0 0.0 0.0 0.0
# 1 0.0 0.0 0.0 0.0
# 2 0.0 0.0 0.0 0.0
# 3 1.0 2.0 3.0 4.0

合并(merge)

pandas中的mergeconcat类似,但主要是用于两组有key column的数据,统一索引的数据. 通常也被用在Database的处理当中.

依据一组key合并
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
import pandas as pd

#定义资料集并打印出
left = pd.DataFrame({'key': ['K0', 'K1', 'K2', 'K3'],
'A': ['A0', 'A1', 'A2', 'A3'],
'B': ['B0', 'B1', 'B2', 'B3']})
right = pd.DataFrame({'key': ['K0', 'K1', 'K2', 'K3'],
'C': ['C0', 'C1', 'C2', 'C3'],
'D': ['D0', 'D1', 'D2', 'D3']})

print(left)
# A B key
# 0 A0 B0 K0
# 1 A1 B1 K1
# 2 A2 B2 K2
# 3 A3 B3 K3

print(right)
# C D key
# 0 C0 D0 K0
# 1 C1 D1 K1
# 2 C2 D2 K2
# 3 C3 D3 K3

#依据key column合并,并打印出
res = pd.merge(left, right, on='key')

print(res)
# A B key C D
# 0 A0 B0 K0 C0 D0
# 1 A1 B1 K1 C1 D1
# 2 A2 B2 K2 C2 D2
# 3 A3 B3 K3 C3 D3
依据两组key合并

合并时有4种方法how = ['left', 'right', 'outer', 'inner'],预设值how='inner'

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
55
56
57
58
59
60
import pandas as pd

#定义资料集并打印出
left = pd.DataFrame({'key1': ['K0', 'K0', 'K1', 'K2'],
'key2': ['K0', 'K1', 'K0', 'K1'],
'A': ['A0', 'A1', 'A2', 'A3'],
'B': ['B0', 'B1', 'B2', 'B3']})
right = pd.DataFrame({'key1': ['K0', 'K1', 'K1', 'K2'],
'key2': ['K0', 'K0', 'K0', 'K0'],
'C': ['C0', 'C1', 'C2', 'C3'],
'D': ['D0', 'D1', 'D2', 'D3']})

print(left)
# A B key1 key2
# 0 A0 B0 K0 K0
# 1 A1 B1 K0 K1
# 2 A2 B2 K1 K0
# 3 A3 B3 K2 K1

print(right)
# C D key1 key2
# 0 C0 D0 K0 K0
# 1 C1 D1 K1 K0
# 2 C2 D2 K1 K0
# 3 C3 D3 K2 K0

#依据key1与key2 columns进行合并,并打印出四种结果['left', 'right', 'outer', 'inner']
res = pd.merge(left, right, on=['key1', 'key2'], how='inner')
print(res)
# A B key1 key2 C D
# 0 A0 B0 K0 K0 C0 D0
# 1 A2 B2 K1 K0 C1 D1
# 2 A2 B2 K1 K0 C2 D2

res = pd.merge(left, right, on=['key1', 'key2'], how='outer')
print(res)
# A B key1 key2 C D
# 0 A0 B0 K0 K0 C0 D0
# 1 A1 B1 K0 K1 NaN NaN
# 2 A2 B2 K1 K0 C1 D1
# 3 A2 B2 K1 K0 C2 D2
# 4 A3 B3 K2 K1 NaN NaN
# 5 NaN NaN K2 K0 C3 D3

res = pd.merge(left, right, on=['key1', 'key2'], how='left')
print(res)
# A B key1 key2 C D
# 0 A0 B0 K0 K0 C0 D0
# 1 A1 B1 K0 K1 NaN NaN
# 2 A2 B2 K1 K0 C1 D1
# 3 A2 B2 K1 K0 C2 D2
# 4 A3 B3 K2 K1 NaN NaN

res = pd.merge(left, right, on=['key1', 'key2'], how='right')
print(res)
# A B key1 key2 C D
# 0 A0 B0 K0 K0 C0 D0
# 1 A2 B2 K1 K0 C1 D1
# 2 A2 B2 K1 K0 C2 D2
# 3 NaN NaN K2 K0 C3 D3
Indicator

indicator=True会将合并的记录放在新的一列。

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
import pandas as pd

#定义资料集并打印出
df1 = pd.DataFrame({'col1':[0,1], 'col_left':['a','b']})
df2 = pd.DataFrame({'col1':[1,2,2],'col_right':[2,2,2]})

print(df1)
# col1 col_left
# 0 0 a
# 1 1 b

print(df2)
# col1 col_right
# 0 1 2
# 1 2 2
# 2 2 2

# 依据col1进行合并,并启用indicator=True,最后打印出
res = pd.merge(df1, df2, on='col1', how='outer', indicator=True)
print(res)
# col1 col_left col_right _merge
# 0 0.0 a NaN left_only
# 1 1.0 b 2.0 both
# 2 2.0 NaN 2.0 right_only
# 3 2.0 NaN 2.0 right_only

# 自定indicator column的名称,并打印出
res = pd.merge(df1, df2, on='col1', how='outer', indicator='indicator_column')
print(res)
# col1 col_left col_right indicator_column
# 0 0.0 a NaN left_only
# 1 1.0 b 2.0 both
# 2 2.0 NaN 2.0 right_only
# 3 2.0 NaN 2.0 right_only
依据index合并
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
import pandas as pd

#定义资料集并打印出
left = pd.DataFrame({'A': ['A0', 'A1', 'A2'],
'B': ['B0', 'B1', 'B2']},
index=['K0', 'K1', 'K2'])
right = pd.DataFrame({'C': ['C0', 'C2', 'C3'],
'D': ['D0', 'D2', 'D3']},
index=['K0', 'K2', 'K3'])

print(left)
# A B
# K0 A0 B0
# K1 A1 B1
# K2 A2 B2

print(right)
# C D
# K0 C0 D0
# K2 C2 D2
# K3 C3 D3

#依据左右资料集的index进行合并,how='outer',并打印出
res = pd.merge(left, right, left_index=True, right_index=True, how='outer')
print(res)
# A B C D
# K0 A0 B0 C0 D0
# K1 A1 B1 NaN NaN
# K2 A2 B2 C2 D2
# K3 NaN NaN C3 D3

#依据左右资料集的index进行合并,how='inner',并打印出
res = pd.merge(left, right, left_index=True, right_index=True, how='inner')
print(res)
# A B C D
# K0 A0 B0 C0 D0
# K2 A2 B2 C2 D2
解决overlapping的问题
1
2
3
4
5
6
7
8
9
10
11
12
import pandas as pd

#定义资料集
boys = pd.DataFrame({'k': ['K0', 'K1', 'K2'], 'age': [1, 2, 3]})
girls = pd.DataFrame({'k': ['K0', 'K0', 'K3'], 'age': [4, 5, 6]})

#使用suffixes解决overlapping的问题
res = pd.merge(boys, girls, on='k', suffixes=['_boy', '_girl'], how='inner')
print(res)
# age_boy k age_girl
# 0 1 K0 4
# 1 1 K0 5

plot 出图

我们随机生成1000个数据,Series 默认的 index 就是从0开始的整数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# 随机生成1000个数据
data = pd.Series(np.random.randn(1000), index=np.arange(1000))

# 为了方便观看效果, 我们累加这个数据
data.cumsum()

# pandas 数据可以直接观看其可视化形式
data.plot()

plt.show()

Dataframe 可视化

生成一个1000*4 的DataFrame,并对他们累加。

1
2
3
4
5
6
7
8
data = pd.DataFrame(
np.random.randn(1000,4),
index=np.arange(1000),
columns=list("ABCD")
)
data.cumsum()
data.plot()
plt.show()

分别给x, y指定数据,然后我们可以再画一个在同一个ax上面,选择不一样的数据列,不同的 colorlabel

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

data = pd.DataFrame(
np.random.randn(1000,4),
index=np.arange(1000),
columns=list("ABCD")
)
data.cumsum()
data.plot()
plt.show()
ax = data.plot.scatter(x='A',y='B',color='DarkBlue',label='Class1')
# 将之下这个 data 画在上一个 ax 上面
data.plot.scatter(x='A',y='C',color='LightGreen',label='Class2',ax=ax)
plt.show()

Matplotlib

官网地址(2021-4-20)

https://matplotlib.org/

Matplotlib可以画出美丽的:

  • 线图;
  • 散点图;
  • 等高线图;
  • 条形图;
  • 柱状图;
  • 3D 图形,
  • 甚至是图形动画等等.

基本用法

基础应用

使用import导入模块matplotlib.pyplot,并简写成plt, 使用import导入模块numpy,并简写成np

使用np.linspace定义x:范围是(-1,1);个数是50. 仿真一维数据组(x ,y)表示直线。

使用plt.figure定义一个图像窗口. 使用plt.plot画(x ,y)曲线. 使用plt.show显示图像。

1
2
3
4
5
6
7
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(-1, 1, 50)
y = 2*x + 1
plt.figure()
plt.plot(x, y)
plt.show()

matplotlib 的 figure 就是一个 单独的 figure 小窗口, 小窗口里面还可以有更多的小图片.

使用plt.figure定义一个图像窗口:编号为3;大小为(8, 5). 使用plt.plot画(x ,y2)曲线. 使用plt.plot画(x ,y1)曲线,曲线的颜色属性(color)为红色;曲线的宽度(linewidth)为1.0;曲线的类型(linestyle)为虚线. 使用plt.show显示图像.

1
2
3
4
5
6
7
8
9
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(-3, 3, 50)
y1 = 2*x + 1
y2 = x**2
plt.figure(num=3, figsize=(8, 5),)
plt.plot(x, y2)
plt.plot(x, y1, color='red', linewidth=1.0, linestyle='--')
plt.show()

设置坐标轴

调整坐标轴名字和间隔

使用plt.xlim设置x坐标轴范围:(-1, 2); 使用plt.ylim设置y坐标轴范围:(-2, 3); 使用plt.xlabel设置x坐标轴名称:’I am x’; 使用plt.ylabel设置y坐标轴名称:’I am y’;

1
2
3
4
5
6
7
8
9
10
11
12
13
import matplotlib.pyplot as plt
import numpy as np
x=np.linspace(-3,3,50)
y1=2*x+1
y2=x**2
plt.figure()
plt.plot(x, y2)
plt.plot(x, y1, color='red', linewidth=1.0, linestyle='--')
plt.xlim((-1, 2))
plt.ylim((-2, 3))
plt.xlabel('I am x')
plt.ylabel('I am y')
plt.show()

使用np.linspace定义范围以及个数:范围是(-1,2);个数是5. 使用print打印出新定义的范围. 使用plt.xticks设置x轴刻度:范围是(-1,2);个数是5.

使用plt.yticks设置y轴刻度以及名称:刻度为[-2, -1.8, -1, 1.22, 3];对应刻度的名称为[‘really bad’,’bad’,’normal’,’good’, ‘really good’]. 使用plt.show显示图像.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import matplotlib.pyplot as plt
import numpy as np
x=np.linspace(-3,3,50)
y1=2*x+1
y2=x**2
plt.figure()
plt.plot(x, y2)
plt.plot(x, y1, color='red', linewidth=1.0, linestyle='--')
plt.xlim((-1, 2))
plt.ylim((-2, 3))
plt.xlabel('I am x')
plt.ylabel('I am y')
new_ticks = np.linspace(-1, 2, 5)
print(new_ticks)
plt.xticks(new_ticks)
plt.yticks([-2, -1.8, -1, 1.22, 3],[r'$really\ bad$', r'$bad$', r'$normal$', r'$good$', r'$really\ good$'])
plt.show()

使用plt.gca获取当前坐标轴信息. 使用.spines设置边框:右侧边框;使用.set_color设置边框颜色:默认白色; 使用.spines设置边框:上边框;使用.set_color设置边框颜色:默认白色;

1
2
3
ax = plt.gca()
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')

调整坐标轴

使用.xaxis.set_ticks_position设置x坐标刻度数字或名称的位置:bottom.(所有位置:topbottombothdefaultnone

1
ax.xaxis.set_ticks_position('bottom')

使用.spines设置边框:x轴;使用.set_position设置边框位置:y=0的位置;(位置所有属性:outwardaxesdata

1
ax.spines['bottom'].set_position(('data', 0))

使用.yaxis.set_ticks_position设置y坐标刻度数字或名称的位置:left.(所有位置:leftrightbothdefaultnone

1
ax.yaxis.set_ticks_position('left')

使用.spines设置边框:y轴;使用.set_position设置边框位置:x=0的位置;(位置所有属性:outwardaxesdata) 使用plt.show显示图像.

1
ax.spines['left'].set_position(('data',0))

Legend 设置图例

添加图例

legend将要显示的信息来自于上面代码中的 label. 所以我们只需要简单写下一下代码, plt 就能自动的为我们添加图例.参数 loc='upper right' 表示图例将添加在图中的右上角.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(-3, 3, 50)
y1 = 2*x + 1
y2 = x**2

plt.figure()
#set x limits
plt.xlim((-1, 2))
plt.ylim((-2, 3))

# set new sticks
new_sticks = np.linspace(-1, 2, 5)
plt.xticks(new_sticks)
# set tick labels
plt.yticks([-2, -1.8, -1, 1.22, 3],
[r'$really\ bad$', r'$bad$', r'$normal$', r'$good$', r'$really\ good$'])
# set line syles
l1, = plt.plot(x, y1, label='linear line')
l2, = plt.plot(x, y2, color='red', linewidth=1.0, linestyle='--', label='square line')
# add legend
plt.legend(loc='upper right')
plt.show()
调整位置和名称

如果我们想单独修改之前的 label 信息, 给不同类型的线条设置图例信息. 我们可以在 plt.legend 输入更多参数. 如果以下面这种形式添加 legend, 我们需要确保, 在上面的代码 plt.plot(x, y2, label='linear line')plt.plot(x, y1, label='square line') 中有用变量 l1l2 分别存储起来. 而且需要注意的是 l1, l2,要以逗号结尾, 因为plt.plot() 返回的是一个列表.

1
plt.legend(handles=[l1, l2], labels=['up', 'down'],  loc='best')

这样我们就能分别重新设置线条对应的 label 了.

其中’loc’参数有多种,’best’表示自动分配最佳位置,其余的如下:

1
2
3
4
5
6
7
8
9
10
11
'best' : 0,          
'upper right' : 1,
'upper left' : 2,
'lower left' : 3,
'lower right' : 4,
'right' : 5,
'center left' : 6,
'center right' : 7,
'lower center' : 8,
'upper center' : 9,
'center' : 10,

Annotation 标注

画出基本图

当图线中某些特殊地方需要标注时,我们可以使用 annotation. matplotlib 中的 annotation 有两种方法, 一种是用 plt 里面的 annotate,一种是直接用 plt 里面的 text 来写标注.

首先,我们在坐标轴中绘制一条直线.

1
2
3
4
5
6
7
8
9
import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(-3, 3, 50)
y = 2*x + 1

plt.figure(num=1, figsize=(8, 5),)
plt.plot(x, y,)
plt.show()
移动坐标

挪动坐标轴的位置.

1
2
3
4
5
6
7
8
ax = plt.gca()
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.spines['top'].set_color('none')
ax.xaxis.set_ticks_position('bottom')
ax.spines['bottom'].set_position(('data', 0))
ax.yaxis.set_ticks_position('left')
ax.spines['left'].set_position(('data', 0))

然后标注出点(x0, y0)的位置信息. 用plt.plot([x0, x0,], [0, y0,], 'k--', linewidth=2.5) 画出一条垂直于x轴的虚线.

1
2
3
4
5
x0 = 1
y0 = 2*x0 + 1
plt.plot([x0, x0,], [0, y0,], 'k--', linewidth=2.5)
# set dot styles
plt.scatter([x0, ], [y0, ], s=50, color='b')
添加注释 annotate

(x0, y0)这个点进行标注.

1
2
3
plt.annotate(r'$2x+1=%s$' % y0, xy=(x0, y0), xycoords='data', xytext=(+30, -30),
textcoords='offset points', fontsize=16,
arrowprops=dict(arrowstyle='->', connectionstyle="arc3,rad=.2"))

其中参数xycoords='data' 是说基于数据的值来选位置, xytext=(+30, -30)textcoords='offset points' 对于标注位置的描述 和 xy 偏差值, arrowprops是对图中箭头类型的一些设置.

添加注释 text
1
2
plt.text(-3.7, 3, r'$This\ is\ the\ some\ text. \mu\ \sigma_i\ \alpha_t$',
fontdict={'size': 16, 'color': 'r'})

其中-3.7, 3,是选取text的位置, 空格需要用到转字符\,fontdict设置文本字体.

tick 能见度

当图片中的内容较多,相互遮盖时,我们可以通过设置相关内容的透明度来使图片更易于观察,也即是通过bbox参数设置来调节图像信息.

生成图形
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(-3, 3, 50)
y = 0.1*x

plt.figure()
# 在 plt 2.0.2 或更高的版本中, 设置 zorder 给 plot 在 z 轴方向排序
plt.plot(x, y, linewidth=10, zorder=1)
plt.ylim(-2, 2)
ax = plt.gca()
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.spines['top'].set_color('none')
ax.xaxis.set_ticks_position('bottom')
ax.spines['bottom'].set_position(('data', 0))
ax.yaxis.set_ticks_position('left')
ax.spines['left'].set_position(('data', 0))
plt.show()
调整坐标

对被遮挡的图像调节相关透明度,本例中设置 x轴 和 y轴 的刻度数字进行透明度设置。

1
2
3
4
for label in ax.get_xticklabels() + ax.get_yticklabels():
label.set_fontsize(12)
# 在 plt 2.0.2 或更高的版本中, 设置 zorder 给 plot 在 z 轴方向排序
label.set_bbox(dict(facecolor='white', edgecolor='None', alpha=0.7, zorder=2))

其中label.set_fontsize(12)重新调节字体大小,bbox设置目的内容的透明度相关参,facecolor调节 box 前景色,edgecolor 设置边框, 本处设置边框为无,alpha设置透明度.

画图种类

Scatter 散点图

生成1024个呈标准正态分布的二维数据组 (平均数是0,方差为1) 作为一个数据集,并图像化这个数据集。每一个点的颜色值用T来表示:

1
2
3
4
5
6
7
import matplotlib.pyplot as plt
import numpy as np

n = 1024 # data size
X = np.random.normal(0, 1, n) # 每一个点的X值
Y = np.random.normal(0, 1, n) # 每一个点的Y值
T = np.arctan2(Y,X) # for color value

数据集生成完毕,现在来用scatterplot这个点集。输入XY作为location,size=75,颜色为Tcolor map用默认值,透明度alpha 为 50%。 x轴显示范围定位(-1.5,1.5),并用xtick()函数来隐藏x坐标轴,y轴同理:

1
2
3
4
5
6
7
8
9
10
11
12
13
import matplotlib.pyplot as plt
import numpy as np
n = 1024 # data size
X = np.random.normal(0, 1, n) # 每一个点的X值
Y = np.random.normal(0, 1, n) # 每一个点的Y值
T = np.arctan2(Y,X) # for color value
plt.scatter(X, Y, s=75, c=T, alpha=.5)

plt.xlim(-1.5, 1.5)
plt.xticks(()) # ignore xticks
plt.ylim(-1.5, 1.5)
plt.yticks(()) # ignore yticks
plt.show()

Bar 柱状图

生成基本图形

向上向下分别生成12个数据,X为 0 到 11 的整数 ,Y是相应的均匀分布的随机数据。 使用的函数是plt.bar,参数为X和Y:

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

n = 12
X = np.arange(n)
Y1 = (1 - X / float(n)) * np.random.uniform(0.5, 1.0, n)
Y2 = (1 - X / float(n)) * np.random.uniform(0.5, 1.0, n)

plt.bar(X, +Y1)
plt.bar(X, -Y2)

plt.xlim(-.5, n)
plt.xticks(())
plt.ylim(-1.25, 1.25)
plt.yticks(())

plt.show()

加颜色和数据

facecolor设置主体颜色,edgecolor设置边框颜色为白色:

1
2
plt.bar(X, +Y1, facecolor='#9999ff', edgecolor='white')
plt.bar(X, -Y2, facecolor='#ff9999', edgecolor='white')

接下来我们用函数plt.text分别在柱体上方(下方)加上数值,用%.2f保留两位小数,横向居中对齐ha='center',纵向底部(顶部)对齐va='bottom'

1
2
3
4
5
6
7
8
9
for x, y in zip(X, Y1):
# ha: horizontal alignment
# va: vertical alignment
plt.text(x + 0.4, y + 0.05, '%.2f' % y, ha='center', va='bottom')

for x, y in zip(X, Y2):
# ha: horizontal alignment
# va: vertical alignment
plt.text(x + 0.4, -y - 0.05, '%.2f' % y, ha='center', va='top')

Contours 等高线图

画等高线

数据集即三维点 (x,y) 和对应的高度值,共有256个点。高度值使用一个 height function f(x,y) 生成。 x, y 分别是在区间 [-3,3] 中均匀分布的256个值,并用meshgrid在二维平面中将每一个x和每一个y分别对应起来,编织成栅格:

1
2
3
4
5
6
7
8
9
10
11
import matplotlib.pyplot as plt
import numpy as np

def f(x,y):
# the height function
return (1 - x / 2 + x**5 + y**3) * np.exp(-x**2 -y**2)

n = 256
x = np.linspace(-3, 3, n)
y = np.linspace(-3, 3, n)
X,Y = np.meshgrid(x, y)

接下来进行颜色填充。使用函数plt.contourf把颜色加进去,位置参数分别为:X, Y, f(X,Y)。透明度0.75,并将 f(X,Y) 的值对应到color map的暖色组中寻找对应颜色。

1
2
3
# use plt.contourf to filling contours
# X, Y and value for (X,Y) point
plt.contourf(X, Y, f(X, Y), 8, alpha=.75, cmap=plt.cm.hot)

接下来进行等高线绘制。使用plt.contour函数划线。位置参数为:X, Y, f(X,Y)。颜色选黑色,线条宽度选0.5。现在的结果如下图所示,只有颜色和线条,还没有数值Label:

1
2
# use plt.contour to add contour lines
C = plt.contour(X, Y, f(X, Y), 8, colors='black',linewidths=[0.5])

添加高度数字

其中,8代表等高线的密集程度,这里被分为10个部分。如果是0,则图像被一分为二。

最后加入Label,inline控制是否将Label画在线里面,字体大小为10。并将坐标轴隐藏:

1
2
3
plt.clabel(C, inline=True, fontsize=10)
plt.xticks(())
plt.yticks(())

Image 图片

随机矩阵画图

用这样 3x3 的 2D-array 来表示点的颜色,每一个点就是一个pixel(像素)。三行三列的格子,a代表每一个值,图像右边有一个注释,白色代表值最大的地方,颜色越深值越小。

1
2
3
4
5
6
import matplotlib.pyplot as plt
import numpy as np

a = np.array([0.313660827978, 0.365348418405, 0.423733120134,
0.365348418405, 0.439599930621, 0.525083754405,
0.423733120134, 0.525083754405, 0.651536351379]).reshape(3,3)

我们之前选cmap的参数时用的是:cmap=plt.cmap.bone,而现在,我们可以直接用单引号传入参数。 origin='lower'代表的就是选择的原点的位置。

出图方式

使用的是内插法中的 Nearest-neighbor 的方法,其他的方式也都可以随意取选。

colorbar

添加一个colorbar ,其中我们添加一个shrink参数,使colorbar的长度变短为原来的92%:

1
2
3
4
plt.colorbar(shrink=.92)

plt.xticks(())
plt.yticks(())

3D 图

首先在进行 3D Plot 时除了导入 matplotlib ,还要额外添加一个模块,即 Axes 3D 3D 坐标轴显示:

1
2
3
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

之后要先定义一个图像窗口,在窗口上添加3D坐标轴:

1
2
fig = plt.figure()
ax = Axes3D(fig)

接下来给进 X 和 Y 值,并将 X 和 Y 编织成栅格。每一个(X, Y)点对应的高度值我们用下面这个函数来计算。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure()
ax = Axes3D(fig)

# X, Y value
X = np.arange(-4, 4, 0.25)
Y = np.arange(-4, 4, 0.25)
X, Y = np.meshgrid(X, Y) # x-y 平面的网格
R = np.sqrt(X ** 2 + Y ** 2)
# height value
Z = np.sin(R)

plt.show()

做出一个三维曲面,并将一个 colormap rainbow 填充颜色,之后将三维图像投影到 XY 平面上做一个等高线图。 plot 3D 图像:

1
ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=plt.get_cmap('rainbow'))

其中,rstridecstride 分别代表 row 和 column 的跨度。

投影

下面添加 XY 平面的等高线:

1
ax.contourf(X, Y, Z, zdir='z', offset=-2, cmap=plt.get_cmap('rainbow'))

如果 zdir 选择了x,那么效果将会是对于 XZ 平面的投影。

Subplot 多合一显示

均匀图中图

matplotlib 是可以组合许多的小图, 放在一张大图里面显示的. 使用到的方法叫作 subplot.

使用plt.figure创建一个图像窗口.

1
2
3
import matplotlib.pyplot as plt

plt.figure()

使用plt.subplot来创建小图. plt.subplot(2,2,1)表示将整个图像窗口分为2行2列, 当前位置为1. 使用plt.plot([0,1],[0,1])在第1个位置创建一个小图.

1
2
plt.subplot(2,2,1)
plt.plot([0,1],[0,1])

plt.subplot(2,2,2)表示将整个图像窗口分为2行2列, 当前位置为2. 使用plt.plot([0,1],[0,2])在第2个位置创建一个小图.

1
2
plt.subplot(2,2,2)
plt.plot([0,1],[0,2])

plt.subplot(2,2,3)表示将整个图像窗口分为2行2列,当前位置为3. plt.subplot(2,2,3)可以简写成plt.subplot(223), matplotlib同样可以识别. 使用plt.plot([0,1],[0,3])在第3个位置创建一个小图.

1
2
plt.subplot(223)
plt.plot([0,1],[0,3])

plt.subplot(224)表示将整个图像窗口分为2行2列, 当前位置为4. 使用plt.plot([0,1],[0,4])在第4个位置创建一个小图.

1
2
plt.subplot(224)
plt.plot([0,1],[0,4])

不均匀图中图

如果把第1个小图放到第一行, 而剩下的3个小图都放到第二行.

使用plt.subplot(2,1,1)将整个图像窗口分为2行1列, 当前位置为1. 使用plt.plot([0,1],[0,1])在第1个位置创建一个小图.

1
2
plt.subplot(2,1,1)
plt.plot([0,1],[0,1])

使用plt.subplot(2,3,4)将整个图像窗口分为2行3列, 当前位置为4. 使用plt.plot([0,1],[0,2])在第4个位置创建一个小图.

1
2
3
4
5
6
7
8
9
import numpy as np
import matplotlib.pyplot as plt
# 使用plt.figure创建一个图像窗口.
plt.figure()
plt.subplot(2,1,1)
plt.plot([0,1],[0,1])
plt.subplot(2,3,4)
plt.plot([0,1],[0,2])
plt.show()

上一步中使用plt.subplot(2,1,1)将整个图像窗口分为2行1列, 第1个小图占用了第1个位置, 也就是整个第1行. 这一步中使用plt.subplot(2,3,4)将整个图像窗口分为2行3列, 于是整个图像窗口的第1行就变成了3列, 也就是成了3个位置, 于是第2行的第1个位置是整个图像窗口的第4个位置.

使用plt.subplot(235)将整个图像窗口分为2行3列,当前位置为5. 使用plt.plot([0,1],[0,3])在第5个位置创建一个小图. 同上, 再创建plt.subplot(236).

1
2
3
4
plt.subplot(235)
plt.plot([0,1],[0,3])
plt.subplot(236)
plt.plot([0,1],[0,4])

Subplot 分格显示

subplot2grid

使用plt.subplot2grid来创建第1个小图, (3,3)表示将整个图像窗口分成3行3列, (0,0)表示从第0行第0列开始作图,colspan=3表示列的跨度为3, rowspan=1表示行的跨度为1. colspanrowspan缺省, 默认跨度为1.

1
2
3
4
5
6
7
import numpy as np
import matplotlib.pyplot as plt
# 使用plt.figure创建一个图像窗口.
ax1 = plt.subplot2grid((3, 3), (0, 0), colspan=3)
ax1.plot([1, 2], [1, 2]) # 画小图
ax1.set_title('ax1_title') # 设置小图的标题
plt.show()

使用plt.subplot2grid来创建第2个小图, (3,3)表示将整个图像窗口分成3行3列, (1,0)表示从第1行第0列开始作图,colspan=2表示列的跨度为2. 同上画出 ax3, (1,2)表示从第1行第2列开始作图,rowspan=2表示行的跨度为2. 再画一个 ax4ax5, 使用默认 colspan, rowspan.

1
2
3
4
ax2 = plt.subplot2grid((3, 3), (1, 0), colspan=2)
ax3 = plt.subplot2grid((3, 3), (1, 2), rowspan=2)
ax4 = plt.subplot2grid((3, 3), (2, 0))
ax5 = plt.subplot2grid((3, 3), (2, 1))

使用ax4.scatter创建一个散点图, 使用ax4.set_xlabelax4.set_ylabel来对x轴和y轴命名.

1
2
3
ax4.scatter([1, 2], [2, 2])
ax4.set_xlabel('ax4_x')
ax4.set_ylabel('ax4_y')

gridspec

使用import导入matplotlib.pyplot模块, 并简写成plt. 使用import导入matplotlib.gridspec, 并简写成gridspec.

1
2
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec

使用plt.figure()创建一个图像窗口, 使用gridspec.GridSpec将整个图像窗口分成3行3列.

1
2
plt.figure()
gs = gridspec.GridSpec(3, 3)

使用plt.subplot来作图, gs[0, :]表示这个图占第0行和所有列, gs[1, :2]表示这个图占第1行和第2列前的所有列, gs[1:, 2]表示这个图占第1行后的所有行和第2列, gs[-1, 0]表示这个图占倒数第1行和第0列, gs[-1, -2]表示这个图占倒数第1行和倒数第2列.

1
2
3
4
5
ax6 = plt.subplot(gs[0, :])
ax7 = plt.subplot(gs[1, :2])
ax8 = plt.subplot(gs[1:, 2])
ax9 = plt.subplot(gs[-1, 0])
ax10 = plt.subplot(gs[-1, -2])

subplots

使用plt.subplots建立一个2行2列的图像窗口,sharex=True表示共享x轴坐标, sharey=True表示共享y轴坐标. ((ax11, ax12), (ax13, ax14))表示第1行从左至右依次放ax11ax12, 第2行从左至右依次放ax13ax14.

1
f, ((ax11, ax12), (ax13, ax14)) = plt.subplots(2, 2, sharex=True, sharey=True)

使用ax11.scatter创建一个散点图.

1
ax11.scatter([1,2], [1,2])

plt.tight_layout()表示紧凑显示图像, plt.show()表示显示图像.

1
2
plt.tight_layout()
plt.show()

图中图

准备数据

1
2
3
4
5
6
7
8
9
# 导入pyplot模块
import matplotlib.pyplot as plt

# 初始化figure
fig = plt.figure()

# 创建数据
x = [1, 2, 3, 4, 5, 6, 7]
y = [1, 3, 4, 2, 5, 8, 6]

大图

绘制大图。首先确定大图左下角的位置以及宽高:

1
left, bottom, width, height = 0.1, 0.1, 0.8, 0.8

4个值都是占整个figure坐标系的百分比。在这里,假设figure的大小是10x10,那么大图就被包含在由(1, 1)开始,宽8,高8的坐标系内。

将大图坐标系添加到figure中,颜色为r(red),取名为title:

1
2
3
4
5
ax1 = fig.add_axes([left, bottom, width, height])
ax1.plot(x, y, 'r')
ax1.set_xlabel('x')
ax1.set_ylabel('y')
ax1.set_title('title')

小图

绘制左上角的小图,步骤和绘制大图一样,注意坐标系位置和大小的改变:

1
2
3
4
5
6
left, bottom, width, height = 0.2, 0.6, 0.25, 0.25
ax2 = fig.add_axes([left, bottom, width, height])
ax2.plot(y, x, 'b')
ax2.set_xlabel('x')
ax2.set_ylabel('y')
ax2.set_title('title inside 1')

绘制右下角的小图。这里我们采用一种更简单方法,即直接往plt里添加新的坐标系:

1
2
3
4
5
plt.axes([0.6, 0.2, 0.25, 0.25])
plt.plot(y[::-1], x, 'g') # 注意对y进行了逆序处理
plt.xlabel('x')
plt.ylabel('y')
plt.title('title inside 2')

次坐标轴

有时候我们会用到次坐标轴,即在同个图上有第2个y轴存在。

第一个y坐标

1
2
3
4
5
6
7
8
9
10
import matplotlib.pyplot as plt
import numpy as np

x = np.arange(0, 10, 0.1)

y1 = 0.05 * x**2

y2 = -1 * y1
# 可以看到,y2和y1是互相倒置的。接着,获取figure默认的坐标系 ax1:
fig, ax1 = plt.subplots()

第二个y坐标

ax1调用twinx()方法,生成如同镜面效果后的ax2

1
2
3
4
5
6
7
ax2 = ax1.twinx()
# 接着进行绘图, 将 y1, y2 分别画在 ax1, ax2 上:
ax1.plot(x, y1, 'g-') # green, solid line
ax1.set_xlabel('X data')
ax1.set_ylabel('Y1 data', color='g')
ax2.plot(x, y2, 'b-') # blue
ax2.set_ylabel('Y2 data', color='b')

Animation 动画

定义方程

使用matplotlib做动画也是可以的,我们使用其中一种方式,function animation来说说, 具体可参考matplotlib animation api。首先,我们做一些准备工作:

1
2
3
4
from matplotlib import pyplot as plt
from matplotlib import animation
import numpy as np
fig, ax = plt.subplots()

我们的数据是一个0~2π内的正弦曲线:

1
2
x = np.arange(0, 2*np.pi, 0.01)
line, = ax.plot(x, np.sin(x))

接着,构造自定义动画函数animate,用来更新每一帧上各个x对应的y坐标值,参数表示第i帧:

1
2
3
def animate(i):
line.set_ydata(np.sin(x + i/10.0))
return line,

然后,构造开始帧函数init

1
2
3
def init():
line.set_ydata(np.sin(x))
return line,

参数设置

接下来,我们调用FuncAnimation函数生成动画。参数说明: 1. fig 进行动画绘制的figure 2. func 自定义动画函数,即传入刚定义的函数animate 3. frames 动画长度,一次循环包含的帧数 4. init_func 自定义开始帧,即传入刚定义的函数init 5. interval 更新频率,以ms计 6. blit 选择更新所有点,还是仅更新产生变化的点。应选择True,但mac用户请选择False,否则无法显示动画.(用的pycharm2020 3.3版本,没实验成功)

1
2
3
4
5
6
ani = animation.FuncAnimation(fig=fig,
func=animate,
frames=100,
init_func=init,
interval=20,
blit=False)

也可以将动画以mp4格式保存下来,但首先要保证你已经安装了ffmpeg 或者mencoder, 更多信息参考matplotlib animation api

1
ani.save('basic_animation.mp4', fps=30, extra_args=['-vcodec', 'libx264'])
文章目录
  1. 1. numpy & pandas
    1. 1.1. 优点
    2. 1.2. numpy
      1. 1.2.1. 官方参考文档(2021-4-18引用)
      2. 1.2.2. numpy 的属性
      3. 1.2.3. 创建array的形式
      4. 1.2.4. 矩阵基本运算
        1. 1.2.4.1. 矩阵的加减乘法
        2. 1.2.4.2. 矩阵相乘和矩阵点乘(对应元素乘法)
        3. 1.2.4.3. 对矩阵中所有元素进行求和,寻找最小值,寻找最大值
        4. 1.2.4.4. 查找矩阵对应元素的索引
        5. 1.2.4.5. 求矩阵的平均值和中位数
        6. 1.2.4.6. 矩阵的累加和累减用法(cumsum和diff)
        7. 1.2.4.7. 将非零元素的行和列分开(nonzero)
        8. 1.2.4.8. 行排序(sort)
        9. 1.2.4.9. 矩阵的转置
        10. 1.2.4.10. 元素在最大最小值外的替换(clip)
      5. 1.2.5. Numpy 索引和迭代输出
      6. 1.2.6. 矩阵合并
        1. 1.2.6.1. 垂直合并(vstack)
        2. 1.2.6.2. 水平合并(hstack)
        3. 1.2.6.3. 增加维度(newaxis)
        4. 1.2.6.4. 合并多个矩阵或序列(concatenate)
      7. 1.2.7. 矩阵分割
        1. 1.2.7.1. 纵向和横向分割
        2. 1.2.7.2. 不等量的分割
      8. 1.2.8. Numpy的浅拷贝和深拷贝(copy)
    3. 1.3. Pandas
      1. 1.3.1. 官方文档(2021-4-20)
      2. 1.3.2. Series
      3. 1.3.3. DataFrame
        1. 1.3.3.1. 常用属性查看
        2. 1.3.3.2. 数据排序
        3. 1.3.3.3. 数据选择
          1. 1.3.3.3.1. 根据标签 loc
          2. 1.3.3.3.2. 根据序列 iloc
          3. 1.3.3.3.3. 通过判断的筛选
        4. 1.3.3.4. 值的设置
          1. 1.3.3.4.1. 根据位置设置 loc 和 iloc
          2. 1.3.3.4.2. 根据条件设置
          3. 1.3.3.4.3. 按行或列设置
          4. 1.3.3.4.4. 添加数据
        5. 1.3.3.5. 处理丢失数据
          1. 1.3.3.5.1. 去掉有 NaN 的行或列(dropna)
          2. 1.3.3.5.2. 用其他值代替(fillna)
          3. 1.3.3.5.3. 判断有无缺失(isnull)
        6. 1.3.3.6. 导入导出
        7. 1.3.3.7. 合并( concat)
          1. 1.3.3.7.1. 合并方向(axis)
          2. 1.3.3.7.2. 重置 index(ignore_index)
          3. 1.3.3.7.3. join 合并方式
          4. 1.3.3.7.4. join_axes (已失效)
          5. 1.3.3.7.5. 添加数据(append )
        8. 1.3.3.8. 合并(merge)
          1. 1.3.3.8.1. 依据一组key合并
          2. 1.3.3.8.2. 依据两组key合并
          3. 1.3.3.8.3. Indicator
          4. 1.3.3.8.4. 依据index合并
          5. 1.3.3.8.5. 解决overlapping的问题
        9. 1.3.3.9. plot 出图
        10. 1.3.3.10. Dataframe 可视化
  2. 2. Matplotlib
    1. 2.1. 官网地址(2021-4-20)
    2. 2.2. 基本用法
      1. 2.2.1. 基础应用
      2. 2.2.2. 设置坐标轴
        1. 2.2.2.1. 调整坐标轴名字和间隔
        2. 2.2.2.2. 调整坐标轴
        3. 2.2.2.3. Legend 设置图例
          1. 2.2.2.3.1. 添加图例
          2. 2.2.2.3.2. 调整位置和名称
        4. 2.2.2.4. Annotation 标注
          1. 2.2.2.4.1. 画出基本图
          2. 2.2.2.4.2. 移动坐标
          3. 2.2.2.4.3. 添加注释 annotate
          4. 2.2.2.4.4. 添加注释 text
        5. 2.2.2.5. tick 能见度
          1. 2.2.2.5.1. 生成图形
          2. 2.2.2.5.2. 调整坐标
    3. 2.3. 画图种类
      1. 2.3.1. Scatter 散点图
      2. 2.3.2. Bar 柱状图
        1. 2.3.2.1. 生成基本图形
        2. 2.3.2.2. 加颜色和数据
      3. 2.3.3. Contours 等高线图
        1. 2.3.3.1. 画等高线
        2. 2.3.3.2. 添加高度数字
      4. 2.3.4. Image 图片
        1. 2.3.4.1. 随机矩阵画图
        2. 2.3.4.2. 出图方式
          1. 2.3.4.2.1. colorbar
      5. 2.3.5. 3D 图
        1. 2.3.5.1. 投影
    4. 2.4. Subplot 多合一显示
      1. 2.4.1. 均匀图中图
      2. 2.4.2. 不均匀图中图
    5. 2.5. Subplot 分格显示
      1. 2.5.1. subplot2grid
      2. 2.5.2. gridspec
      3. 2.5.3. subplots
    6. 2.6. 图中图
      1. 2.6.1. 准备数据
      2. 2.6.2. 大图
      3. 2.6.3. 小图
    7. 2.7. 次坐标轴
      1. 2.7.1. 第一个y坐标
      2. 2.7.2. 第二个y坐标
    8. 2.8. Animation 动画
      1. 2.8.1. 定义方程
      2. 2.8.2. 参数设置