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

问题描述 投票:0回答:1

我有一个包含 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 的时间,而不重复时间。

python matplotlib seaborn axis-labels line-plot
1个回答
1
投票
  • 创建一个表示给定日期的总秒数的列,该列将用作 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)
    完成,但这是与问题无关的外观变化。
  • 根据
    Move seaborn plot legend to a different position
    .
    A seaborn legend should be move with 
    sns.move_legend, not plt.legend
  • 使用
    ax
    matplotlib.axes.Axes
    的别名)坚持面向对象的接口比在
    ax
    plt
    之间交替更一致。
  • 测试于
    python 3.11.2
    pandas 2.0.0
    matplotlib 3.7.1
    seaborn 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
© www.soinside.com 2019 - 2024. All rights reserved.