python使用matplotlib库生成持续时间图表

背景:拥有一组包含“开始时间”和“结束时间”的数据,可用于计算每条记录的持续时间。同时,每条记录还包含一个“面积”字段。为了更直观地展示每条数据的持续时间与面积,希望通过图形化方式进行可视化表达。

解决思路:设计一张时间轴图,横轴为月份(从1月至12月),纵轴按年份分组排列。每条记录绘制为一条表示持续时间的横向线段,线段长度代表持续时间,颜色深浅或色阶表示面积大小,并在每条线上标注对应的序号以便识别。最终效果如图。

代码如下:


# -*- coding: utf-8 -*-
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib import rcParams
from matplotlib.colors import Normalize, LinearSegmentedColormap
from matplotlib.ticker import MultipleLocator

# 中文显示强化配置
rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei', 'Arial Unicode MS']
rcParams['axes.unicode_minus'] = False

# 数据准备
data = {
    '序号': [],#序号数组
    '开始时间': [], #开始时间
    '结束时间': [],#结束时间
    '面积': [] #面积
}

df = pd.DataFrame(data)
df['开始时间'] = pd.to_datetime(df['开始时间'])
df['结束时间'] = pd.to_datetime(df['结束时间'])

# 计算月份位置
def calc_month_position(dt_series):
    return dt_series.dt.month + (dt_series.dt.day-1)/dt_series.dt.days_in_month

df['开始位置'] = calc_month_position(df['开始时间'])
df['结束位置'] = calc_month_position(df['结束时间'])

# 创建红色系渐变色映射
area_min, area_max = df['面积'].min(), df['面积'].max()
norm = Normalize(vmin=area_min, vmax=area_max)
cmap = LinearSegmentedColormap.from_list('red_tide', ['#FFEEEE','#CC0000'])

# 创建图表
fig, ax = plt.subplots(figsize=(15, 8))
years = range(开始年份, 结束年份)  #自己的时间
y_pos = {year: idx for idx, year in enumerate(years)}

# 绘制时间线
for idx, row in df.iterrows():
    color = cmap(norm(row['面积']))
    y = y_pos[row['开始时间'].year]
    ax.hlines(y=y, xmin=row['开始位置'], xmax=row['结束位置'], 
              colors=[color], linewidth=4, alpha=0.8)
    ax.text((row['开始位置']+row['结束位置'])/2, y+0.1, row['序号'], 
            ha='center', va='bottom', fontsize=8)

# 添加颜色条
sm = plt.cm.ScalarMappable(cmap=cmap, norm=norm)
sm.set_array([])
cbar = plt.colorbar(sm, ax=ax, pad=0.03)
cbar.set_label('面积 (平方千米)', fontsize=12)

# 坐标轴及网格设置
ax.set_yticks(list(y_pos.values()))
ax.set_yticklabels(y_pos.keys())
ax.xaxis.set_major_locator(MultipleLocator(1))
ax.set_xlim(1, 12)
ax.grid(axis='x', linestyle='--', alpha=0.5, color='#AAAAAA')
plt.xlabel('月份')
plt.tight_layout()
plt.show()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值