时间趋势类可视化图表用于展示数据随时间变化的模式和趋势。以下是几种常见的时间趋势可视化图表及其特点、应用场景和Python实现方法。
- 折线图 (Line Chart)
特点:
用连续的线段连接各个时间点的数据值
简单直观,易于理解
应用场景:
展示单一或多个时间序列的整体趋势
比较不同组别的时间趋势
优点:
实现简单
能够清晰展示趋势变化
缺点:
数据点过多时可能显得杂乱
不适合展示大量时间序列
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
# 创建示例数据
dates = pd.date_range('2023-01-01', periods=30)
values = np.cumsum(np.random.randn(30))
plt.figure(figsize=(10, 5))
plt.plot(dates, values, marker='o')
plt.title('折线图示例')
plt.xlabel('日期')
plt.ylabel('值')
plt.grid(True)
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()
- 地平线图 (Horizon Chart)
特点:
将数据分层折叠显示,节省垂直空间
使用颜色深浅表示数值大小
应用场景:
需要同时比较多个时间序列
垂直空间有限时
优点:
节省空间
能够展示大量时间序列
缺点:
解读需要一定学习成本
数值精确度降低
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from matplotlib.collections import LineCollection
def horizon_plot(data, n_layers=3, figsize=(10, 5)):
fig, ax = plt.subplots(figsize=figsize)
# 计算每层的高度
layer_height = 1.0 / n_layers
y_max = data.max()
for i in range(n_layers):
# 计算当前层的y轴范围
lower = i * y_max / n_layers
upper = (i + 1) * y_max / n_layers
# 裁剪数据到当前层
layer_data = np.clip(data, lower, upper) - lower
# 创建线段集合
points = np.array([data.index, layer_data]).T.reshape(-1, 1, 2)
segments = np.concatenate([points[:-1], points[1:]], axis=1)
# 创建颜色(交替颜色)
color = 'red' if i % 2 == 0 else 'blue'
# 添加线段集合到图中
lc = LineCollection(segments, colors=color, linewidths=2)
ax.add_collection(lc)
# 添加填充
ax.fill_between(data.index, layer_data, 0, color=color, alpha=0.1)
ax.set_xlim(data.index[0], data.index[-1])
ax.set_ylim(0, y_max / n_layers)
ax.set_title('地平线图示例')
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()
# 生成示例数据
dates = pd.date_range('2023-01-01', periods=100)
values = np.random.randn(100).cumsum()
data = pd.Series(values, index=dates)
horizon_plot(data, n_layers=4)
- 河流图/流图 (Stream Graph)
特点:
围绕中心轴堆叠的面积图
产生流动的视觉效果
应用场景:
展示多个类别随时间的变化
强调整体模式和相对比例
优点:
美观,视觉冲击力强
能展示整体趋势和组成部分
缺点:
难以精确读取具体数值
类别过多时难以分辨
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from matplotlib import cm
def streamgraph(data, figsize=(12, 6)):
fig, ax = plt.subplots(figsize=figsize)
# 计算堆叠数据
stacked = data.cumsum(axis=1)
# 计算基线(居中)
baseline = stacked.sum(axis=1) / 2
# 为每个类别绘制多边形
colors = cm.viridis(np.linspace(0, 1, data.shape[1]))
for i, col in enumerate(data.columns):
# 计算上下边界
y_upper = stacked.iloc[:, i] - baseline
y_lower = stacked.iloc[:, i - 1] - baseline if i > 0 else -baseline
# 绘制多边形
ax.fill_between(data.index, y_upper, y_lower,
color=colors[i], alpha=0.7, label=col)
ax.legend(loc='upper left')
ax.set_title('河流图示例')
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()
# 生成示例数据
dates = pd.date_range('2023-01-01', periods=50)
categories = ['A', 'B', 'C', 'D']
data = pd.DataFrame(np.random.rand(50, 4) * 10, index=dates, columns=categories)
streamgraph(data)
- 瀑布图 (Waterfall Chart)
特点:
展示从初始值到最终值的变化过程
用上升和下降的柱形表示增减
应用场景:
财务分析中的利润变化
展示组成成分对整体的贡献
优点:
清晰展示变化过程
直观显示正负贡献
缺点:
主要用于离散变化分析
不适合连续时间序列
import matplotlib.pyplot as plt
def waterfall_chart(data, figsize=(10, 6)):
fig, ax = plt.subplots(figsize=figsize)
# 计算中间值
totals = [data[0]]
for i in range(1, len(data)):
totals.append(totals[i - 1] + data[i])
# 绘制柱形
bars = ax.bar(range(len(data)), data,
bottom=[0] + totals[:-1],
color=['green' if x >= 0 else 'red' for x in data])
# 添加连接线
for i in range(1, len(data)):
ax.plot([i - 0.5, i + 0.5], [totals[i - 1], totals[i - 1]], 'k-')
ax.set_title('瀑布图示例')
ax.set_xticks(range(len(data)))
ax.set_xticklabels([f'Step {i + 1}' for i in range(len(data))])
plt.tight_layout()
plt.show()
# 示例数据
data = [100, 20, -15, 30, -10, 40]
waterfall_chart(data)
- 烛形图/蜡烛图 (Candlestick Chart)
特点:
显示开盘、收盘、最高、最低价
用颜色表示涨跌
应用场景:
金融市场价格分析
波动性分析
优点:
信息丰富,一目了然
技术分析标准工具
缺点:
需要专业知识解读
数据点过多时难以阅读
import matplotlib.pyplot as plt
from matplotlib.dates import DateFormatter, DayLocator
import pandas as pd
# 示例数据
data = pd.DataFrame({
'Date': pd.date_range(start='2023-01-01', periods=20),
'Open': [100, 102, 105, 103, 107, 108, 106, 110, 112, 115,
113, 110, 108, 105, 103, 106, 104, 107, 109, 111],
'High': [102, 106, 107, 108, 110, 112, 111, 115, 117, 118,
116, 113, 110, 108, 107, 109, 108, 110, 113, 114],
'Low': [98, 101, 103, 101, 105, 106, 104, 108, 110, 113,
110, 107, 105, 103, 101, 103, 102, 105, 107, 109],
'Close': [101, 105, 103, 107, 108, 106, 110, 112, 115, 113,
110, 108, 105, 103, 106, 104, 107, 109, 111, 113]
})
# 创建图形
fig, ax = plt.subplots(figsize=(12, 6))
# 确定上涨和下跌
up = data[data['Close'] >= data['Open']]
down = data[data['Close'] < data['Open']]
# 设置宽度(以天为单位)
width = 0.6
width2 = 0.05
# 绘制上涨K线(绿色)
ax.bar(up['Date'], up['Close']-up['Open'], width, bottom=up['Open'], color='green')
ax.bar(up['Date'], up['High']-up['Close'], width2, bottom=up['Close'], color='green')
ax.bar(up['Date'], up['Low']-up['Open'], width2, bottom=up['Open'], color='green')
# 绘制下跌K线(红色)
ax.bar(down['Date'], down['Close']-down['Open'], width, bottom=down['Open'], color='red')
ax.bar(down['Date'], down['High']-down['Open'], width2, bottom=down['Open'], color='red')
ax.bar(down['Date'], down['Low']-down['Close'], width2, bottom=down['Close'], color='red')
# 设置日期格式
ax.xaxis.set_major_locator(DayLocator(interval=2))
ax.xaxis.set_major_formatter(DateFormatter("%Y-%m-%d"))
plt.xticks(rotation=45)
# 添加标题和标签
plt.title('Manual Candlestick Chart')
plt.ylabel('Price ($)')
plt.tight_layout()
plt.show()
- 面积图 (Area Chart)
特点:
折线图下的区域填充颜色
可以堆叠显示多个序
应用场景:
展示总量及其组成部分
比较多个类别的趋势
优点:
直观展示数量大小
强调变化幅度
缺点:
堆叠时下层变化影响上层
类别过多时难以分辨
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
# 生成示例数据
dates = pd.date_range('2023-01-01', periods=12)
categories = ['A', 'B', 'C']
data = pd.DataFrame(np.random.rand(12, 3)*100,
index=dates,
columns=categories).cumsum()
plt.figure(figsize=(10, 5))
plt.stackplot(data.index, data.T, labels=data.columns)
plt.legend(loc='upper left')
plt.title('堆叠面积图示例')
plt.xlabel('日期')
plt.ylabel('值')
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()
- 甘特图 (Gantt Chart)
特点:
用横条表示任务和时间跨度
显示项目进度和时间安排
应用场景:
项目管理
任务时间安排
优点:
清晰展示时间跨度
直观显示任务进度
缺点:
主要用于离散任务
不适合连续数据
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
from datetime import datetime
def gantt_chart(tasks, figsize=(10, 5)):
fig, ax = plt.subplots(figsize=figsize)
for i, (task, start, end) in enumerate(tasks):
ax.barh(i, end - start, left=start, height=0.5, align='center')
ax.set_yticks(range(len(tasks)))
ax.set_yticklabels([task[0] for task in tasks])
ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
ax.xaxis.set_major_locator(mdates.DayLocator(interval=5))
plt.xticks(rotation=45)
plt.title('甘特图示例')
plt.tight_layout()
plt.show()
# 示例数据
tasks = [
("任务A", datetime(2023, 1, 1), datetime(2023, 1, 10)),
("任务B", datetime(2023, 1, 5), datetime(2023, 1, 15)),
("任务C", datetime(2023, 1, 12), datetime(2023, 1, 20)),
("任务D", datetime(2023, 1, 18), datetime(2023, 1, 25))
]
gantt_chart(tasks)
- 日历热力图 (Calendar Heatmap)
特点:
按日历布局展示数据
用颜色表示数值大小
应用场景:
展示日级别数据
发现周期性模式
优点:
直观展示日历模式
美观
缺点:
需要足够空间
精确数值难以读取
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import matplotlib as mpl
from matplotlib.patches import Rectangle
def calendar_heatmap(data, year, cmap='viridis'):
fig, ax = plt.subplots(figsize=(10, 6))
# 创建日历网格
for month in range(1, 13):
# 计算该月第一天是星期几
first_day = pd.Timestamp(f'{year}-{month}-01')
weekday = first_day.dayofweek
# 计算该月有多少天
days_in_month = first_day.days_in_month
# 为每一天绘制方块
for day in range(1, days_in_month + 1):
date = pd.Timestamp(f'{year}-{month}-{day}')
# 计算方块位置
row = (date.dayofyear - 1 + pd.Timestamp(f'{year}-01-01').dayofweek) // 7
col = date.dayofweek
# 获取数据值
value = data.get(date, np.nan)
# 绘制方块
if not np.isnan(value):
color = plt.cm.get_cmap(cmap)(value / max(data.values()))
rect = Rectangle((col - 0.5, row - 0.5), 1, 1,
facecolor=color, edgecolor='white')
ax.add_patch(rect)
ax.set_xlim(-0.5, 6.5)
ax.set_ylim(-0.5, 53)
ax.set_xticks(range(7))
ax.set_xticklabels(['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'])
ax.set_yticks([])
ax.set_title(f'日历热力图 {year}')
plt.tight_layout()
plt.show()
# 生成示例数据
year = 2023
dates = pd.date_range(f'{year}-01-01', f'{year}-12-31')
values = np.random.rand(len(dates)) * 100
data = dict(zip(dates, values))
calendar_heatmap(data, year, cmap='YlOrRd')
总结
选择合适的时间趋势可视化图表应根据数据特点、分析目的和受众需求综合考虑。简单趋势分析可使用折线图,多序列比较可考虑地平线图或河流图,金融数据适合烛形图,而项目管理则适合甘特图。