前导:入门+工具:
【数据可视化】Pyecharts连接MySQL数据库进行绘图(全)
【数据可视化(一)】Pyecharts中如何使用MySQL数据库中的数据
日历热力图的绘制,先看成果:
程序中连接数据库中不同的表,可以实现一年中温度的可视化。
一、数据库数据格式
三列:日期、地点、温度
二、代码
(一)导入库
pymysql--
用于连接和操作 MySQL 数据库;
pandas--
用于数据处理和分析;
re--
正则表达式库,用于处理和转换日期格式。
import pymysql
import pandas as pd
import re
import pyecharts.options as opts
from pyecharts.charts import Calendar, Tab
from pyecharts.globals import ThemeType
(二)数据库连接与查询
使用 pymysql.connect
连接到 MySQL 数据库,指定主机、用户名、密码、数据库名和字符集。
我们选择五个地区来展示。
# 连接数据库
db = pymysql.connect(
host="localhost",
user="root",
password="root",
db="xiangmu",
charset="utf8",
)
# 查询数据
sql = "SELECT * FROM China_temp_1 WHERE spot IN ('天津市', '广东省', '西藏自治区', '黑龙江省', '浙江省')"
try:
cursor = db.cursor()
cursor.execute(sql)
result = cursor.fetchall()
except Exception as e:
db.rollback()
print("Error", e)
else:
db.commit()
print("Success")
(三)数据处理
创建DataFrame,在上篇文章提到过:
# 创建 DataFrame
df = pd.DataFrame(result, columns=['date', 'spot', 'temp'])
因为数据库中的数据来源不同,日期格式可能不同,所以检查并修改,convert_date
函数:使用正则表达式检查和转换日期格式,从“2020年1月1日”转换为“2020/1/1”:
# 定义日期转换函数
def convert_date(date_str):
# 检查日期格式是否为“2020年1月1日”
match = re.match(r"(\d{4})年(\d{1,2})月(\d{1,2})日", date_str)
if match:
year, month, day = match.groups()
# 转换为“2020/1/1”格式
return f"{year}/{month}/{day}"
return date_str
# 应用日期转换函数
df['date'] = df['date'].apply(convert_date)
将日期列转换为 datetime
格式,以便进行时间序列分析,处理无法转换的日期为 NaT(缺失值),后续一并去除:
# 将日期列转换为 datetime 格式
df['date'] = pd.to_datetime(df['date'], format='%Y/%m/%d', errors='coerce')
去除重复记录,保留每个日期和地点的第一次出现的记录:
# 去除重复记录
df = df.drop_duplicates(subset=['date', 'spot'], keep='first')
按照日期对 DataFrame 进行排序,以便正确展示时间序列数据:
# 按照日期排序
df = df.sort_values(by='date')
(四)创建和配置图表
Tab对象即最上方的城市选择框,可以点击它们切换不同城市数据。
创建一个 Tab
对象,用于将多个图表合并到一个页面中;定义一个地区列表,用于生成图表:
# 创建 Tab 对象
tab = Tab()
# 获取需要展示的地区列表
regions = ['天津市', '广东省', '西藏自治区', '黑龙江省', '浙江省']
遍历每个地区,过滤出对应地区和年份的数据;将数据转换为 pyecharts
日历图表所需的格式,日期和温度以列表形式存储:
# 遍历每个地区,创建对应的 Calendar 图表
for region in regions:
# 过滤出特定地区的数据
df_region = df[df['spot'] == region]
# 过滤出 2022 年的数据
df_2022 = df_region[df_region['date'].dt.year == 2022]
# 转换 DataFrame 为 Calendar 图表所需的数据格式
data = [
[str(row['date'].date()), row['temp']]
for _, row in df_2022.iterrows()
]
最后,为每个地区创建一个 Calendar
图表(即日历图),并设置其初始选项、添加数据、设置全局选项如标题和视觉映射(颜色区间);将生成的 Calendar
图表添加到 Tab
对象中:
# 创建 Calendar 图表
calendar = (
Calendar(init_opts=opts.InitOpts(
bg_color='rgba(0,0,0,0)',
width='2000px',
height='600px',
theme=ThemeType.PURPLE_PASSION,
)
)
.add(
series_name=f"{region} Temperature Data 2022",
yaxis_data=data,
calendar_opts=opts.CalendarOpts(
pos_top="120",
pos_left="30",
pos_right="30",
range_="2022",
yearlabel_opts=opts.CalendarYearLabelOpts(is_show=False),
),
)
.set_global_opts(
title_opts=opts.TitleOpts(pos_top="30", pos_left="center", title=f"{region} Temperature Data 2022"),
visualmap_opts=opts.VisualMapOpts(
is_piecewise=True,
pieces=[
{"max": 80, "min": 35, "label": ">35℃", "color": "#E00501"},
{"max": 34.99, "min": 32, "label": "32-35℃", "color": "#FA5702"},
{"max": 31.99, "min": 28, "label": "28-32℃", "color": "#FA9682"},
{"max": 27.99, "min": 24, "label": "24-28℃", "color": "#FFCCA1"},
{"max": 23.99, "min": 20, "label": "20-24℃", "color": "#FFF3C3"},
{"max": 19.99, "min": 16, "label": "16-20℃", "color": "#BAFB95"},
{"max": 15.99, "min": 12, "label": "12~16℃", "color": "#CEFFCE"},
{"max": 11.99, "min": 8, "label": "8~12℃", "color": "#D0FCFF"},
{"max": 7.99, "min": 4, "label": "4~8℃", "color": "#AAE9F8"},
{"max": 3.99, "min": 0, "label": "0~4℃", "color": "#85D0FF"},
{"max": -0.01, "min": -4, "label": "-4~0℃", "color": "#3E9FEC"},
{"max": -4.01, "min": -10, "label": "-10~-4℃", "color": "#2373D2"},
{"max": -10.01, "min": -20, "label": "-20~-10℃", "color": "#1C5D9E"},
{"max": -20.01, "min": -50, "label": "<-20℃", "color": "#002F87"},
]
),
)
)
# 将 Calendar 图表添加到 Tab 中
tab.add(calendar, region)
(五)渲染图表
# 渲染为 HTML 文件
tab.render("index.html")
三、运行结果
四、源代码
import pymysql
import pandas as pd
import re
import pyecharts.options as opts
from pyecharts.charts import Calendar, Tab
from pyecharts.globals import ThemeType
# 连接数据库
db = pymysql.connect(
host="localhost",
user="root",
password="root",
db="xiangmu",
charset="utf8",
)
# 查询数据
sql = "SELECT * FROM China_temp_1 WHERE spot IN ('天津市', '广东省', '西藏自治区', '黑龙江省', '浙江省')"
try:
cursor = db.cursor()
cursor.execute(sql)
result = cursor.fetchall()
except Exception as e:
db.rollback()
print("Error", e)
else:
db.commit()
print("Success")
# 创建 DataFrame
df = pd.DataFrame(result, columns=['date', 'spot', 'temp'])
# 定义日期转换函数
def convert_date(date_str):
# 检查日期格式是否为“2020年1月1日”
match = re.match(r"(\d{4})年(\d{1,2})月(\d{1,2})日", date_str)
if match:
year, month, day = match.groups()
# 转换为“2020/1/1”格式
return f"{year}/{month}/{day}"
return date_str
# 应用日期转换函数
df['date'] = df['date'].apply(convert_date)
# 将日期列转换为 datetime 格式
df['date'] = pd.to_datetime(df['date'], format='%Y/%m/%d', errors='coerce')
# 去除重复记录
df = df.drop_duplicates(subset=['date', 'spot'], keep='first')
# 按照日期排序
df = df.sort_values(by='date')
# 创建 Tab 对象
tab = Tab()
# 获取需要展示的地区列表
regions = ['天津市', '广东省', '西藏自治区', '黑龙江省', '浙江省']
# 遍历每个地区,创建对应的 Calendar 图表
for region in regions:
# 过滤出特定地区的数据
df_region = df[df['spot'] == region]
# 过滤出 2022 年的数据
df_2022 = df_region[df_region['date'].dt.year == 2022]
# 转换 DataFrame 为 Calendar 图表所需的数据格式
data = [
[str(row['date'].date()), row['temp']]
for _, row in df_2022.iterrows()
]
# 创建 Calendar 图表
calendar = (
Calendar(init_opts=opts.InitOpts(
bg_color='rgba(0,0,0,0)',
width='2000px',
height='600px',
theme=ThemeType.PURPLE_PASSION,
)
)
.add(
series_name=f"{region} Temperature Data 2022",
yaxis_data=data,
calendar_opts=opts.CalendarOpts(
pos_top="120",
pos_left="30",
pos_right="30",
range_="2022",
yearlabel_opts=opts.CalendarYearLabelOpts(is_show=False),
),
)
.set_global_opts(
title_opts=opts.TitleOpts(pos_top="30", pos_left="center", title=f"{region} Temperature Data 2022"),
visualmap_opts=opts.VisualMapOpts(
is_piecewise=True,
pieces=[
{"max": 80, "min": 35, "label": ">35℃", "color": "#E00501"},
{"max": 34.99, "min": 32, "label": "32-35℃", "color": "#FA5702"},
{"max": 31.99, "min": 28, "label": "28-32℃", "color": "#FA9682"},
{"max": 27.99, "min": 24, "label": "24-28℃", "color": "#FFCCA1"},
{"max": 23.99, "min": 20, "label": "20-24℃", "color": "#FFF3C3"},
{"max": 19.99, "min": 16, "label": "16-20℃", "color": "#BAFB95"},
{"max": 15.99, "min": 12, "label": "12~16℃", "color": "#CEFFCE"},
{"max": 11.99, "min": 8, "label": "8~12℃", "color": "#D0FCFF"},
{"max": 7.99, "min": 4, "label": "4~8℃", "color": "#AAE9F8"},
{"max": 3.99, "min": 0, "label": "0~4℃", "color": "#85D0FF"},
{"max": -0.01, "min": -4, "label": "-4~0℃", "color": "#3E9FEC"},
{"max": -4.01, "min": -10, "label": "-10~-4℃", "color": "#2373D2"},
{"max": -10.01, "min": -20, "label": "-20~-10℃", "color": "#1C5D9E"},
{"max": -20.01, "min": -50, "label": "<-20℃", "color": "#002F87"},
]
),
)
)
# 将 Calendar 图表添加到 Tab 中
tab.add(calendar, region)
# 渲染为 HTML 文件
tab.render("index.html")