【问题标题】:Weird behavior of barplot from python matplotlib with datetimepython matplotlib中带有日期时间的barplot的奇怪行为
【发布时间】:2019-04-23 14:21:00
【问题描述】:
import matplotlib.pyplot as plt
import datetime
x = [datetime.datetime(1943,3, 13,12,0,0),
     datetime.datetime(1943,3, 13,12,5,0),
     datetime.datetime(1943,3, 13,12,10,0),
     datetime.datetime(1943,3, 13,12,15,0),
     datetime.datetime(1943,3, 13,12,20,0),
     datetime.datetime(1943,3, 13,12,25,0),
     datetime.datetime(1943,3, 13,12,30,0),
     datetime.datetime(1943,3, 13,12,35,0)]
y = [1,2,3,4,2,1,3,4]

# plot the data out but does not provide sufficient detail on the lower    values
plt.figure()
plt.bar(x,y)

# plot the data out but ommit the datetime information
plt.figure()
plt.bar(range(0,len(x)),y)

大家好,我刚从 matplotlib 开始,从 matlab 过渡到 python。但是,我遇到了 matplotlib 的奇怪行为,因为它无法与 datetime 元素一起显示数据。 我的问题是两个条形图的输出都会产生两个不同的结果。

第一个直接将数据转换为某种连续数据,而第二个更像分类数据。有没有人遇到过和我类似的问题并且不介意分享他们的解决方法?

P/s:我试过 seaborn,它可以工作,但不知何故不能很好地用于双轴绘图。我也搜索过类似的问题,但不知何故不是这样的问题?

【问题讨论】:

    标签: python datetime matplotlib bar-chart visualize


    【解决方案1】:

    我不确定我是否会将观察到的行为称为意外。在第一种情况下,您为条形图的 x 变量提供日期,因此它将在这些日期绘制条形图。在第二种情况下,您为 x 变量提供了一些数字,因此它将绘制数字。

    由于您没有说出您真正喜欢哪一个,因此解决方案是让它们在视觉上相同。不过,各自的概念是不同的。

    import matplotlib.pyplot as plt
    from matplotlib.dates import DateFormatter
    import datetime
    x = [datetime.datetime(1943,3, 13,12,0,0),
         datetime.datetime(1943,3, 13,12,5,0),
         datetime.datetime(1943,3, 13,12,10,0),
         datetime.datetime(1943,3, 13,12,15,0),
         datetime.datetime(1943,3, 13,12,20,0),
         datetime.datetime(1943,3, 13,12,25,0),
         datetime.datetime(1943,3, 13,12,30,0),
         datetime.datetime(1943,3, 13,12,35,0)]
    y = [1,2,3,4,2,1,3,4]
    
    # plot numeric plot
    plt.figure()
    plt.bar(x,y, width=4./24/60) # 4 minutes wide bars
    plt.gca().xaxis.set_major_formatter(DateFormatter("%H:%M"))
    
    # Plot categorical plot
    plt.figure()
    plt.bar(range(0,len(x)),y, width=0.8) # 0.8 units wide bars
    plt.xticks(range(0,len(x)), [d.strftime("%H:%M") for d in x])
    
    plt.show()
    

    然而,当使用不同的数据时,概念之间的差异会更明显,

    x = [datetime.datetime(1943,3, 13,12,0,0),
         datetime.datetime(1943,3, 13,12,5,0),
         datetime.datetime(1943,3, 13,12,15,0),
         datetime.datetime(1943,3, 13,12,25,0),
         datetime.datetime(1943,3, 13,12,30,0),
         datetime.datetime(1943,3, 13,12,35,0),
         datetime.datetime(1943,3, 13,12,45,0),
         datetime.datetime(1943,3, 13,12,50,0)]
    

    【讨论】:

    • OP 的一个小补充,可以在这里找到 DateFormatter 接受的格式 (docs.python.org/3/library/…)。
    • 我认为 matlab 日期时间格式 ('HH:MM') 和 python ('%H:%M') 之间的关系在这种情况下非常明显,但无论如何都要感谢您的链接。
    • 谢谢。我猜这里的关键字是日期时间的“宽度”。我没有意识到它在确定条形是连续的还是离散的方面起作用。我想我确实对python中的日期时间格式有点困惑。再次感谢您的指出!
    • width 不参与确定轴单位。确实是x 本身决定了单位。如果这些是日期时间,则单位不同于从 0 开始的整数。
    • 我明白了。感谢您的澄清!
    【解决方案2】:

    我不确定如何解决matplotlibdatetime 的问题,但pandas 可以很好地处理datetime 对象。你可以考虑一下。例如,您可以执行以下操作:

    import pandas as pd
    df = pd.DataFrame({'date': x, 'value': y})
    df.set_index('date').plot.bar()
    plt.show()
    

    改进也很容易:

    df = pd.DataFrame({'date': x, 'value': y})
    df['date'] = df['date'].dt.time 
    df.set_index('date').plot.bar(rot=0, figsize=(10, 5), alpha=0.7)
    plt.show()
    

    【讨论】:

    • “但是 pandas 可以很好地处理 datetime 对象” - 请注意,在这种情况下,pandas 不会将 datetime 对象用作真实日期。如果在日期之间使用不相等的间距,您会看到。它们仍将在轴上等距分布。
    猜你喜欢
    • 2014-11-23
    • 1970-01-01
    • 1970-01-01
    • 2018-12-25
    • 2021-11-29
    • 2019-11-30
    • 1970-01-01
    • 1970-01-01
    • 2010-09-30
    相关资源
    最近更新 更多