У меня есть набор данных с date_time, date, time и столбцом VALUE1, в котором показаны значения измерений для каждой временной точки. Для одного и того же идентификатора в течение дня проводится несколько измерений. Кроме того, есть 6 различных 24-часовых измерений для ID, которые показаны в колонке 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()
Как я могу показать 24-часовой дневной цикл на оси X, не повторяя время снова? Чтобы сформулировать, ось X начинается с 00:40:00, а затем снова показывает 00:00:00. Есть ли способ справиться с этим тоже? Я хочу показать только время с 00:00:00 до 23:59:00 по оси x без повторения времени.
'INSPECTION'
.
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)
, но это косметическое изменение, не имеющее отношения к вопросу.
sns.move_legend
, а не 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