I have data from different locations and the following code to plot rainfall and river discharge for each location separately.
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 hours
'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 3
'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 3
}
df = pd.DataFrame(data)
I would like to plot multiple graphs, as shown in the example of the image.
You can use subplots2grid
import pandas as pd
import matplotlib.pyplot as plt
def hydrograph_plot(dates, rain, river_flow, posx, posy):
# figure and subplots
ax1 = plt.subplot2grid((6,2), (posy*3, posx), colspan=1, rowspan=1)
ax2 = plt.subplot2grid((6,2), (posy*3+1, posx), colspan=1, rowspan=2, sharex=ax1)
# 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)
data = {
'Time': pd.date_range(start='2023-10-01', periods=24, freq='D'), # Time in hours
'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 3
'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 3
}
df = pd.DataFrame(data)
fig=plt.figure()
hydrograph_plot(df.Time, df.Rainfall_Loc1, df.Streamflow_Loc1, 0,0)
hydrograph_plot(df.Time, df.Rainfall_Loc2, df.Streamflow_Loc2, 1,0)
hydrograph_plot(df.Time, df.Rainfall_Loc3, df.Streamflow_Loc3, 0,1)
hydrograph_plot(df.Time, df.Rainfall_Loc4, df.Streamflow_Loc4, 1,1)
# layout and show
fig.autofmt_xdate()
plt.tight_layout()
plt.show()
(I do not argue that it is the best way to do it, with hydrograph_plot
needing to be aware of how many total plots there are. Maybe total shape could be an argument. But that is the way that left most of your code unchanged)
Note the sharex
argument, which ensure that ax1
and ax2
, even if they are, each time, just 2 among 8 plots, do share x-axis.