背景:拥有一组包含“开始时间”和“结束时间”的数据,可用于计算每条记录的持续时间。同时,每条记录还包含一个“面积”字段。为了更直观地展示每条数据的持续时间与面积,希望通过图形化方式进行可视化表达。
解决思路:设计一张时间轴图,横轴为月份(从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()