You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Python绘制多区域水文多面图的实现需求

使用Python绘制多区域水文多面图的实现需求

我手里有好几个区域的水文监测数据,现在已经写了一段代码可以单独画出每个区域的降雨量(倒置柱状图)和河流流量(折线图)的组合水文图,但现在想把这些区域的图整合到同一个画布上,做成类似2x2布局的多面图,这样对比起来更直观。

原有的代码和示例数据如下:

import pandas as pd
import matplotlib.pyplot as plt

def hydrograph_plot(dates, rain, river_flow):
  # figure and subplots
  fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(10, 6), sharex=True, gridspec_kw={'height_ratios': [1, 2]})

  # bar graph rainfall (inverse y axis)
  ax1.bar(dates, rain, color='blue', alpha=0.6, label='Chuva (mm)')
  ax1.set_ylabel('Rainfall (mm)', color='blue')
  ax1.set_ylim(max(rain), 0)  # y axis inverted
  ax1.set_title('Hydrograph: Rainfall at ' + rain.name + ' and Flow at ' + river_flow.name) # Concatenate colname to the title
  ax1.legend(loc='upper left')
  ax1.grid(True, linestyle='--', alpha=0.5)

  # line graph for river flow
  ax2.plot(dates, river_flow, color='green', marker='o', label='Nível do Rio (m)')
  ax2.set_xlabel('Data')
  ax2.set_ylabel('StreamFlow (m)', color='green')
  ax2.legend(loc='upper left')
  ax2.grid(True, linestyle='--', alpha=0.5)

  # layout and show
  fig.autofmt_xdate()
  plt.tight_layout()
  plt.show()


# Example data for multiple locations
data = {
    'Time': pd.date_range(start='2023-10-01', periods=24, freq='D'),  # Time in days
    'Rainfall_Loc1': [0, 2, 5, 10, 8, 4, 2, 0, 0, 1, 3, 6, 9, 7, 5, 3, 1, 0, 0, 0, 0, 0, 0, 0],  # Rainfall for Location 1
    'Streamflow_Loc1': [10, 12, 15, 50, 80, 70, 60, 50, 40, 35, 30, 25, 20, 18, 16, 14, 12, 11, 10, 10, 10, 10, 10, 10],  # Streamflow for Location 1
    'Rainfall_Loc2': [0, 1, 3, 7, 12, 10, 6, 3, 1, 0, 0, 0, 2, 4, 6, 8, 7, 5, 3, 1, 0, 0, 0, 0],  # Rainfall for Location 2
    'Streamflow_Loc2': [15, 18, 20, 60, 90, 85, 75, 65, 55, 50, 45, 40, 35, 30, 25, 20, 18, 16, 15, 15, 15, 15, 15, 15],  # Streamflow for Location 2
    'Rainfall_Loc3': [0, 0, 0, 0, 1, 2, 4, 6, 8, 10, 12, 10, 8, 6, 4, 2, 1, 0, 0, 0, 0, 0, 0, 0],  # Rainfall for Location 3
    'Streamflow_Loc3': [20, 22, 25, 70, 100, 95, 85, 75, 65, 60, 55, 50, 45, 40, 35, 30, 25, 22, 20, 20, 20, 20, 20, 20],  # Streamflow for Location 3
    'Rainfall_Loc4': [0, 5, 8, 0, 1, 3, 14, 6, 5, 20, 1, 10, 0, 16, 2, 21, 10, 0, 0, 0, 0, 0, 0, 0],  # Rainfall for Location 4
    'Streamflow_Loc4': [20, 22, 25, 70, 100, 95, 85, 75, 65, 60, 55, 50, 45, 40, 35, 30, 25, 22, 20, 20, 20, 20, 20, 20]  # Streamflow for Location 4
}

df = pd.DataFrame(data)

解决方案:修改代码实现多区域多面布局

要实现你想要的多子图布局,咱们只需要对原代码做两个关键调整,就能批量生成统一布局的多区域水文图:

import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.gridspec import GridSpec

# 修改后的绘图函数:接收外部子图对象,不再单独创建画布
def hydrograph_plot(dates, rain, river_flow, ax1, ax2):
    # 绘制降雨量柱状图(倒置Y轴)
    ax1.bar(dates, rain, color='blue', alpha=0.6, label='Chuva (mm)')
    ax1.set_ylabel('Rainfall (mm)', color='blue')
    # 处理无降雨的异常情况,避免Y轴范围错误
    ax1.set_ylim(max(rain) if max(rain) > 0 else 10, 0)
    ax1.set_title(f'Hydrograph: {rain.name} & {river_flow.name}')
    ax1.legend(loc='upper left')
    ax1.grid(True, linestyle='--', alpha=0.5)

    # 绘制河流流量折线图
    ax2.plot(dates, river_flow, color='green', marker='o', label='Nível do Rio (m)')
    ax2.set_xlabel('Data')
    ax2.set_ylabel('StreamFlow (m)', color='green')
    ax2.legend(loc='upper left')
    ax2.grid(True, linestyle='--', alpha=0.5)
    # 自动旋转X轴日期标签,避免重叠
    plt.setp(ax2.get_xticklabels(), rotation=45, ha='right')

# 加载数据
data = {
    'Time': pd.date_range(start='2023-10-01', periods=24, freq='D'),
    'Rainfall_Loc1': [0, 2, 5, 10, 8, 4, 2, 0, 0, 1, 3, 6, 9, 7, 5, 3, 1, 0, 0, 0, 0, 0, 0, 0],
    'Streamflow_Loc1': [10, 12, 15, 50, 80, 70, 60, 50, 40, 35, 30, 25, 20, 18, 16, 14, 12, 11, 10, 10, 10, 10, 10, 10],
    'Rainfall_Loc2': [0, 1, 3, 7, 12, 10, 6, 3, 1, 0, 0, 0, 2, 4, 6, 8, 7, 5, 3, 1, 0, 0, 0, 0],
    'Streamflow_Loc2': [15, 18, 20, 60, 90, 85, 75, 65, 55, 50, 45, 40, 35, 30, 25, 20, 18, 16, 15, 15, 15, 15, 15, 15],
    'Rainfall_Loc3': [0, 0, 0, 0, 1, 2, 4, 6, 8, 10, 12, 10, 8, 6, 4, 2, 1, 0, 0, 0, 0, 0, 0, 0],
    'Streamflow_Loc3': [20, 22, 25, 70, 100, 95, 85, 75, 65, 60, 55, 50, 45, 40, 35, 30, 25, 22, 20, 20, 20, 20, 20, 20],
    'Rainfall_Loc4': [0, 5, 8, 0, 1, 3, 14, 6, 5, 20, 1, 10, 0, 16, 2, 21, 10, 0, 0, 0, 0, 0, 0, 0],
    'Streamflow_Loc4': [20, 22, 25, 70, 100, 95, 85, 75, 65, 60, 55, 50, 45, 40, 35, 30, 25, 22, 20, 20, 20, 20, 20, 20]
}
df = pd.DataFrame(data)
dates = df['Time']

# 1. 规划画布布局:4个区域用2行2列的大网格,每个大格子包含上下两个子图(降雨+流量)
fig = plt.figure(figsize=(16, 12))
gs = GridSpec(4, 2, figure=fig, height_ratios=[1,2,1,2])  # 4行2列:第1/3行是降雨子图,第2/4行是流量子图

# 2. 循环批量处理每个区域
locations = ['Loc1', 'Loc2', 'Loc3', 'Loc4']
for idx, loc in enumerate(locations):
    # 获取当前区域的降雨和流量数据
    rain_col = f'Rainfall_{loc}'
    flow_col = f'Streamflow_{loc}'
    rain_data = df[rain_col]
    flow_data = df[flow_col]
    
    # 计算当前区域对应的子图位置
    row = idx * 2  # 每个区域占2行(降雨在上,流量在下)
    ax_rain = fig.add_subplot(gs[row, idx%2])
    ax_flow = fig.add_subplot(gs[row+1, idx%2], sharex=ax_rain)
    
    # 调用修改后的绘图函数绘制当前区域的图
    hydrograph_plot(dates, rain_data, flow_data, ax_rain, ax_flow)

# 调整整体布局,避免标签重叠
fig.tight_layout()
plt.subplots_adjust(hspace=0.3)  # 增加子图之间的垂直间距
plt.show()

关键修改说明

  • 绘图函数重构:去掉原函数中创建画布的逻辑,改成接收外部传入的子图对象,这样就能把图画到预先规划的网格里,实现多面布局。
  • 灵活网格布局:用GridSpec实现精准的子图划分,保持每个区域的降雨/流量子图高度比例和原代码一致。
  • 批量处理逻辑:通过循环自动匹配每个区域的列名,计算子图位置,批量生成所有区域的水文图,不用重复写代码。
  • 异常兼容:处理了某区域无降雨的情况,避免Y轴范围出现错误。

备注:内容来源于stack exchange,提问作者Caluan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 15:18:00