《基于plotly的可视化绘图》笔记3

《python数据分析 基于plotly的动态可视化绘图》, 孙洋洋 王硕 邢梦来 袁泉 吴娜著, 电子工业出版社.

看到这里有点乏味了,下周打算去爬个房价数据画着试试。

分类回归与聚类

鸢尾花 SVM 分类

SVM分类图

画图步骤为两步,一是绘制热力图,即背景图;
另一个是绘制样本点,需要将颜色与分类标签挂钩,即color=Y,保证同类样本显示同样的颜色。但是我不明白为什么:

1
2
3
4
x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
x_ = np.arange(x_min, x_max, h) # x、y是两个特征
y_ = np.arange(y_min, y_max, h) # 生成等差h的的序列

这个处理为什么如此正好。

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 plotly as py
import plotly.graph_objs as go
import numpy as np
import matplotlib.pyplot as plt
from sklearn import svm, datasets

pyplt = py.offline.iplot
iris = datasets.load_iris()
X = iris.data[:, :2] # 只取前两个特征
Y = iris.target # 分类标签 0 1 2
h = .02 # 设定网格大小
clf = svm.SVC(kernel='linear')
clf.fit(X, Y)

x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
x_ = np.arange(x_min, x_max, h) # x、y是两个特征
y_ = np.arange(y_min, y_max, h) # 生成等差h的的序列
xx, yy = np.meshgrid(x_, y_)
Z = clf.predict(np.c_[xx.ravel(), yy.ravel()]) # xx.ravel() 将多维数组转化为一维的; np.c_将数组按行转化为矩阵

# Put the result into a color plot
Z = Z.reshape(xx.shape) # 分类得到的结果矩阵 220*280

cmap = ['RGB(10,64,159)','RGB(5,159,126)','RGB(159,26,64)'] #源代码多了个中括号
# 画布
trace1 = go.Heatmap(x=x_, y=y_, z=Z,
colorscale=cmap,
showscale=False)

# 画点
trace2 = go.Scatter(x=X[:, 0], y=X[:, 1],
mode='markers',
marker=dict(color=Y,
colorscale=cmap,
showscale=False,
line=dict(color='black', width=1)))

layout = go.Layout(title="基于线性核的SVM的多分类")
fig = go.Figure(data= [trace1, trace2], layout=layout)
pyplt(fig)

随机数据 SVM 回归

SVM回归图

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
import plotly as py
import plotly.graph_objs as go
import numpy as np
from sklearn.svm import SVR

pyplt = py.offline.iplot

X = np.sort(5 * np.random.rand(40, 1), axis=0)
y = np.sin(X).ravel()
y[::5] += 3 * (0.5 - np.random.rand(8))

svr_rbf = SVR(kernel='rbf', C=1e3, gamma=0.1)
svr_lin = SVR(kernel='linear', C=1e3)
svr_poly = SVR(kernel='poly', C=1e3, degree=3)

y_rbf = svr_rbf.fit(X, y).predict(X)
y_lin = svr_lin.fit(X, y).predict(X)
y_poly = svr_poly.fit(X, y).predict(X)


def data_to_plotly(x):
k = []

for i in range(0, len(x)):
k.append(x[i][0])

return k

lw = 2
p1 = go.Scatter(x=data_to_plotly(X), y=y, # 原始点的xy
mode='markers',
marker=dict(color='darkorange'),
name='data')

p2 = go.Scatter(x=data_to_plotly(X), y=y_rbf, # RBF拟合的结果
mode='lines',
line=dict(color='navy', width=lw),
name='RBF model')

p3 = go.Scatter(x=data_to_plotly(X), y=y_lin, # 线性拟合
mode='lines',
line=dict(color='cyan', width=lw),
name='Linear model')

p4 = go.Scatter(x=data_to_plotly(X), y=y_poly, # 多项式拟合
mode='lines',
line=dict(color='cornflowerblue', width=lw),
name='Polynomial model')

layout = go.Layout(title='SVM回归',
hovermode='closest',
xaxis=dict(title='data'),
yaxis=dict(title='target'))

fig = go.Figure(data=[p1, p2, p3, p4], layout=layout)
pyplt(fig)

聚类图

本案例比较的是K-meansMiniBatchKmeans.

本案例分为三部分:产生聚类的数据;两种方法训练模型;绘制聚类图。

会得到三个图,前两个分别是两种方法的分类结果,第三张图片会突出两种分类结果的差异。

聚类图

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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
import plotly as py
import plotly.graph_objs as go
from plotly import tools

import time
import numpy as np

from sklearn.cluster import MiniBatchKMeans, KMeans
from sklearn.metrics.pairwise import pairwise_distances_argmin
from sklearn.datasets.samples_generator import make_blobs

# 生成随机数据
np.random.seed(0)

batch_size = 45
centers = [[1, 1], [-1, -1], [1, -1]]
n_clusters = len(centers)
X, labels_true = make_blobs(n_samples = 3000, centers = centers, cluster_std = 0.7) #书上说的不对,centers是聚类中心。

# n_samples是待生成的样本的总数
# cluster_std表示每个类别的方差,例如我们希望生成2类数据,其中一类比另一类具有更大的方差,可以将cluster_std设置为[1.0,3.0]。
# 训练模型
# 使用K-means算法
k_means = KMeans(init = 'k-means++', n_clusters = 3, n_init = 10)
t0 = time.time()
k_means.fit(X)
t_batch = time.time() - t0

# 使用MiniBatchKMeans算法
mbk = MiniBatchKMeans(init = 'k-means++', n_clusters = 3, batch_size = batch_size,
n_init = 10, max_no_improvement = 10, verbose = 0)
t0 = time.time()
mbk.fit(X)
t_mini_batch = time.time() - t0
# 画图
pyplt = py.offline.iplot
colors = ['#4EACC5', '#FF9C34', '#4E9A06']

# 希望MiniBatchKMeans和KMeans算法中的同一个集群有相同的颜色
k_means_cluster_centers = np.sort(k_means.cluster_centers_, axis=0)
mbk_means_cluster_centers = np.sort(mbk.cluster_centers_, axis=0)
# 计算一个点和一组点之间的最小距离
k_means_labels = pairwise_distances_argmin(X, k_means_cluster_centers)
mbk_means_labels = pairwise_distances_argmin(X, mbk_means_cluster_centers)
order = pairwise_distances_argmin(k_means_cluster_centers,
mbk_means_cluster_centers)

fig = tools.make_subplots(rows=1, cols=3,
print_grid=False,
subplot_titles=('KMeans<br>train time: %.2fs\ninertia: %f' %
(t_mini_batch, mbk.inertia_),
'MiniBatchKmeans<br>train time: %.2fs\ninertia: %f' %
(t_mini_batch, mbk.inertia_),
'Difference'))
# 第一张图
for k, col in zip(range(n_clusters), colors):
my_members = k_means_labels == k
cluster_center = k_means_cluster_centers[k]
kmeans1 = go.Scatter(x=X[my_members, 0], y=X[my_members, 1],
showlegend=False,
mode='markers', marker=dict(color=col, size=4))
kmeans2 = go.Scatter(x=[cluster_center[0]], y=[cluster_center[1]],
showlegend=False,
mode='markers', marker=dict(color=col, size=14,
line=dict(color='black',
width=1)))
fig.append_trace(kmeans1, 1, 1)
fig.append_trace(kmeans2, 1, 1)

fig['layout']['xaxis1'].update(showticklabels=False, ticks='',
zeroline=False, showgrid=False)
fig['layout']['yaxis1'].update(showticklabels=False, ticks='',
zeroline=False, showgrid=False)
# 第二张图
for k, col in zip(range(n_clusters), colors):
my_members = mbk_means_labels == order[k]
cluster_center = mbk_means_cluster_centers[order[k]]
minibatchkmeans1 = go.Scatter(x=X[my_members, 0], y=X[my_members, 1],
showlegend=False,
mode='markers', marker=dict(color=col, size=4))
minibatchkmeans2 = go.Scatter(x=[cluster_center[0]], y=[cluster_center[1]],
showlegend=False,
mode='markers', marker=dict(color=col, size=14,
line=dict(color='black',
width=1)))
fig.append_trace(minibatchkmeans1, 1, 2)
fig.append_trace(minibatchkmeans2, 1, 2)

fig['layout']['xaxis2'].update(showticklabels=False, ticks='',
zeroline=False, showgrid=False)
fig['layout']['yaxis2'].update(showticklabels=False, ticks='',
zeroline=False, showgrid=False)

# 第三张图
different = (mbk_means_labels == 4)

for k in range(n_clusters):
different += ((k_means_labels == k) != (mbk_means_labels == order[k]))

identic = np.logical_not(different)
difference1 = go.Scatter(x=X[identic, 0], y=X[identic, 1],
showlegend=False,
mode='markers', marker=dict(color='#bbbbbb', size=4))

difference2 = go.Scatter(x=X[different, 0], y=X[different, 1],
showlegend=False,
mode='markers', marker=dict(color='magenta', size=4))

fig.append_trace(difference1, 1, 3)
fig.append_trace(difference2, 1, 3)

fig['layout']['xaxis3'].update(showticklabels=False, ticks='',
zeroline=False, showgrid=False)
fig['layout']['yaxis3'].update(showticklabels=False, ticks='',
zeroline=False, showgrid=False)
pyplt(fig)

visdom与plotly

visdom是一个可交互式工具组件,绘图底层用的是plotlyjs接口,支持torchnumpy

安装使用

jupyter里使用:

!pip install visdom -i https://pypi.tuna.tsinghua.edu.cn/simple

启动服务器:

!python -m visdom.server
python -m visdom.server

启动不了,好像是得下点东西,有需要再说吧。

matplotlib

这本书真的不错,是我太菜了,经验忒少。

在用matplotlib绘图的时候,是在一个figure对象上,可以画多个axes对象。
每个axes对象都是一个拥有自己坐标系统的绘图区域。

  • axes 设置坐标轴边界、颜色、坐标刻度值大小和网格的显示。
  • figure 设置边界颜色、图形大小和子区。
  • font 字体 字号 样式
  • grid 网格颜色和线型
  • legend 图例和文本显示
  • lines 线条颜色线型宽度 标记
  • savefig 对保存的图形单独设置
  • xtick ytick 坐标轴刻度的值 为xy轴的主刻度和次刻度设置颜色、大小、方向和标签大小。
  • text 添加文字说明
  • axis 坐标范围
  • xlim 调整坐标范围
  • annotate 文本注释 需考虑两个点:被注释的地方和插入文本的地方
  • subplot 子图

线性函数

线性函数

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
import matplotlib.pyplot as plt
#使用import导入模块matplotlib.pyplot,并简写成plt
import numpy as np
#使用import导入模块numpy,并简写成np
import plotly as py # 导入plotly库并命名为py

# 配置中文显示
plt.rcParams['font.family'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号

fig, ax = plt.subplots()
x = np.linspace(1,10)
# np.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None)
# 参数解释:start,stop是开始,结束的数字,num是生成多少个数字,默认50个;endpoint是最后一个stop数字是否包含进去,默认包含;retstep,是两个数字间的间距,默认不显示;dtype默认。
y = x*3 + 5
#线性方程y= x*3 + 5
plt.title("线性函数")
#设置标题
plt.xlabel("x 值")
#设置x轴标签
plt.ylabel("y 值")
#设置y轴标签
ax.plot(x, y)
#画图
plt.show()

子图

1

子图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
import numpy as np#使用import导入模块numpy
import matplotlib.pyplot as plt#使用import导入模块matplotlib.pyplot
import plotly as py # 导入plotly库并命名为py

pympl = py.offline.iplot_mpl
fig, ax = plt.subplots()

x1 = np.arange(0.0, 3.0, 0.01)
x2 = np.arange(0.0, 4.0, 0.01)
#产生x1,x2数据
y1 = np.cos(2 * np.pi * x1) * np.exp(-x1)
y2 = np.cos(2 * np.pi * x2)
#产生数据y1,y2
plt.subplot(2, 1, 1)
# pyplot通过调用subplot或者add_subplot来增加子图,如p1 = plt.subplot(211) 或者 p1 = plt.subplot(2,1,1), 表示创建一个2行,1列的图,p1为第一个子图,然后在p1上画曲线,设置标注标题图例等,就可以使用p1来调用相关的函数,可以直接使用pyplot画图,添加label,等。
plt.plot(x1, y1)
plt.title('子图1')
#添加标题
plt.ylabel('y1 值')
#添加y轴名称
plt.subplot(2, 1, 2)
#添加子图
plt.plot(x2, y2)
plt.xlabel('数量')
#添加标签
plt.ylabel('y2 值')
#添加y轴名称
plot_url = pympl(fig, show_link=False,resize=True)

不想整了,暂时用不到的东西学着学着就兴致不高了。

2

子图2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import numpy as np#使用import导入模块numpy
import matplotlib.pyplot as plt#使用import导入模块matplotlib.pyplot
import plotly as py # 导入plotly库并命名为py
pympl = py.offline.iplot_mpl
# 配置中文显示
fig, ax = plt.subplots()

def f(t):
return np.cos(2*np.pi*t)
#产生f(t)函数
t1 = np.arange(0.0, 5.0, 0.5)
t2 = np.arange(0.0, 5.0, 0.01)
#产生t1,t2数据
plt.figure(1)
plt.subplot(211)
#添加子图
plt.plot(t1, f(t1), 'bo', t2, f(t2), 'k')
#画图
plt.subplot(212)
#添加子图
plt.plot(np.cos(2*np.pi*t2), 'r--')

plot_url = pympl(fig, show_link=False,resize=True)

确定坐标范围

确定坐标范围

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from pylab import *
import numpy as np#使用import导入模块numpy
import matplotlib.pyplot as plt#使用import导入模块matplotlib.pyplot
import plotly as py # 导入plotly库并命名为py

pympl = py.offline.iplot_mpl

x = np.arange(-5.0, 5.0, 0.02)
# x = np.linspace(-5, 5, num=50, endpoint=True, retstep=False, dtype=None)
y1 = x**2+1
plt.figure(1)
plt.subplot(211)
xlabel('x 值')
ylabel('y1 值')
#设置x轴范围,x轴只显示(-5,3),总区间(-5,5)
xlim(-5, 3)
#设置y轴范围
ylim(-10, 50)
plt.plot(x,y1)
fig= plt.gcf()
plot_url = pympl(fig, show_link=False,resize=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 numpy as np#使用import导入模块numpy
import matplotlib.pyplot as plt#使用import导入模块matplotlib.pyplot
import plotly as py # 导入plotly库并命名为py
from scipy.stats import norm
pympl = py.offline.iplot_mpl

#正太分布函数等和其他函数都在matplotlib.mlab库里面
np.random.seed(2020)
#产生随机种子
mu = 100
sigma = 15
x = mu + sigma * np.random.randn(437)
#生产数据
num_bins = 50
fig, ax = plt.subplots()
n, bins, patches = ax.hist(x, num_bins, density=1) # 版本更新,把normed改成density
#产生直方图
y = norm.pdf(bins, mu, sigma) # 这里也改了
#normpdf:正态概率密度函数
#Y = normpdf(X,mu,sigma)
#mu:均值
#sigma:标准差
#Y:正态概率密度函数在x处的值
ax.plot(bins, y, '--')
#画图
ax.set_xlabel('X 轴')
#x轴标签
ax.set_ylabel('概率密度')
#y轴标签
ax.set_title(r'柱状图IQ: $\mu=100$, $\sigma=15$')
#设置标题
fig.tight_layout()
#产生紧凑的图片
plot_url = pympl(fig, show_link=False,resize=True)

散点图

1

散点图1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import numpy as np#使用import导入模块numpy
import matplotlib.pyplot as plt#使用import导入模块matplotlib.pyplot
import plotly as py # 导入plotly库并命名为py

pympl = py.offline.iplot_mpl

fig, ax = plt.subplots()
#产生测试数据
x = np.arange(1,30)
y =np.sin(x)
ax1 = fig.add_subplot(111)
#设置标题i
ax1.set_title('散点图')
#设置X轴标签
plt.xlabel('X')
#设置Y轴标签
plt.ylabel('Y')
#画散点图
lValue = x
ax1.scatter(x,y,c='r',s= 100,linewidths=lValue,marker='o')
#设置图标
plt.legend('x1')
plot_url = pympl(fig, show_link=False,resize=True)

不好看啊

2

散点图2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from numpy.random import rand#使用import导入模块numpy
import matplotlib.pyplot as plt#使用import导入模块matplotlib.pyplot
import plotly as py # 导入plotly库并命名为py

pympl = py.offline.iplot_mpl

fig, ax = plt.subplots()
for color in ['red', 'green', 'blue']:
n = 500
x, y = rand(2, n)#产生2*n的矩阵
ax.scatter(x, y, c=color, label=color,
alpha=0.3, edgecolors='none')
#设置每个点的颜色,x,y分别代表的横纵坐标,通过横纵坐标确定点的位置,c表示点的颜色color,s表示点的大小size,alpha表示点的透明度,1是不透明,0是透明。
ax.legend()
ax.grid(True)
#设置网格
plot_url = pympl(fig, show_link=False,resize=True)

柱状图

1

柱状图1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import numpy as np#使用import导入模块numpy
import matplotlib.pyplot as plt#使用import导入模块matplotlib.pyplot
import plotly as py # 导入plotly库并命名为py

pympl = py.offline.iplot_mpl
plt.figure(figsize=(7,5))

X = np.arange(1,6)
#X是1,2,3,4,5,6,7,8,柱的个数
# numpy.random.uniform(low=0.0, high=1.0, size=None), normal
#uniform均匀分布的随机数,normal是正态分布的随机数,0.5-1均匀分布的数,一共有n个
Y1 = np.random.uniform(0.5,1.0,5)
Y2 = np.random.uniform(0.5,1.0,5)
plt.bar(X,Y1,width = 0.35,facecolor = 'lightskyblue',edgecolor = 'white')
#width:柱的宽度
plt.bar(X+0.35,Y2,width = 0.20,facecolor = 'yellowgreen',edgecolor = 'white')
#水平柱状图plt.barh,属性中宽度width变成了高度height
#打两组数据时用+
#facecolor柱状图里填充的颜色
#edgecolor是边框的颜色
#想把一组数据打到下边,在数据前使用负号
fig = plt.gcf()
plot_url = pympl(fig, show_link=False,resize=True)

2

柱状图2

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 numpy as np#使用import导入模块numpy
import matplotlib.pyplot as plt#使用import导入模块matplotlib.pyplot
import plotly as py # 导入plotly库并命名为py

pympl = py.offline.iplot_mpl
np.random.seed(2020)

n_bins = 10
x = np.random.randn(1000, 3) #产生1000*3的矩阵

fig, axes = plt.subplots(nrows=2, ncols=2)
ax0, ax1, ax2, ax3 = axes.flatten()

colors = ['red', 'tan', 'lime'] #设置颜色

ax0.hist(x, n_bins, density=1, histtype='bar', color=colors, label=colors) #设置柱状图的信息
ax0.legend(prop={'size': 10})
ax0.set_title('图例bar') #添加标题

ax1.hist(x, n_bins, density=1, histtype='bar', stacked=True)
ax1.set_title('堆积bar')

ax2.hist(x, n_bins, density=1, histtype='bar', stacked=True, fill=False)
ax2.set_title('堆积bar(非填充)')

x_multi = [np.random.randn(n) for n in [10000, 5000, 2000]]
ax3.hist(x_multi, n_bins, histtype='bar')
ax3.set_title('不同样本容量')

fig.tight_layout() #使图形紧凑
#plt.show()
fig1= plt.gcf()
pympl(fig1)

这个代码是有错的,没找出来咋改,气死我了睡觉了。

reference

visdom使用,https://www.cnblogs.com/fanghao/p/10256287.html
visdom激活服务失败,https://blog.csdn.net/zl1107604962/article/details/104229548?utm_medium=distribute.pc_relevant.none-task-blog-searchFromBaidu-3.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-searchFromBaidu-3.control