如何使时间序列轴刻度和标签与数据点匹配
Posted
技术标签:
【中文标题】如何使时间序列轴刻度和标签与数据点匹配【英文标题】:How to make the timeseries axis ticks and labels match the data points 【发布时间】:2022-01-06 23:43:19 【问题描述】:我已经通过手动设置我的 xticks 来绕过这个问题。 但是,我想了解这个“问题”背后的原因。
我有以下数据:
如您所见,我计算了我们每周广告系列的平均购物篮。 但是,如果我尝试绘制它,前几个日期会更改。
plt.figure(figsize=(16,6))
plt.plot(pd.to_datetime(avg_basket_pbm["trunc_usage_date"]), avg_basket_pbm["average_base_spend"], label="Monday Coupon Users")
plt.plot(pd.to_datetime(avg_basket_reg["TRUNC(EV.EFFECTIVE_DAY,'DD')"]), avg_basket_reg["average_base_spend"], label="Regular Coupon Users")
# plt.xticks(pd.to_datetime(avg_basket_pbm["trunc_usage_date"],format="%Y-%m-%d"), labels = avg_basket_pbm["trunc_usage_date"])
plt.title("Average Basket", weight = "bold", fontsize=14)
plt.legend()
这似乎只影响前几个日期,后面的日期保持不变。
可重现的例子:
from matplotlib import pyplot as plt
import numpy as np
import pandas as pd
dates = ['2021-10-11 00:00:00',
'2021-10-18 00:00:00',
'2021-10-25 00:00:00',
'2021-11-01 00:00:00',
'2021-11-08 00:00:00',
'2021-11-15 00:00:00',
'2021-11-22 00:00:00']
stamps = pd.to_datetime(dates)
vals = np.random.random(7)
plt.figure(figsize=(14,6))
plt.plot(stamps, vals)
【问题讨论】:
如果您正在绘制日期,刻度线在美学上是间隔开的,而不是标记您的数据。您的某些日期恰好位于审美边界上,但这是一种巧合(尝试将第 4 个日期设置为2021-11-02
,您会看到刻度没有变化)。
仅供参考:彻底回答问题非常耗时。如果您的问题已解决,请通过接受最适合您的需求的解决方案表示感谢。 ✔ 位于答案左上角的 ▲/▼ 箭头下方。如果出现更好的解决方案,则可以接受新的解决方案。如果您的声望超过 15,您也可以使用 ▲/▼ 箭头对答案的有用性进行投票。 如果解决方案无法回答问题,请发表评论。 What should I do when someone answers my question?。谢谢。
【参考方案1】:
Matplotlib 不会尝试将刻度与您的数据完全匹配,因为在大多数情况下看起来很糟糕。为了说明,我调整了您的示例并仅添加了四个数据点并强制 xticks 匹配数据:
from matplotlib import pyplot as plt
import numpy as np
import pandas as pd
dates = ['2021-10-11 00:00:00',
'2021-10-18 00:00:00',
'2021-10-25 00:00:00',
'2021-11-01 00:00:00',
'2021-11-08 00:00:00',
'2021-11-09 00:00:00', # added
'2021-11-10 00:00:00', # added
'2021-11-11 00:00:00', # added
'2021-11-12 00:00:00', # added
'2021-11-15 00:00:00',
'2021-11-22 00:00:00']
stamps = pd.to_datetime(dates)
vals = np.random.random(11)
plt.figure(figsize=(14,6))
plt.xticks(stamps, labels = dates)
plt.plot(stamps, vals)
刻度标签重叠且不可读。如果您将 plt.xticks
注释掉,matplotlib 可以“做自己的事情”,并将刻度放在它认为“合理”的地方。在这种特定情况下,它似乎是“每周一次,从每月 1 日开始”。如果您对您认为“合理”的刻度线位置有不同的意见/算法,那么您必须手动放置它们。
【讨论】:
确实有道理。但是,增加图形大小不会允许 plt 绘制“原始”刻度吗? 您可以拥有数千个数据点。一般来说,您不希望它们全部打勾。【参考方案2】: 绘制pandas.DataFrame
的正确方法是使用pandas.DataFrame.plot
,它使用matplotlib
作为默认后端
pandas
调整刻度位置和标签以防止轴拥挤
指定 xticks=
参数以使日期刻度和标签与数据框中的日期相匹配,但这可能会导致轴拥挤,使其变得不可读。
在python 3.9.7
、pandas 1.3.4
、matplotlib 3.5.0
中测试
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
dates1 = ['2021-10-11 00:00:00', '2021-10-18 00:00:00', '2021-10-25 00:00:00', '2021-11-01 00:00:00', '2021-11-08 00:00:00', '2021-12-15 00:00:00', '2021-12-22 00:00:00']
dates2 = ['2021-10-12 00:00:00', '2021-10-19 00:00:00', '2021-10-26 00:00:00', '2021-11-02 00:00:00', '2021-11-09 00:00:00', '2021-12-16 00:00:00', '2021-12-23 00:00:00']
np.random.seed(365)
vals1 = np.random.random(7) * 200
vals2 = np.random.random(7) * 200
df1 = pd.DataFrame('date1': dates1, 'val1': vals1)
df2 = pd.DataFrame('date2': dates2, 'val2': vals2)
# convert the colmun to a datetime dtype
df1.date1 = pd.to_datetime(df1.date1).dt.date
df2.date2 = pd.to_datetime(df2.date2).dt.date
# plot the dataframe
ax = df1.plot(x='date1', marker='o', figsize=(12, 5))
df2.plot(x='date2', marker='o', ax=ax)
ax.set_title("Average Basket", weight="bold", fontsize=14)
指定xticks=df1.date1
或xticks=df2.date2
,来自一个DataFrame 的所有日期都将在x 轴上。
两个 DataFrame 中的日期不相同。
ax = df1.plot(x='date1', marker='o', figsize=(12, 5))
df2.plot(x='date2', marker='o', ax=ax, xticks=df1.date1, rot=90, grid=True)
ax.set_title("Average Basket", weight="bold", fontsize=14)
将两个 DataFrame 中的日期组合起来用作xticks
# combine the dates to be used for xticks
xticks = df1.date1.tolist() + df2.date2.tolist()
# plot the dataframe
ax = df1.plot(x='date1', marker='o', figsize=(12, 5))
df2.plot(x='date2', marker='o', ax=ax, xticks=xticks, rot=90, grid=True)
ax.set_title("Average Basket", weight="bold", fontsize=14)
【讨论】:
以上是关于如何使时间序列轴刻度和标签与数据点匹配的主要内容,如果未能解决你的问题,请参考以下文章
Python,x轴标题与matplotlib中的刻度标签重叠