如何将每日数据绘制在24小时轴上(00:00 – 23:59:59)

huangapple go评论106阅读模式
英文:

How to plot daily data against a 24 hour axis (00:00 - 23:59:59)

问题

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

  1. import random
  2. import pandas as pd
  3. import numpy as np
  4. import matplotlib.pyplot as plt
  5. import seaborn as sns
  6. import matplotlib.ticker as ticker
  7. random.seed(0)
  8. df = pd.DataFrame({'DATE_TIME': pd.date_range('2022-11-01', '2022-11-06 23:00:00', freq='20min'),
  9. 'ID': [random.randrange(1, 3) for n in range(430)]})
  10. df['VALUE1'] = [random.uniform(110, 160) for n in range(430)]
  11. df['VALUE2'] = [random.uniform(50, 80) for n in range(430)]
  12. df['INSPECTION'] = df['DATE_TIME'].dt.day
  13. df['MODE'] = np.select([df['INSPECTION'] == 1, df['INSPECTION'].isin([2, 3])], ['A', 'B'], 'C')
  14. df['TIME'] = df['DATE_TIME'].dt.time
  15. df['TIME'] = df['TIME'].astype('str')
  16. df['TIMEINTERVAL'] = df.DATE_TIME.diff().astype('timedelta64[m]')
  17. df['TIMEINTERVAL'] = df['TIMEINTERVAL'].fillna(0)
  18. def to_day_period(s):
  19. bins = ['0', '06:00:00', '13:00:00', '18:00:00', '23:00:00', '24:00:00']
  20. labels = ['Nighttime', 'Daytime', 'Daytime', 'Nighttime', 'Nighttime']
  21. return pd.cut(
  22. pd.to_timedelta(s),
  23. bins=list(map(pd.Timedelta, bins)),
  24. labels=labels, right=False, ordered=False
  25. )
  26. df['TIME_OF_DAY'] = to_day_period(df['TIME'])
  27. df_monthly = df
  28. # ++++++++++++++++++++++++++++++++ sns plot ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  29. df_id = df[df.ID==1]
  30. sns.set_style('darkgrid')
  31. sns.set(rc={'figure.figsize':(14,8)})
  32. #print(df_id.INSPECTION.unique())
  33. ax = sns.lineplot(data=df_id, x ='TIME', y = 'VALUE1',
  34. hue='INSPECTION', palette='viridis',
  35. legend='full', lw=3)
  36. ax.xaxis.set_major_locator(ticker.MultipleLocator(10))
  37. plt.legend(bbox_to_anchor=(1, 1))
  38. plt.ylabel('VALUE1')
  39. plt.xlabel('TIME')
  40. plt.show()

如何将每日数据绘制在24小时轴上(00:00 – 23:59:59)

如何在x轴上显示一个24小时的循环,而不重复显示时间?具体来说,x轴从00:40:00开始,然后再次显示00:00:00。有没有办法处理这个问题?我想在x轴上仅显示从00:00:00到23:59:00的时间,而不重复显示时间。

英文:

I have a dataset with date_time, date, time, and a VALUE1 column that shows measurement values of each time point. For the same ID, there are multiple measurements over a day. Besides, there are 6 different 24 hour measurements for an ID, which is shown in INSPECTION column.

  1. import random
  2. import pandas as pd
  3. import numpy as np
  4. import matplotlib.pyplot as plt
  5. import seaborn as sns
  6. import matplotlib.ticker as ticker
  7. random.seed(0)
  8. df = pd.DataFrame({'DATE_TIME': pd.date_range('2022-11-01', '2022-11-06 23:00:00', freq='20min'),
  9. 'ID': [random.randrange(1, 3) for n in range(430)]})
  10. df['VALUE1'] = [random.uniform(110, 160) for n in range(430)]
  11. df['VALUE2'] = [random.uniform(50, 80) for n in range(430)]
  12. df['INSPECTION'] = df['DATE_TIME'].dt.day
  13. # df['INSPECTION'] = df['INSPECTION'].replace(6, 1)
  14. # df['INSPECTION'] = df['INSPECTION'].replace(3, 1)
  15. df['MODE'] = np.select([df['INSPECTION'] == 1, df['INSPECTION'].isin([2, 3])], ['A', 'B'], 'C')
  16. df['TIME'] = df['DATE_TIME'].dt.time
  17. df['TIME'] = df['TIME'].astype('str')
  18. df['TIMEINTERVAL'] = df.DATE_TIME.diff().astype('timedelta64[m]')
  19. df['TIMEINTERVAL'] = df['TIMEINTERVAL'].fillna(0)
  20. def to_day_period(s):
  21. bins = ['0', '06:00:00', '13:00:00', '18:00:00', '23:00:00', '24:00:00']
  22. labels = ['Nighttime', 'Daytime', 'Daytime', 'Nighttime', 'Nighttime']
  23. return pd.cut(
  24. pd.to_timedelta(s),
  25. bins=list(map(pd.Timedelta, bins)),
  26. labels=labels, right=False, ordered=False
  27. )
  28. df['TIME_OF_DAY'] = to_day_period(df['TIME'])
  29. df_monthly = df
  30. # ++++++++++++++++++++++++++++++++ sns plot ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  31. df_id = df[df.ID==1]
  32. sns.set_style('darkgrid')
  33. sns.set(rc={'figure.figsize':(14,8)})
  34. #print(df_id.INSPECTION.unique())
  35. ax = sns.lineplot(data=df_id, x ='TIME', y = 'VALUE1',
  36. hue='INSPECTION', palette='viridis',
  37. legend='full', lw=3)
  38. ax.xaxis.set_major_locator(ticker.MultipleLocator(10))
  39. plt.legend(bbox_to_anchor=(1, 1))
  40. plt.ylabel('VALUE1')
  41. plt.xlabel('TIME')
  42. plt.show()

如何将每日数据绘制在24小时轴上(00:00 – 23:59:59)

How can I show a 24 hours day cycle on the x-axis without repeating the time again? To articulate, x-axis starts at 00:40:00 and then it shows 00:00:00 again. Is there a way to deal with this too? I want to show only time from 00:00:00 until 23:59:00 on the x-axis without repeating the time.

答案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) 来实现,但这只是与问题无关的外观更改。
  • 使用 sns.move_legend 移动 seaborn 图例,而不是 plt.legend,请参考将 seaborn 绘图图例移动到不同位置
  • 与在 ax 中使用面向对象的接口,即 matplotlib.axes.Axes 的别名,交替使用 axplt 相比,更一致。
  1. import seaborn as sns
  2. import pandas as pd
  3. import matplotlib.pyplot as plt
  4. import matplotlib.ticker as tkr
  5. from datetime import time as dtime
  6. # 假设已存在一个带有 DATE_TIME 列的 DataFrame,并且 DATE_TIME 列为日期时间数据类型
  7. # 添加一个总秒数的列
  8. df['total_seconds'] = df.DATE_TIME.apply(lambda row: (row - row.replace(hour=0, minute=0, second=0, microsecond=0)).total_seconds())
  9. # 遍历每个 ID
  10. for id_ in sorted(df.ID.unique()):
  11. # 选择给定 id_ 的数据
  12. data = df[df.ID.eq(id_)]
  13. # 创建一个图
  14. fig = plt.figure(figsize=(10, 6))
  15. # 绘制数据
  16. ax = sns.lineplot(data=data, x='total_seconds', y='VALUE1', hue='INSPECTION', palette='viridis', legend='full')
  17. # 设置标题和标签
  18. ax.set(title=f'ID: {id_}', xlabel='TIME', ylabel='VALUE1')
  19. # 移动图例
  20. sns.move_legend(ax, bbox_to_anchor=(1.0, 0.5), loc='center left', frameon=False)
  21. # 限制 x 轴的范围为一天中的秒数
  22. ax.set_xlim(0, 24 * 3600)
  23. # 创建一天中每小时的标签,并添加一个额外的位置用于最后的刻度
  24. hours = [dtime(i).strftime('%H:%M') for i in range(24)] + ['']
  25. # 在每小时创建 x 刻度
  26. ax.xaxis.set_major_locator(tkr.MultipleLocator(3600))
  27. # 设置刻度和对应的标签;截掉额外的起始和结束刻度以匹配标签
  28. ax.set_xticks(ticks=ax.get_xticks()[1:-1], labels=hours, rotation=90)
  29. # 移除轴线
  30. ax.spines[['top', 'right']].set_visible(False)

如何将每日数据绘制在24小时轴上(00:00 – 23:59:59)

df.head()

  1. DATE_TIME ID VALUE1 VALUE2 INSPECTION MODE TIME TIMEINTERVAL total_seconds TIME_OF_DAY
  2. 0 2022-11-01 00:00:00 2 145.003985 57.488269 1 A 00:00:00 NaT 0.0 Nighttime
  3. 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
  4. 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
  5. 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
  6. 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
英文:
  • Create a column representing the total number of seconds for a given day, which will be used as the x-axis, and will ensure every point for a given 'INSPECTION' is properly positioned.
    • Given a specific day, subtract the day at midnight from the current datetime, and use the .total_seconds() method.
    • df.DATE_TIME.apply(lambda row: (row - row.replace(hour=0, minute=0, second=0, microsecond=0)).total_seconds())
  • Set ticks to be every hour.
    • ax.xaxis.set_major_locator(tkr.MultipleLocator(3600))
  • Create a list of every hour, which will be used as the labels. [''] is for the last tick at '00:00' of the next day.
    • hours = [dtime(i).strftime('%H:%M') for i in range(24)] + ['']
  • This can also be done with fig, (ax1, ax2) = plt.subplots(2, 1), but that's a cosmetic change that's not relevant to the question.
  • A seaborn legend should be move with sns.move_legend, not plt.legend, as per Move seaborn plot legend to a different position.
  • It is more consistent to stick with the object oriented interface using ax, the alias for matplotlib.axes.Axes, than to alternate between ax and plt.
  • Tested in python 3.11.2, pandas 2.0.0, matplotlib 3.7.1, seaborn 0.12.2
  1. import seaborn as sns
  2. import pandas as pd
  3. import matplotlib.pyplot as plt
  4. import matplotlib.ticker as tkr
  5. from datetime import time as dtime
  6. # given the existing dataframe with the DATE_TIME column as a datetime Dtype
  7. # add a column for total seconds
  8. df['total_seconds'] = df.DATE_TIME.apply(lambda row: (row - row.replace(hour=0, minute=0, second=0, microsecond=0)).total_seconds())
  9. # iterate through each ID
  10. for id_ in sorted(df.ID.unique()):
  11. # select the data for the given id_
  12. data = df[df.ID.eq(id_)]
  13. # create a figure
  14. fig = plt.figure(figsize=(10, 6))
  15. # plot the data
  16. ax = sns.lineplot(data=data, x ='total_seconds', y = 'VALUE1', hue='INSPECTION', palette='viridis', legend='full')
  17. # set the title and labels
  18. ax.set(title=f'ID: {id_}', xlabel='TIME', ylabel='VALUE1')
  19. # move the legend
  20. sns.move_legend(ax, bbox_to_anchor=(1.0, 0.5), loc='center left', frameon=False)
  21. # constrain the x-axis limits to the number of seconds in a day
  22. ax.set_xlim(0, 24*3600)
  23. # create labels for every hour in the day, and add an extra spot for the last tick position
  24. hours = [dtime(i).strftime('%H:%M') for i in range(24)] + ['']
  25. # create xticks at every hour
  26. ax.xaxis.set_major_locator(tkr.MultipleLocator(3600))
  27. # set the ticks and corresponding labels; cut off extra starting and ending ticks to match labels
  28. ax.set_xticks(ticks=ax.get_xticks()[1:-1], labels=hours, rotation=90)
  29. # remove spines
  30. ax.spines[['top', 'right']].set_visible(False)

如何将每日数据绘制在24小时轴上(00:00 – 23:59:59)

df.head()

  1. DATE_TIME ID VALUE1 VALUE2 INSPECTION MODE TIME TIMEINTERVAL total_seconds TIME_OF_DAY
  2. 0 2022-11-01 00:00:00 2 145.003985 57.488269 1 A 00:00:00 NaT 0.0 Nighttime
  3. 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
  4. 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
  5. 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
  6. 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

huangapple
  • 本文由 发表于 2023年4月11日 01:08:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/75979113.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定