【问题标题】:Plot graph with two x label index - day and time绘制带有两个 x 标签索引的图表 - 日期和时间
【发布时间】:2021-04-06 13:57:40
【问题描述】:

我有很多按季度计算的数据(消耗与时间的关系)。我必须对这些数据进行平均,并且我希望根据一周中的天数 + 时间来显示平均值。

所以我希望同时显示日期和时间。预期的结果在 Excel 中是可能的,但我希望在 python 中使用 matplotlib(并使用数据框)。

如果您有任何想法,非常感谢! 纪尧姆

这是一个显示不错结果的代码,但我想要更好。 很抱歉,因为我是论坛的新手,所以无法直接附上图片。

import pandas as pd
import datetime
import matplotlib.pyplot as plts

columns = ["Date/Time","Value"]
new_df = pd.DataFrame(columns = columns)
Jour1 = pd.to_datetime('02/01/2021')
value = np.random.randint(100, 150, size=(672,))

for x in range(672):
    TimeStamp = Jour1
    Jour1 = Jour1 + datetime.timedelta(minutes=15)  
    new_df = new_df.append(pd.Series([TimeStamp,value[x]],  index = columns) ,ignore_index=True) 

new_df['Day of week Name'] = new_df['Date/Time'].dt.dayofweek.astype(str) + ' - '+ new_df['Date/Time'].dt.day_name()
new_df["Time"] = new_df['Date/Time'].dt.time
new_df = new_df.groupby(['Day of week Name','Time'])['Value'].sum().reset_index()
new_df['TimeShow'] = new_df['Day of week Name'] +' '+ new_df['Time'].astype(str)

fig = plt.figure(figsize=(18,10))
ax=fig.add_subplot(111)

ax.plot(new_df['TimeShow'], new_df['Value'], label="Test", linewidth = 2)
plt.xticks(['0 - Monday 00:00:00','1 - Tuesday 00:00:00','2 - Wednesday 00:00:00','3 - Thursday 00:00:00','4 - Friday 00:00:00','5 - Saturday 00:00:00','6 - Sunday 00:00:00'])
plt.show()

Image in python

Image in excel - day not in order

编辑: 感谢您的帮助,我终于找到了适合我的东西。我不知道代码是否经过优化,但它可以工作。如果需要,这里是代码:

fig = plt.figure(figsize=(18,10))
ax=fig.add_subplot(111)

date_rng = pd.date_range('2021-01-01 00:00:00','2021-01-08 00:00:00', freq='6h')
xlabels = pd.DataFrame(index=date_rng)
xlabels = xlabels.index.strftime('%H:%M').tolist()

liste_saisons =  df['Saison'].unique().tolist()
for saisons in liste_saisons :

    df_show = df.loc[(df['Saison'] == saisons)]
    df_show = df_show.groupby(['Jour Semaine Nom','Time'],as_index=False)['SUM(CORR_VALUE)'].mean()
    df_show['TimeShow'] = df_show['Jour Semaine Nom'] +' '+ df_show['Time'].astype(str)
    ax.plot(df_show.index, df_show['SUM(CORR_VALUE)'], label=saisons, linewidth = 3)
    
fig.suptitle('Evolution de la charge BT quart-horaire moyenne semaine', fontsize=20)
plt.xlabel('Jour de la semaine + Heure', fontsize=20)
plt.ylabel('Charge BT quart-horaire moyenne [MW]', fontsize = 20)
plt.rc('legend', fontsize=16)
ax.legend(loc='upper left')
plt.grid(color='k', linestyle='-.', linewidth=1)


ax.set_xticklabels(xlabels)
plt.xticks(np.arange(0, 96*7, 4*6))
plt.ylim(50,350)

xdays = df_show["Jour Semaine Nom"].tolist()
graph_pos = plt.gca().get_position()
points = np.arange(48, len(xdays), 96)
day_points = np.arange(0, len(xdays), 96)
offset = -65.0
trans = ax.get_xaxis_transform()
for i,d in enumerate(xdays):
    if i in points:
         ax.text(i, graph_pos.y0 - offset, d, ha='center',bbox=dict(facecolor='cyan', edgecolor='black', boxstyle='round'), fontsize=12)

plt.show()

Result

【问题讨论】:

  • 请参阅How to Askminimal reproducible example。 (数据图像没有帮助)。还请包括您迄今为止的尝试。
  • this previous post 有帮助吗?我认为在网上搜索“matplotlib 分层轴标签”将为您提供一些示例和想法。这绝对是可行的,但不幸的是没有一个好的开箱即用解决方案。
  • 您好,感谢 frodnar 提供的链接,我将检查。我将更改我的帖子@BigBen 抱歉。

标签: python pandas matplotlib


【解决方案1】:

这种任务有很多可能的方法,但我使用 text 和 plot 函数来处理它。为了添加第一个日期,我取了图形的大小并从 y0 值中减去偏移值来确定位置。为了添加第一个日期,我获取了图表的大小并从 y0 值中减去了一个偏移值,并且对于每个日期,我手动设置了 y1 值来定位垂直线。

PS:为了更快的回答,我会给出未完成的代码。附上图片而不是链接。在文本中附加玩具数据。这是必要的。

import pandas as pd
import numpy as np

date_rng = pd.date_range('2021-01-01','2021-03-01', freq='1h')
value = np.random.randint(100, 150, size=(1417,))
df = pd.DataFrame({'date':pd.to_datetime(date_rng),'value':value})

import matplotlib.pyplot as plt

w = 0.7
fig,ax = plt.subplots(figsize=(20,4))

ax.bar(df.date[:100].apply(lambda x:x.strftime('%Y-%m-%d %H:%M:%S')), df.value[:100], color='C0', width=w, align="center")

xlabels = df.date[:100].apply(lambda x:x.strftime('%H:%M:%S')).tolist()
xdays = df.date[:100].apply(lambda x:x.strftime('%d-%b')).tolist()
ax.set_xticklabels(xlabels, rotation=90)

graph_pos = plt.gca().get_position()
points = np.arange(12, len(xlabels), 24)
day_points = np.arange(0, len(xlabels), 24)
offset = 50.0
trans = ax.get_xaxis_transform()
for i,d in enumerate(xdays):
    if i in points:
        ax.text(i, graph_pos.y0 - offset, d, ha='center')
    if i in day_points:
        ax.plot([i, i], [0, -0.3], color='gray', transform=trans, clip_on=False)
ax.set_xlim(-1, len(xlabels))
plt.show()

【讨论】:

  • 您好,感谢您的评论。我更新了我的帖子;我无法附上图片,因为我是这个论坛的新手(抱歉)。但是我已经设置了一个代码来解释我的问题和我的第一个解决方案。我会探索你的代码,我会回来的。谢谢
猜你喜欢
  • 1970-01-01
  • 2011-06-18
  • 1970-01-01
  • 2018-06-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-02
相关资源
最近更新 更多