python 水质日历热力图

本文介绍了使用Python编程获取水质监测站点数据,通过日历热力图展示全年水质变化,评估站点等级,并展示了两种可视化库(calmap和pyecharts)在生成交互式日历热力图的应用。
摘要由CSDN通过智能技术生成

利用日历热力图可以方便的查看站点水质全年的变化情况。

接口获取站点数据

这一步根据自己实际情况,也可以读取excel、MySQL读取数据。这里把API地址已隐去。

import numpy as np
import calendar
import requests
import json
import pandas as pd
import time
from datetime import date, datetime, timedelta
import matplotlib.pyplot as plt
from matplotlib.pylab import style  # 自定义图表风格
# style.use('ggplot')
# 解决中文乱码问题
plt.rcParams['font.sans-serif'] = ['Simhei']# 解决坐标轴刻度负号乱码
plt.rcParams['axes.unicode_minus'] = False
connect_table =pd.read_excel("设备因子对照.xls")
# 根据时间、站点名称参数获取API url
def url_ask(beginTime,endTime,mn,period):
    # beginTime 要拉取的数据开始时间节点(yyyy-MM-dd HH:mm:ss)
    # endTime = "2023-10-30 00:00:00" #前闭后开
    # mn 设备编码
    # page当前页码
    # 原始接口中包括page和pagesize 默认1和10000   
    # 这里需要注意 不宜太大,暂内存,二是如果查询内容过大则会超过1页,需要查询total page 字段的数字,并判断
    # period 时间周期,实时为空,但要带这个请求参数,1小时为h1,4小时为h4,天数据为d1 
    page ="1"
    pageSize ="10000"
    mianurl = "             "
    ip_port = "             "       
    url =ip_port + mianurl+"beginTime="+beginTime+"&endTime="+endTime +"&mn="+mn +"&page="+page +"&period=" +period +"&pageSize="+pageSize
    # 发起API请求获取JSON数据
    return(url)
# 根据站点名称求编码
def seak_mn(ask_station):
    mn_text = connect_table.loc[connect_table['设备名称'] ==ask_station] 
    mn = mn_text.mn.unique()[0]
    return(mn)

period = "h4"
ask_station = '湾凼'
mn = seak_mn(ask_station)
url =url_ask('2023-01-01 00:00:00','2023-11-20 00:00:00',mn,period)

# 根据URL 获取站点监测数据 未经降维
def mn_value(url):
    response = requests.get(url)
    response_data = response.json()
    data =response_data["data"]
    titles =data["titles"]
    titles= pd.DataFrame(titles)
    factor_code = titles["identifier"]
    factor_name = titles["name"]
    # 查询监测数据
    df_value =data["items"]
    df_value = pd.DataFrame(df_value,columns=factor_code)
    df_value.columns= factor_name
    df_value.rename(columns={'上报时间': '监测时间'}, inplace=True)
    return(df_value)
df_value =mn_value(url)
df_value.tail()

输出数据结构如下:

进行站点等级评价

选择 '氨氮', '高锰酸盐指数', '总磷',作为评价因子,以地表水评价导则判断各因子的评价等级,

再按照因子评价等级最高的最为站点评价等级。

df = df_value[['氨氮', '高锰酸盐指数', '总磷', '监测时间']]  
# 数据清洗
df = df.replace(0, np.nan)  # 将0替换为NaN
df = df.dropna(axis=0, how='any')  # 删除包含NaN的行
# 将监测时间转换为日期,并计算日平均值
df['监测时间'] = pd.to_datetime(df['监测时间'])
df['日期'] = df['监测时间'].dt.date
df = df.groupby('日期').mean().reset_index()

# 数据评价
def evaluate_index(value, limits):
    for i, limit in enumerate(limits):
        if value <= limit:
            return i + 1
    return len(limits) + 1

# 设置各因子的标准限值
limits = {
    '高锰酸盐指数': [2, 4, 6, 10, 15],
    '氨氮': [0.15, 0.5, 1, 1.5, 2.0],
    '总磷': [0.02, 0.1, 0.2, 0.3, 0.4]
}

# 计算评价等级
for factor, limit in limits.items():
    df[f'{factor}评价等级'] = df[factor].apply(lambda x: evaluate_index(x, limit))

# 计算站点评价等级
df['站点评价等级'] = df[['高锰酸盐指数评价等级', '氨氮评价等级', '总磷评价等级']].max(axis=1)

最后的结果如下图

日历热力图的绘制

通过简单查询可以知道这个点位的等级范围为2-6类(Ⅱ类到劣Ⅴ类)

第一种方式 calmap库

import pandas as pd
import calmap
import matplotlib.pyplot as plt
import matplotlib.dates as mdates

# 将日期列转换为日期类型
df['日期'] = pd.to_datetime(df['日期'])

# 确保站点评价等级是数值类型
df['站点评价等级'] = pd.to_numeric(df['站点评价等级'])

# 创建日历热力图
fig, ax = plt.subplots(figsize=(20, 6), dpi=300)
calmap.yearplot(df.set_index('日期')['站点评价等级'], year=2023, cmap='RdYlGn_r', linewidth=0.01, linecolor='grey', monthticks=5, monthlabels='none')

# 添加颜色条
cmap = plt.cm.get_cmap('RdYlGn_r', 6)  # 选择颜色映射,这里假设我们将颜色分为7个区间
bounds = [0.5, 1.5, 2.5, 3.5, 4.5, 5.5]  # 设置颜色条的分割点
norm = plt.cm.colors.BoundaryNorm(bounds, cmap.N)  # 根据分割点创建颜色映射
sm = plt.cm.ScalarMappable(cmap=cmap, norm=norm)
sm.set_array([])
cbar = plt.colorbar(sm, orientation='horizontal', ticks=[1, 2, 3, 4, 5], shrink=0.4)  # 设置颜色条的标记位置
cbar.ax.set_xticklabels(['Ⅱ类', 'Ⅲ类', 'Ⅳ类', 'Ⅴ类', '劣Ⅴ类'])
cbar.set_label('水质等级', fontsize=14)

# 自定义月份显示为中文
plt.gca().set_xticklabels(['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'])

# 调整图形布局
plt.subplots_adjust(left=0.05, right=0.95, top=0.95, bottom=0.2)

# 设置图形标题
label_name = ask_station + "2023年水质等级日历热力图"
plt.title(label_name, fontsize=16)
# 保存图形到本地
# plt.savefig("calendar_heatmap.png")
# 显示图形
plt.show()

缺点比较明显 不能交互,且月份之间间隔不明显。

第一种方式 pyecharts库

代码更简洁,效果还可以,输出格式为html,可交互,逻辑更清晰。

import pandas as pd
from pyecharts import options as opts
from pyecharts.charts import Calendar

# 将日期列转换为日期类型
df['日期'] = pd.to_datetime(df['日期'])

# 确保站点评价等级是数值类型
df['站点评价等级'] = pd.to_numeric(df['站点评价等级'])

# 获取日期和评价等级数据
data = df[['日期', '站点评价等级']].values.tolist()

# 创建日历热力图
calendar = (
    Calendar()
    .add("", data, calendar_opts=opts.CalendarOpts(range_='2023'))
    .set_global_opts(
        title_opts=opts.TitleOpts(title=ask_station + "2023年水质等级日历热力图"),
        visualmap_opts=opts.VisualMapOpts(
            max_=5,
            min_=1,
            orient="horizontal",
            pos_top="230px",
            pos_left="center",
            is_piecewise=True,
            pieces=[
                {"min": 1, "max": 2, "label": "Ⅱ类", "color": "#00E500"},
                {"min": 2, "max": 3, "label": "Ⅲ类", "color": "blue"},
                {"min": 3, "max": 4, "label": "Ⅳ类", "color": "#FFA500"},
                {"min": 4, "max": 5, "label": "Ⅴ类", "color": "#FF0000"},
                {"min": 5, "max": 6, "label": "劣Ⅴ类", "color": "#800080"},
            ],           
        ),
    )
    .render("calendar_heatmap.html")
)

# 还是有改进的地方,比如根据等级的上下限自动匹配色块

小结

从图中可以看到该站点4-10月水质较差,其他月份水质为Ⅲ类及以下。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

细节处有神明

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值