Skip to content

图表

pyecharts

https://github.com/pyecharts/pyecharts

http://pyecharts.org/#/zh-cn/

https://gallery.pyecharts.org/#/README

生成图片

安装依赖

1
pip install snapshot_selenium

https://github.com/pyecharts/snapshot-selenium

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
from pyecharts.charts import Bar
from pyecharts import options as opts
from snapshot_selenium import snapshot as driver
from pyecharts.render import make_snapshot

bar = Bar()
bar.add_xaxis(["衬衫", "毛衣", "领带", "裤子", "风衣", "高跟鞋", "袜子"])
bar.add_yaxis("商家A", [114, 55, 27, 101, 125, 27, 105])
bar.add_yaxis("商家B", [57, 134, 137, 129, 145, 60, 49])
bar.set_global_opts(title_opts=opts.TitleOpts(title="某商场销售情况"))
make_snapshot(driver, bar.render(), "bar.png")
# make_snapshot(driver, "xxx.html", "bar.png")

因为是用的selenium,可能会出现chromedriver版本和Chrome版本不一样的情况,更新一下chromedirver即可

查看bar.png,如下图所示:

画表格

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
from pyecharts.components import Table
from pyecharts.options import ComponentTitleOpts

table = Table()

headers = ["City name", "Area", "Population", "Annual Rainfall"]
rows = [
    ["Brisbane", 5905, 1857594, 1146.4],
    ["Adelaide", 1295, 1158259, 600.5],
    ["Darwin", 112, 120900, 1714.7],
    ["Hobart", 1357, 205556, 619.5],
    ["Sydney", 2058, 4336374, 1214.8],
    ["Melbourne", 1566, 3806092, 646.9],
    ["Perth", 5386, 1554769, 869.4],
]
table.add(headers, rows)
table.set_global_opts(
    title_opts=ComponentTitleOpts(title="Table-基本示例", subtitle="我是副标题支持换行哦")
)
table.render("table_base.html")

https://github.com/pyecharts/pyecharts/issues/1170

注意:Table、Image 类目前并不支持 snapshot!

生成表格的 html 并发送邮件:

 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
import smtplib
from email.mime.text import MIMEText
from email.utils import formatdate
from email.header import Header
from email.mime.multipart import MIMEMultipart
from email.mime.image import MIMEImage
from pyecharts.components import Table
from pyecharts.options import ComponentTitleOpts
from snapshot_selenium import snapshot as driver
from pyecharts.render import make_snapshot

def get_html_table():
    table = Table()
    headers = ["City name", "Area", "Population", "Annual Rainfall"]
    rows = [
        ["Brisbane", 5905, 1857594, 1146.4],
        ["Adelaide", 1295, 1158259, 600.5],
        ["Darwin", 112, 120900, 1714.7],
        ["Hobart", 1357, 205556, 619.5],
        ["Sydney", 2058, 4336374, 1214.8],
        ["Melbourne", 1566, 3806092, 646.9],
        ["Perth", 5386, 1554769, 869.4],
    ]
    table.add(headers, rows)
    return table.html_content

def send_email(to_addr):
    host = 'smtp.exmail.qq.com'
    port = 465
    username = "zhaoyz@xxx.com"
    password = "xxx"

    smtp = smtplib.SMTP_SSL(host, port)
    smtp.login(username, password)

    subject = '[Notice]hello'
    body = """
    <h1>test_html_table</h1>
    """
    body += get_html_table()

    # 初始化邮件
    encoding = 'utf-8'
    mail = MIMEMultipart('mixed')
    mail.attach(MIMEText(body.encode(), 'html', encoding))
    mail['Subject'] = Header(subject, encoding)
    mail['From'] = username
    mail['To'] = to_addr
    mail['Date'] = formatdate()

    smtp.sendmail(username, to_addr, mail.as_string())

send_email("zhaoyangzhen@foxmail.com")

画折线图

 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 pyecharts.options as opts
from pyecharts.charts import Line
from snapshot_selenium import snapshot as driver
from pyecharts.render import make_snapshot


week_name_list = ["周一", "周二", "周三", "周四", "周五", "周六", "周日"]
high_temperature = [11, 11, 15, 13, 12, 13, 10]
low_temperature = [1, -2, 2, 5, 3, 2, 0]
line = Line(init_opts=opts.InitOpts(width="1600px", height="800px"))
line.add_xaxis(xaxis_data=week_name_list)
line.add_yaxis(
    series_name="最高气温",
    y_axis=high_temperature,
)
line.add_yaxis(
    series_name="最低气温",
    y_axis=low_temperature,
)
line.set_global_opts(
    title_opts=opts.TitleOpts(title="未来一周气温变化"),
    tooltip_opts=opts.TooltipOpts(trigger="axis"),
    xaxis_opts=opts.AxisOpts(type_="category", boundary_gap=False),
)
line.render("temperature_change_line_chart.html")
# make_snapshot(driver, line.render(), "line.png")

生成 svg

svg 的分辨率更高

注意生成图片时格式必须是 .svg 格式:

 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
from pyecharts import options as opts
from pyecharts.charts import HeatMap
from pyecharts.options.series_options import LabelOpts
from pyecharts.render import make_snapshot
from snapshot_selenium import snapshot as driver
import pandas as pd

dic = {
    "a": [1, 2, 5, 7],
    "一个各个": [23333, None, 3, 2],
    "中正500": [1, 5, 66, 99],
    "我大的点点滴": [25, 0, 66, None],
    "我得到的": [25, -233, 66, 345],
    "你卧榻": [0, -233, -55, 345]
}
df = pd.DataFrame(dic)
names = list(dic.keys())
corr = df.corr()
print(corr)
data = corr.to_dict('split')['data']
# print(data)
item_len = len(data)
value = []
values_mean = []
for i in range(item_len):
    val_sum = 0
    for j in range(item_len):
        value.append([i, j, round(data[i][j] * 100) / 100])
        if i != j:
            val_sum += data[i][j]
    values_mean.append(round(val_sum / (item_len - 1) * 100) / 100)
for i in range(item_len):
    value.append([item_len, i, values_mean[i]])

max_value = -1e9
min_value = 1e9

for i in range(item_len):
    for j in range(item_len):
        max_value = max(max_value, value[i * item_len + j][2])
        min_value = min(min_value, value[i * item_len + j][2])
print(min_value, max_value)
heatmap = HeatMap(init_opts=opts.InitOpts(theme="dark", renderer="svg"))
xaxis_opts = opts.AxisOpts(
    position="top",
    axislabel_opts=LabelOpts(font_size=5),
)
yaxis_opts = opts.AxisOpts(
    is_inverse=True,
    axislabel_opts=LabelOpts(font_size=8),
)
heatmap.set_global_opts(
    xaxis_opts=xaxis_opts,
    yaxis_opts=yaxis_opts,
)
heatmap.add_xaxis(names + ["汇总"])
heatmap.add_yaxis(
        "相关性系数矩阵",
        names,
        value,
        label_opts=opts.LabelOpts(is_show=True, position="inside"),
    )
heatmap.set_global_opts(
        title_opts=opts.TitleOpts(),
        visualmap_opts=opts.VisualMapOpts(
            range_color=["green", "red"],
            min_=min_value,
            max_=max_value,
        ),
    )


heatmap.render("heatmap_with_label_show2.html")

make_snapshot(driver, "heatmap_with_label_show2.html", "test.svg")

生成的 svg 文件内容为一个 svg 标签,可以直接将其文本嵌入到 html 文件中

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<!DOCTYPE html>
<html lang="zh">
<head>
  <meta charset="UTF-8">
  <title>Page Title</title>
</head>
<body>
    <svg>xxx</svg>
</body>
</html>

Matplotlib

常用技巧

导入

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

设置绘图样式:我们将使用 plt.style 来选择图形的绘图风格。现在选择经典(classic)风格,这样画出的图就都是经典的 Matplotlib 风格了

1
plt.style.use('classic')

在脚本中画图

如果你在一个脚本中使用 Matplotlib,那么显示图形的时候必须使用 plt.show()。plt.show() 会启动一个事件循环(event loop),并找到所有当前可用的图形对象,然后打开一个或多个交互式窗口显示图形

1
2
3
4
5
6
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0, 10, 100)
plt.plot(x, np.sin(x))
plt.plot(x, np.cos(x))
plt.show()

注意:一个 Python 会话中只能使用一次 plt.show(),因此通常都把它放在脚本的最后。多个 plt.show() 命令会导致难以预料的显示异常,应该尽量避免

简易线形图

调整图形:坐标轴上下限

1
2
3
4
5
6
7
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0, 10, 100)
plt.plot(x, np.sin(x))
plt.xlim(-1, 11)
plt.ylim(-1.5, 1.5)
plt.show()

调整坐标轴上下限

还有一个方法是plt.axis()。通过传入[xmin, xmax, ymin, ymax]对应的值,plt.axis()方法可以用一行代码设置 xy 的限值

简易散点图

用plt.plot画散点图

1
2
3
4
5
6
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0, 10, 30)
y = np.sin(x)
plt.plot(x, y, 'o', color='black')
plt.show()

用plt.scatter画散点图

1
2
3
4
5
6
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0, 10, 30)
y = np.sin(x)
plt.scatter(x, y, marker='o')
plt.show()

plt.scatterplt.plot的主要差别在于,前者在创建散点图时具有更高的灵活性,可以单独控制每个散点与数据匹配,也可以让每个散点具有不同的属性(大小、表面颜色、边框颜色等)

PyG2Plot

https://github.com/hustcc/PyG2Plot