pyecharts绘制天气热力图

pyecharts绘制天气热力图


前言

基于爬取中国气象局数据后,生成的透视表不够美观,采用excel生成报表操作重复。可以考虑使用pyecharts进行热力图生成,挂载服务器后每周生成,为其他业务预测提供参考依据。

本文主要讲解如何使用pyecharts构建并生成最终的热力图。


一、数据源

数据源:爬取中国气象局中各省份城市天气(链接)。其中101010100 为城市天气查询编码,可在网页中寻找到全部城市天气查询编码。

数据格式:需要温度带、城市、日期、最高(低)气温℃字段。日期包括去年乃至今年(即每日对应的气温都有一条去年对应的气温)。数据表格式如下:

温度带城市编码城市日期星期最高气温℃最低气温℃降雨概率%历史
0寒带101050101哈尔滨20211111NaN5-417.01
1寒带101050101哈尔滨20211112NaN4-420.01
2寒带101050101哈尔滨20211113NaN1-723.01
..............................
2911热带101310101海口202212252216NaN0
2912热带101310101海口202212262116NaN0
2913热带101310101海口202212272115NaN0


二、成果图

计算绘制当天前7天与后21天范围内的数据。

 

三、绘制步骤

1.引入库

import pandas as pd
import os,re,time,random
from pyecharts import options as opts
from pyecharts.charts import HeatMap
from pyecharts.commons.utils import JsCode

2.数据处理

path为天气数据路径。handle_data(path):读入数据后选取数据框范围,计算数值。

代码如下:

def handle_data(path):
    df=pd.read_excel(path)
    #写入时间
    d1 = 7*24*60*60
    d2 = 21*24*60*60
    t = time.time()
    date1 = int(time.strftime("%Y%m%d",time.gmtime(t-d1)))
    date2 = int(time.strftime("%Y%m%d",time.gmtime(t+d2)))
    date3 = date1 - 10000
    date4 = date2 - 10000
    df_new = df.loc[(df['日期']>=date1) & (df['日期'] <= date2),:]
    df_old = df.loc[(df['日期']>=date3) & (df['日期'] <= date4),:]
    df_new['去年最高气温℃'] = list(df_old['最高气温℃'])
    df_new['最高温差(今年-去年)'] = df_new['最高气温℃'] - df_new['去年最高气温℃']
    df_new['去年最低气温℃'] = list(df_old['最低气温℃'])
    df_new['最低温差(今年-去年)'] = df_new['最低气温℃'] - df_new['去年最低气温℃']
    return df_new

3.绘制函数

df_为计算后天气数据框,types为类型,例如绘制最高温差图,则types为数据框中的'最高温差(今年-去年)'。thermodynamic(df_,types):读入数据后,对数据进行处理。

读入后的data数据格式如下:[['1111', '哈尔滨', 5], ['1112', '哈尔滨', -4], ['1113', '哈尔滨', -1], ['1114', '哈尔滨', 1], ['1115', '哈尔滨', 2], ..., ['1206', '海口', 1], ['1207', '海口', -1], ['1208', '海口', -1], ['1209', '海口', 0]]。city列表如下:

城市温度带
2福州热带
6海口热带
.........
27长春寒带
18沈阳寒带
5哈尔滨寒带

data列表中每一个元素为['日期','城市名称','温差'],city为城市,温度带,作用是对y轴按照温度带对城市进行排序。构建两个字典,对data中的数据进行映射,日期对应于x轴(0-(len(date)-1),城市对应于y轴(0-(len(c)-1),即构建(x,y,z)。接着将温度带首次出现与城市名字相连接,并对齐,随后反转列表。

采用pyecharts开始绘制热力图即可。.add_xaxis()为x轴坐标,.add_yaxis()为设置y轴坐标,具体参数详见下文代码。

代码如下:

def thermodynamic(df_,types):
    #数据处理,为了下文中标签名字范围
    date1 = min(df_['日期'])
    date2 = max(df_['日期'])
    data = [[str(df_.iloc[i]['日期'])[4:], df_.iloc[i]['城市'], df_.iloc[i][types]] for i in range(len(df_))]
    date = [str(i)[4:] for i in list(df_.loc[df_['城市']=='北京',:]['日期'])]
    city = pd.read_excel('./city_weather.xlsx')
    l= ['寒带','温带','暖带','热带']
    city['温度带'] = city['温度带'].astype('category')
    city['温度带'].cat.reorder_categories(l, inplace=True)
    city.sort_values(['温度带','城市'], ascending=False, inplace=True)
    c = list(city['城市'])
    te = list(city['温度带'])

    #构建字典
    dict_date = {}
    for i in range(len(date)):
        dict_date[date[i]] = i

    dict_city = {}
    for i in range(len(c)):
        dict_city[c[i]] = i
    
    #将data中的数据转换
    df = [[dict_date[i], dict_city[j], int(z)] for i,j,z in data]

    #将列表中首次出现的温度带与城市相连接,并对齐四个城市。
    tep = []
    ci = []
    for i in range(len(te)-1,-1,-1):
        if te[i] not in tep:
            tep.append(te[i])
            ci.append(f'{te[i]}{(5-len(c[i]))*"—"}{c[i]}')
        else:
            ci.append(c[i])
    ci.reverse()

    im = (
        HeatMap(init_opts=opts.InitOpts(width="2075px", height="899px"))
        .add_xaxis(xaxis_data=date)
        .add_yaxis(
            series_name=types,
            #ci:y轴城市名称
            yaxis_data=ci,
            value=df,
            # 图中列表的字体设置等
            label_opts=opts.LabelOpts(
                font_size=13,
                is_show=True,
                font_style = 'normal',
                font_family = 'Times New Roman',
                color="#493D26",
                position="inside",
                horizontal_align = 'center',
                #horizontal_align="50%"
                vertical_align = 'middle'
            ),
        )
        .set_series_opts()
        .set_global_opts(
            title_opts=opts.TitleOpts(title=types),
            #工具栏,使用后不美观
            #toolbox_opts=opts.ToolboxOpts(),
            legend_opts=opts.LegendOpts(is_show=False),
            xaxis_opts=opts.AxisOpts(
                #x轴坐标倾斜,可自主设置。
                #axislabel_opts=opts.LabelOpts(rotate=-30),
                #x轴上方名称
                name=f'{date1}----{date2}',
                name_location='middle',
                #间距
                name_gap=35,
                name_textstyle_opts=opts.TextStyleOpts(
                    font_family= 'Times New Roman',
                    font_size=20,
                    color='black',
                    font_weight='bolder',
                ),
                #类目数据
                type_="category",
                position='top',
                #is_scale=True,
                splitarea_opts=opts.SplitAreaOpts(
                    is_show=True, areastyle_opts=opts.AreaStyleOpts(opacity=1)
                ),
            ),
            yaxis_opts=opts.AxisOpts(
                name='city',
                name_location='middle',
                name_gap=45,
                name_textstyle_opts=opts.TextStyleOpts(
                    font_family= 'Times New Roman',
                    font_size=20,
                    color='black',
                    font_weight='bolder',
                ),
                type_="category",
                #type_="value",
                #修改y轴标签颜色
                axislabel_opts=opts.LabelOpts(
                    is_show=True,
                    position="top",
                    color='pink',
                ),
                splitarea_opts=opts.SplitAreaOpts(
                    is_show=True, areastyle_opts=opts.AreaStyleOpts(opacity=1)
                ),
            ),
            visualmap_opts=opts.VisualMapOpts(
                range_text = [ '热','冷'],
                range_color = ['#1589FF','#38ACEC','#3BB9FF','#C6DEFF','#EBF4FA','#FBBBB9','#F9966B','#F75D59','#FF0000'],
                #range_color = ['#FF0000','#F75D59','#F9966B','#FBBBB9','#EBF4FA','#C6DEFF','#3BB9FF','#38ACEC','#1589FF'],
                type_='color',
                #颜色取值范围
                min_=min(df_[types]),
                max_=max(df_[types]),
                is_calculable=True,
                #orient="horizontal",
                orient = 'vertical',
                #pos_left="center"
                #pos_right = "right"
                pos_top = "center"
            ),
        )
    )

    '''
    # 标记线条,穿过温度带城市,使用后不美观。可在其他类型图表中使用,例如标记最高、最低,平均等。
    lst = [i for i in filter(lambda x: '带' in x, ci)]
    im.set_series_opts(
         markline_opts=opts.MarkLineOpts(
                # 标记线数据
                data=[
                    # MarkLineItem:标记线数据项
                    opts.MarkLineItem(                  
                        name=lst[0],
                        y = lst[0],
                        symbol_size = None,   
                        ),
                    opts.MarkLineItem(                  
                        name=lst[1],
                        y = lst[1],
                        symbol_size = None,   
                        ),
                    opts.MarkLineItem(                  
                        name=lst[2],
                        y = lst[2],
                        symbol_size = None,   
                        ),
                    opts.MarkLineItem(                  
                        name=lst[3],
                        y = lst[3],
                        symbol_size = None,   
                        )],
             symbol ='circle',
        label_opts=opts.LabelOpts(color="#493D26"),
        linestyle_opts=opts.LineStyleOpts(
                    color = 'red',
                    opacity = 0.6,
                    # 'solid', 'dashed', 'dotted'
                    type_ = 'dashed',
                    width = 0.5,
                )
    
            ),  
        )
    '''
    return im

4.保存

保存为图片需要使用chromedriver,并安装snapshot-selenium。运行方法、保存图片代码如下:​​​​​​​

#path:数据文件路径
df = handle_data(path)
im = thermodynamic(df,'最高温差(今年-去年)')
#输出
im.render_notebook()
#保存
im.render(f"路径.html")

#保存为图片
from snapshot_selenium import snapshot
from pyecharts.render import make_snapshot
make_snapshot(snapshot, im.render(), "test.jpeg")


总结

由于y轴为类目数据,标记线划分将会穿过数据中间,对温度带划分较不美观。可采用JsCode对y轴城市进行操作。

  • 7
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
好的,我可以为您解答关于使用 pyecharts 中的 Grid 或者 Page 以及 HeatMap 的问题。 首先,Grid 和 Page 都是 pyecharts 中的布局容器,可以将多个图表组合在一起展示。它们的区别在于,Grid 是网格布局,可以自由设置每个图表所占的行列位置和大小,而 Page 则是分页布局,每个页面只能展示一个图表,可以通过翻页来展示不同的图表。 HeatMap 是 pyecharts 中的热力图组件,可以将一组数据通过颜色的深浅来展示数据的大小或者密度分布情况。 下面是一个使用 Grid 和 HeatMap 来展示数据的示例代码: ```python from pyecharts.charts import Grid, HeatMap from pyecharts import options as opts from random import randint # 生成一组随机数据 data = [[i, j, randint(0, 50)] for i in range(24) for j in range(7)] # 创建 HeatMap 实例 heatmap = ( HeatMap() .add_xaxis(list(range(24))) .add_yaxis("weekday", list("abcdefg"), data) .set_global_opts( title_opts=opts.TitleOpts(title="HeatMap 示例"), visualmap_opts=opts.VisualMapOpts() ) ) # 创建 Grid 实例,将 HeatMap 放入其中 grid = ( Grid() .add(heatmap, grid_opts=opts.GridOpts(pos_left="10%", pos_right="10%")) ) # 展示 Grid grid.render("heatmap_grid.html") ``` 这个示例代码中,我们首先生成了一组随机数据,然后使用 HeatMap 组件将数据展示成热力图。接着,我们创建了一个 Grid 实例,并将 HeatMap 放入其中,通过设置 grid_opts 参数来控制 HeatMap 在 Grid 中的位置和大小。最后,我们将 Grid 渲染成 HTML 文件并展示出来。 希望这个示例代码可以帮助您理解如何使用 Grid 和 HeatMap。如果您有其他问题,欢迎随时提出。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

迟步彩云

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

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

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

打赏作者

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

抵扣说明:

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

余额充值