matplotlib 如何根据24小时轴绘制每日数据(00:00 - 23:59:59)

7bsow1i6  于 2023-04-12  发布在  其他
关注(0)|答案(1)|浏览(145)

我有一个包含date_time、date、time和VALUE1列的数据集,该列显示每个时间点的测量值。对于同一个ID,一天内有多个测量值。此外,对于一个ID,有6个不同的24小时测量值,显示在INSPECTION列中。

import random
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import matplotlib.ticker as ticker

random.seed(0)

df = pd.DataFrame({'DATE_TIME': pd.date_range('2022-11-01', '2022-11-06 23:00:00', freq='20min'),
                   'ID': [random.randrange(1, 3) for n in range(430)]})
df['VALUE1'] = [random.uniform(110, 160) for n in range(430)]
df['VALUE2'] = [random.uniform(50, 80) for n in range(430)]
df['INSPECTION'] = df['DATE_TIME'].dt.day
# df['INSPECTION'] = df['INSPECTION'].replace(6, 1)
# df['INSPECTION'] = df['INSPECTION'].replace(3, 1)

df['MODE'] = np.select([df['INSPECTION'] == 1, df['INSPECTION'].isin([2, 3])], ['A', 'B'], 'C')
df['TIME'] = df['DATE_TIME'].dt.time
df['TIME'] = df['TIME'].astype('str')

df['TIMEINTERVAL'] = df.DATE_TIME.diff().astype('timedelta64[m]')
df['TIMEINTERVAL'] = df['TIMEINTERVAL'].fillna(0)

def to_day_period(s):
    bins = ['0', '06:00:00', '13:00:00', '18:00:00', '23:00:00', '24:00:00']
    labels = ['Nighttime', 'Daytime', 'Daytime', 'Nighttime', 'Nighttime']

    return pd.cut(
        pd.to_timedelta(s),
        bins=list(map(pd.Timedelta, bins)),
        labels=labels, right=False, ordered=False
    )

df['TIME_OF_DAY'] = to_day_period(df['TIME'])
df_monthly = df

# ++++++++++++++++++++++++++++++++ sns plot ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
df_id = df[df.ID==1]
sns.set_style('darkgrid')
sns.set(rc={'figure.figsize':(14,8)})
#print(df_id.INSPECTION.unique())
ax = sns.lineplot(data=df_id, x ='TIME', y = 'VALUE1',
                  hue='INSPECTION', palette='viridis',
                  legend='full', lw=3)

ax.xaxis.set_major_locator(ticker.MultipleLocator(10))
plt.legend(bbox_to_anchor=(1, 1))
plt.ylabel('VALUE1')
plt.xlabel('TIME')
plt.show()

如何在x轴上显示一天24小时的周期而不重复时间?为了清晰地表达,x轴从00:40:00开始,然后它再次显示00:00:00。是否也有方法处理这个问题?我想在x轴上只显示从00:00:00到23:59:00的时间,而不重复时间。

slhcrj9b

slhcrj9b1#

  • 创建一列表示给定日期的总秒数,将其用作x轴,并确保给定'INSPECTION'的每个点都正确定位。
  • 给定一个特定的日子,从当前日期时间中减去午夜的那一天,然后使用.total_seconds()方法。
  • df.DATE_TIME.apply(lambda row: (row - row.replace(hour=0, minute=0, second=0, microsecond=0)).total_seconds())
  • 将刻度设置为每小时。
  • ax.xaxis.set_major_locator(tkr.MultipleLocator(3600))
  • 创建一个每小时的列表,它将被用作标签。['']是第二天'00:00'的最后一个刻度。
  • hours = [dtime(i).strftime('%H:%M') for i in range(24)] + ['']
  • 这也可以用fig, (ax1, ax2) = plt.subplots(2, 1)来完成,但这只是表面上的改变,与问题无关。
  • 有关在子图中绘图的其他详细信息,请参见How to plot in multiple subplots
  • 根据Move seaborn plot legend to a different position,海运图例应使用sns.move_legend移动,而不是plt.legend
  • 坚持使用axmatplotlib.axes.Axes的别名)的面向对象接口比交替使用axplt更一致。
    *python 3.11.2pandas 2.0.0matplotlib 3.7.1seaborn 0.12.2中测试
import seaborn as sns
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.ticker as tkr
from datetime import time as dtime

# given the existing dataframe with the DATE_TIME column as a datetime Dtype

# add a column for total seconds
df['total_seconds'] = df.DATE_TIME.apply(lambda row: (row - row.replace(hour=0, minute=0, second=0, microsecond=0)).total_seconds())

# iterate through each ID
for id_ in sorted(df.ID.unique()):
    
    # select the data for the given id_
    data = df[df.ID.eq(id_)]

    # create a figure
    fig = plt.figure(figsize=(10, 6))

    # plot the data
    ax = sns.lineplot(data=data, x ='total_seconds', y = 'VALUE1', hue='INSPECTION', palette='viridis', legend='full')
    
    # set the title and labels
    ax.set(title=f'ID: {id_}', xlabel='TIME', ylabel='VALUE1')
    
    # move the legend
    sns.move_legend(ax, bbox_to_anchor=(1.0, 0.5), loc='center left', frameon=False)

    # constrain the x-axis limits to the number of seconds in a day
    ax.set_xlim(0, 24*3600)

    # create labels for every hour in the day, and add an extra spot for the last tick position
    hours = [dtime(i).strftime('%H:%M') for i in range(24)] + ['']

    # create xticks at every hour
    ax.xaxis.set_major_locator(tkr.MultipleLocator(3600))
    
    # set the ticks and corresponding labels; cut off extra starting and ending ticks to match labels
    ax.set_xticks(ticks=ax.get_xticks()[1:-1], labels=hours, rotation=90)
    
    # remove spines
    ax.spines[['top', 'right']].set_visible(False)

df.head()

DATE_TIME  ID      VALUE1     VALUE2  INSPECTION MODE      TIME    TIMEINTERVAL  total_seconds TIME_OF_DAY
0 2022-11-01 00:00:00   2  145.003985  57.488269           1    A  00:00:00             NaT            0.0   Nighttime
1 2022-11-01 00:20:00   2  142.449613  75.888882           1    A  00:20:00 0 days 00:20:00         1200.0   Nighttime
2 2022-11-01 00:40:00   1  119.748681  70.052981           1    A  00:40:00 0 days 00:20:00         2400.0   Nighttime
3 2022-11-01 01:00:00   2  149.170848  69.793085           1    A  01:00:00 0 days 00:20:00         3600.0   Nighttime
4 2022-11-01 01:20:00   2  148.873049  56.777515           1    A  01:20:00 0 days 00:20:00         4800.0   Nighttime

相关问题