如何从matplotlib数组中正确地绘制x个int日期值?

iq0todco  于 2023-02-09  发布在  其他
关注(0)|答案(1)|浏览(122)

我在尝试将一些日期值绘制到matplotlib并排条形图中时遇到了问题。
我首先定义我的Series x = new_df ['month'],它包含以下值:

0,2021-01-01
1,2021-02-01
2,2021-03-01
3,2021-04-01
4,2021-05-01
5,2021-06-01
6,2021-07-01
7,2021-08-01
8,2021-09-01
9,2021-10-01
10,2021-11-01
11,2021-12-01
12,2022-01-01
13,2022-02-01
14,2022-03-01
15,2022-04-01
16,2022-05-01
17,2022-06-01
18,2022-07-01
19,2022-08-01
20,2022-09-01
21,2022-10-01
22,2022-11-01

在此之后,我定义函数来绘制图形:

import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import matplotlib.dates as mdates
import numpy as np

def side_by_side_bar_chart(x, y, labels, file_name):

    width = 0.25 # set bar width
    ind = np.arange(len(x)) # Get the number of x labels
    fig, ax = plt.subplots(figsize=(10, 8))

    # Get average number in order to set labels formatting
    ymax = int(max([mean(x) for x in y]))

    plt.xticks(ind, x) # sets x labels with values in x list (months)

    # These two lines format ax labels

    dtFmt = mdates.DateFormatter('%b-%y') # define the formatting
    plt.gca().xaxis.set_major_formatter(dtFmt)

    plt.savefig("charts/"+ file_name + ".png", dpi = 300)

但是,我的x值对于所有xtick都标绘为Jan 70:
Wrong labeled x ticks
我怀疑这与格式有关,同样的问题也出现在脚本的另一个部分,我使用twin(x)来绘制一个顶部有趋势线的并排图表,结果我的值在图表中绘制错误:
Wrong plotted graph
有人知道如何修复这些错误吗?提前感谢您的帮助!
在x数组中传递日期,并在图形中相应地绘制所有值。

zbdgwd5y

zbdgwd5y1#

问题是你的"x"不是一个日期。它显然是一个字符串。所以格式化程序不能正确地解释它。
让我们试着重现你的问题(这是我前面提到的那种最小可重现性的例子):

import datetime
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import numpy as np # just to generate something to plot

# Generate a dummy set of 20 dates, starting from Mar 15 2020
dt=datetime.timedelta(days=31)
x0=[datetime.date(2020,3,1) + k*dt for k in range(20)]
x=[d.strftime("%Y-%m-%d") for d in x0] # This looks like your x: 20 strings 

# And some y to have something to plot
y=np.cumsum(np.random.normal(0,1,20)) # Don't overthink it, it is just 20 numbers :)

# Plot y vs x (x being the strings)
plt.plot(x,y)
plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%b-%y'))
plt.show()

结果

现在,解决办法很简单:x必须包含日期,而不是字符串。在我的示例中,我可以只使用plt.plot(x0,y)而不是x,因为x0是计算x所依据的日期列表。但是,如果您只有字符串可用,则可以解析它们。例如,使用[d datetime.date.fromisoformat(d) for d in x]
或者,由于您手头已经有pandaspd.to_datetime(x)(不是完全相同的日期时间,但matplotlib可以理解两者)

xx=pd.to_datetime(x)
plt.plot(xx,y)
plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%b-%y'))
plt.show()

请注意,如果我不执行任何操作,它也会停止打印所有标签。这是因为在第一种情况下,matplotlib不知道x值的任何逻辑级数。从它的Angular 来看,这些值都只是标签。而且,您不能先验地跳过标签,因为读者无法猜测被间隙隔开的两个标签之间的内容(这对我们来说似乎很明显,因为我们知道它们是日期,但matplotlib不知道,就好像x包含['red', 'green', 'yellow', 'purple', 'black', 'blue', ...]一样,你不会期望每个其他标签都被任意跳过)。
然而,现在我们将真实日期传递给matplotlib,就好像x是数值:它的值有一个逻辑级数。Matplotlib知道它,更重要的是,它知道我们知道它。因此,可以跳过一些,使图更易读:每个人都知道"3月20日"和"5月20日"之间是什么日子。
简单来说:将字符串转换为日期。

相关问题