【问题标题】:How to label milliseconds axis with datetime labels in matplotlib如何在 matplotlib 中使用日期时间标签标记毫秒轴
【发布时间】:2021-09-17 20:30:46
【问题描述】:

我有一种时间线图。我在上面画了矩形,当时间以毫秒为单位时,这很容易做到。但随后 x 轴标签出现数字,我宁愿它们是日期。我可以用df['timestamp'] = pandas.to_datetime(df['timestamp']) 转换我的时间戳来修复x 轴标签,但是我的矩形绘图数学会中断,因为我不能从像rect = [(t - 59000, h - 0.4), (t - 59000, h + 0.4), (t, h + 0.4), (t, h - 0.4), (t - 59000, h - 0.4)]; bars.append(rect); bars = PolyCollection(bars) 这样的日期时间中减去毫秒

我认为更改轴的标记方式是最简单的。我怎样才能让它不再尝试绘制大量长数字,而是绘制漂亮的日期字符串?

我只想将 x 轴标签显示为日期时间,而不是这些难以理解的数字。

import pandas
from matplotlib import pyplot
from matplotlib.collections import PolyCollection
from matplotlib.ticker import MultipleLocator

df = pandas.read_csv('thing.csv')

vert = {"upright":1, "supine":2, "lying_left":3, "prone":4, "lying_right":5, "unknown":6}

fig, (ax1) = pyplot.subplots(1, 1, figsize=(15,5))

# first plot of positions over time
# get the computed body positions as bars
bars = []
colors = []
for i,row in df.iterrows():
    h = vert[row['body_position']]
    t = row['timestamp']
    
    rect = [(t - 59000, h - 0.4), (t - 59000, h + 0.4), (t, h + 0.4), (t, h - 0.4), (t - 59000, h - 0.4)]
    bars.append(rect)
    colors.append("C" + str(h-1))

bars = PolyCollection(bars, facecolors=colors)
ax1.add_collection(bars)

ax1.autoscale()
ax1.xaxis.set_major_locator(MultipleLocator(60000))
#ax1.set_xticklabels([''], rotation=90)
#ax1.xaxis.set_major_formatter(dates.DateFormatter("%B-%d\n%H:%M"))

ax1.set_yticks(sorted(vert.values()))
ax1.set_yticklabels(sorted(vert, key=vert.get))

pyplot.tight_layout()
pyplot.show()

以下是一些用于生成绘图的示例数据:

timestamp,incline_angle,rotation_angle,body_position
1631311140000,,,unknown
1631311200000,,,unknown
1631311260000,2.698802523069221,175.23174346257375,upright
1631311320000,3.79042308483573,167.83999245871857,upright
1631311380000,1.5175027051794074,179.61841112309935,upright
1631311440000,3.975208379737314,171.42631984353366,upright
1631311500000,1.1885374082444298,86.49027321064233,upright
1631311560000,4.810193480680129,21.462454182905063,upright
1631311620000,,,unknown
1631311680000,88.69449620162857,-178.52467261213772,supine
1631311740000,76.13842375737948,-176.28409623055694,supine
1631311800000,56.72313055674839,-171.72681198213715,supine
1631311860000,,,unknown
1631311920000,77.82676616765237,-72.18362857622509,lying_right
1631311980000,81.8046648695628,-46.69883607858903,lying_right
1631312040000,90.30495291582416,-11.324002429040227,prone
1631312100000,,,unknown
1631312160000,108.06979339334902,108.76621826399024,lying_left
1631312220000,,,unknown
1631312280000,,,unknown
1631312340000,,,unknown
1631312400000,117.55244721818904,165.87088640221413,unknown
1631312460000,0.5689364636363466,171.6313935247612,upright
1631312520000,10.566662943419471,-10.860907998962931,upright
1631312580000,24.244743971818696,-3.2077664692605854,upright
1631312640000,24.790924330066783,-5.473576795955548,upright
1631312700000,27.581635762266146,-6.965410020736653,upright

【问题讨论】:

    标签: python matplotlib


    【解决方案1】:

    好的,太好了!我能够重现您的代码,并添加了几行代码以获得您正在寻找的结果@PavelKomarov

    import pandas
    from matplotlib import pyplot
    from matplotlib.collections import PolyCollection
    from matplotlib.ticker import MultipleLocator
    import matplotlib.pyplot as plt
    
    df = pandas.read_csv('thing.csv')
    
    vert = {"upright":1, "supine":2, "lying_left":3, "prone":4, "lying_right":5, "unknown":6}
    
    fig, (ax1) = pyplot.subplots(1, 1, figsize=(15,5))
    
    # first plot of positions over time
    # get the computed body positions as bars
    bars = []
    colors = []
    for i,row in df.iterrows():
        h = vert[row['body_position']]
        t = row['timestamp']
        
        rect = [(t - 59000, h - 0.4), (t - 59000, h + 0.4), (t, h + 0.4), (t, h - 0.4), (t - 59000, h - 0.4)]
        bars.append(rect)
        colors.append("C" + str(h-1))
    
    bars = PolyCollection(bars, facecolors=colors)
    ax1.add_collection(bars)
    
    ax1.autoscale()
    ax1.xaxis.set_major_locator(MultipleLocator(60000))
    
    ax1.set_yticks(sorted(vert.values()))
    ax1.set_yticklabels(sorted(vert, key=vert.get))
    
    ax1.set_xticklabels([pd.to_datetime(x).strftime("%Y/%m/%d") for x in ax1.get_xticks()])
    plt.xticks(rotation=90)
    
    pyplot.tight_layout()
    pyplot.show()
    

    我添加的 2 行是:

    ax1.set_xticklabels([pd.to_datetime(x).strftime("%Y/%m/%d") for x in ax1.get_xticks()])
    plt.xticks(rotation=90)
    

    xaxis 上的时间戳已降至毫秒,因此我将它们格式化为 YYYY/MM/DD,您可以使用 this 更改格式。

    如果这是您要找的,请告诉我。

    【讨论】:

    • 好吧,有几件事:pandas.to_datetime()默认使用纳秒,所以你要给单位;显然,您实际上并不需要 strftime;您可以将旋转放在同一命令中;你可以直接将 get_ticks() 列表传递给 to_datetime() 。总之就是:ax1.set_xticklabels(pandas.to_datetime(ax1.get_xticks(), unit='ms'), rotation=90)
    • 太棒了!感谢@PavelKomarov 的反馈。如果您正在寻找答案,请随时接受。
    • 对未来的人也请注意:您可能关心时区,在这种情况下,to_datetime 调用变为pandas.to_datetime(ax1.get_xticks(), unit='ms').tz_localize('UTC').tz_convert('US/Mountain')
    • 我改变了对.strftime() 的看法。例如,如果您希望日期显示为更短、更整洁的%H:%M,而不是详尽的年-月-日时:分:秒时区,那么在设置刻度标签之前将日期时间转换为字符串是最简单的方式。
    【解决方案2】:

    您正在寻找的是格式化您的xaxis 你可以使用这个:

    import matplotlib.dates as mdates
    fig, ax = plt.subplots()
    myFmt = mdates.DateFormatter("%B-%d\n%H:%M")
    ax.xaxis.set_major_formatter(myFmt)
    

    然后在您的数据上绘制任何类型的图。 完整文档here。对于特定的日期时间格式代码,也可以使用this

    【讨论】:

    • 它不起作用。我已经尝试过类似的东西。我收到一个错误:File "/usr/local/lib/python3.9/site-packages/matplotlib/dates.py", line 328, in _from_ordinalf np.timedelta64(int(np.round(x * MUSECONDS_PER_DAY)), 'us')) OverflowError: int too big to convert
    • @PavelKomarov 确保您的 xaxis 是一个日期时间对象。也许这会帮助您当前的错误。 stackoverflow.com/a/61771415
    • 轴如何成为日期时间?我希望它保持数字,这样我的矩形就不会破裂。
    • @PavelKomarov 对不起。我需要看看数据是什么样的,以及一些代码来重现你的矩形断裂。祝你好运。
    • 是的,很抱歉这个凌乱的问题。现在有一个最小可行的数据示例。
    猜你喜欢
    • 2021-06-12
    • 2019-06-28
    • 1970-01-01
    • 1970-01-01
    • 2011-06-23
    • 1970-01-01
    • 2020-09-14
    • 2021-11-28
    • 1970-01-01
    相关资源
    最近更新 更多