我正在尝试在 Matplotlib 中创建子图,其中第一个图是堆积条形图,第二个图是线图。两个图应共享相同的 x 轴日期时间索引。但是,我面临一个问题,第二个图没有显示任何数据。
Economizer Economizer_plus_Mech ... Not_Mechanical OaTemp
2023-10-01 1.680672 1.680672 ... 1.680672 84.317815
2023-10-02 17.127072 5.524862 ... 1.657459 76.263536
2023-10-03 31.481481 5.092593 ... 0.000000 73.407407
这是我的绘图函数:
import matplotlib.pyplot as plt
import os
import pandas as pd
PLOTS_DIR = 'path/to/plots'
def save_mode_plot_with_oat(combined_data, title, ylabel, filename):
# Ensure the index is datetime
combined_data.index = pd.to_datetime(combined_data.index)
# Create a 2-row subplot layout, sharing the x-axis
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(12, 12), sharex=True)
# Bar plot for mode percentages on the first subplot
combined_data.iloc[:, :-1].plot(kind='bar', stacked=True, ax=ax1, colormap='viridis')
ax1.set_title(title)
ax1.set_ylabel(ylabel)
# Hide x-label on the first plot
ax1.set_xlabel('')
ax1.tick_params(axis='x', labelbottom=False) # Hide x-tick labels on the first plot
# Line plot for outside air temperature on the second subplot
ax2.plot(combined_data.index, combined_data['OaTemp'], color='red', linestyle='-', marker='o')
ax2.set_title('Average Outside Air Temperature Over Time')
ax2.set_ylabel('Average Outside Air Temperature (°F)')
ax2.set_xlabel('Date')
ax2.tick_params(axis='x', rotation=90) # Rotate x-tick labels on the second plot
ax2.grid(True)
plt.tight_layout()
plt.savefig(os.path.join(PLOTS_DIR, filename))
plt.close()
# Example call
save_mode_plot_with_oat(month_df, 'Mode Percentages and OAT', 'Percentage (%)', 'mode_oat_plot.png')
我的情节是这样的,第二个情节总是空白,我无法弄清楚。任何提示表示赞赏。
pandas
DataFrame.plot.bar
API 使用索引作为分类变量对数据进行分组,但绘图的 x 值只是 0 到类别数(负 1)。 IE。 ax1
的 x 刻度的实际值将是 0
到 31
,而标签是索引的字符串表示形式。
与此相反,
DataFrame.plot.line
API 和 matplotlib.pyplot.plot
API 将 x 刻度值的日期转换为自纪元开始(1970 年 1 月 1 日)以来的天数。
两个轴的 x 刻度的值根本不同。 所以,我们能做些什么? 手动构建其中一张图,而不是使用高级 API。 在这种情况下,我们可以通过堆叠数据框中的每一列并将它们在 x 轴上与纪元开始以来的天数对齐来构建条形图。
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib import colormaps
def save_mode_plot_with_oat(combined_data, title, ylabel, filename):
# Ensure the index is datetime, get days since epoch
combined_data.index = pd.to_datetime(combined_data.index)
epoch_days = (combined_data.index.to_series() - pd.to_datetime('1970-1-1')).dt.days
# Create a 2-row subplot layout, sharing the x-axis
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(12, 12), sharex=True)
# Bar plot for mode percentages on the first subplot
cols = combined_data.columns[:-1]
cmap = colormaps.get('viridis')
prev_y_vals = 0
# plot each column values as a bar on top of the previous bar values
for i, col in enumerate(cols):
y_vals = combined_data.loc[:, col] + prev_y_vals
ax1.bar(epoch_days, height=y_vals, bottom=prev_y_vals, c=cmap(i))
prev_y_vals = y_vals
ax1.set_title(title)
ax1.set_ylabel(ylabel)
ax1.set_xlabel('')
ax1.tick_params(axis='x', labelbottom=False)
# Line plot for outside air temperature on the second subplot
ax2.plot(combined_data.index, combined_data['OaTemp'], color='red', linestyle='-', marker='o')
ax2.set_title('Average Outside Air Temperature Over Time')
ax2.set_ylabel('Average Outside Air Temperature (°F)')
ax2.set_xlabel('Date')
ax2.tick_params(axis='x', rotation=90) # Rotate x-tick labels on the second plot
ax2.grid(True)
plt.tight_layout()
plt.savefig(os.path.join(PLOTS_DIR, filename))
plt.close()