如何在matplotlib中创建折断的垂直条形图? [英] How to create broken vertical bar graphs in matplotlib?

查看:110
本文介绍了如何在matplotlib中创建折断的垂直条形图?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在matplotlib中创建一个损坏的垂直条形图。



为了更好地了解我想要的结果,我举了一个例子与和示例,但我似乎找不到合适的图表类型。看起来非常相似的唯一事物是 boxplot ,但这不是我想要的




  • 我宁愿不必使用图形基元手动绘制图形。

  • 我可以根据需要调整数据的形状。



PS:如果您知道一个好的库可以在另一个库中执行此操作语言(例如javascript),我也将感谢指针。

解决方案

这听起来像您有一系列的开始日期时间和结束日期时间。



在这种情况下,只需使用 bar 进行绘制即可,并告诉matplotlib轴是日期。



要获取时间,您可以利用以下事实:matplotlib的内部日期格式是浮点数,其中每个整数对应于0:当天的00。因此,要获取时间,我们可以做 times = date%1



例如(90其中的%是生成和处理日期。绘图只是对 bar 的一次调用。):

  import datetime as dt 
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl

def main() :
开始,停止= dt.datetime(2012,3,1),dt.datetime(2012,4,1)

图,ax = plt.subplots()
用于['blue','red','green']中的颜色:
开始,停止= generate_data(开始,停止)
plot_durations(开始,停止,斧头,facecolor = color,alpha = 0.5)
plt.show()

def plot_durations(开始,停止,ax = None,** kwargs):
如果ax为None:
ax = plt.gca()
#设置默认的对齐中心,除非另有指定
kwargs ['align'] = kwargs.get('align','center')

#将内容转换为matplotlib的内部日期格式at ...
开始,停止= mpl.dates.date2num(开始),mpl.dates.date2num(停止)

#将事情分解为开始日期和开始时间
start_times =开始%1
start_days =开始-start_times
duration =停止-开始
start_times + = int(starts [0])#这样我们就有一个有效的日期...

#绘制条形图
艺术家= ax.bar(开始日期,持续时间,底部=开始时间,**扭曲)

#告诉matplotlib将轴视为日期。 ..
ax.xaxis_date()
ax.yaxis_date()
ax.figure.autofmt_xdate()
返回艺术家

def generate_data(start, stop):
生成一些随机数据...
#进行一系列活动,相隔1天
starts = mpl.dates.drange(start,stop,dt .timedelta(days = 1))

#更改日期时间以使它们发生在随机时间
#请记住,在这种情况下,1.0等于1天...
开始+ = np.random.random(starts.size )

#进行一些随机的停止时间...
停止=开始+ 0.2 * np.random.random(starts.size)

#转换回datetime对象...
返回mpl.dates.num2date(开始),mpl.dates.num2date(停止)

如果__name__ =='__main__':
main()



在旁注中,对于从一天开始到第二天结束的事件,这会将y轴扩展为第二天。如果愿意,可以用其他方式处理它,但是我认为这是最简单的选择。


I'd like to create a broken vertical bar graph in matplotlib.

To give a better idea of the result I'm after, I put an example together with Balsamiq:

I've had a look at the matpltolib docs and examples but I can't seem to find the appropriate chart type to use. The only thing that looks remotely similar is the boxplot but this isn't what I need.

  • I'd rather not have to draw the graph manually with graphics primitive.
  • I can massage the data into shape as needed.

PS: If you know of a good library that does this in another language (javascript, for example), I'd be grateful for the pointer too.

解决方案

It sounds like you have a few series of start datetimes and stop datetimes.

In that case, just use bar to plot things, and tell matplotlib that the axes are dates.

To get the times, you can exploit the fact that matplotlib's internal date format is a float where each integer corresponds to 0:00 of that day. Therefore, to get the times, we can just do times = dates % 1.

As an example (90% of this is generating and manipulating dates. The plotting is just a single call to bar.):

import datetime as dt
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl

def main():
    start, stop = dt.datetime(2012,3,1), dt.datetime(2012,4,1)

    fig, ax = plt.subplots()
    for color in ['blue', 'red', 'green']:
        starts, stops = generate_data(start, stop)
        plot_durations(starts, stops, ax, facecolor=color, alpha=0.5)
    plt.show()

def plot_durations(starts, stops, ax=None, **kwargs):
    if ax is None:
        ax = plt.gca()
    # Make the default alignment center, unless specified otherwise
    kwargs['align'] = kwargs.get('align', 'center')

    # Convert things to matplotlib's internal date format...
    starts, stops = mpl.dates.date2num(starts), mpl.dates.date2num(stops)

    # Break things into start days and start times 
    start_times = starts % 1
    start_days = starts - start_times
    durations = stops - starts
    start_times += int(starts[0]) # So that we have a valid date...

    # Plot the bars
    artist = ax.bar(start_days, durations, bottom=start_times, **kwargs)

    # Tell matplotlib to treat the axes as dates...
    ax.xaxis_date()
    ax.yaxis_date()
    ax.figure.autofmt_xdate()
    return artist

def generate_data(start, stop):
    """Generate some random data..."""
    # Make a series of events 1 day apart
    starts = mpl.dates.drange(start, stop, dt.timedelta(days=1))

    # Vary the datetimes so that they occur at random times
    # Remember, 1.0 is equivalent to 1 day in this case...
    starts += np.random.random(starts.size)

    # Make some random stopping times...
    stops = starts + 0.2 * np.random.random(starts.size)

    # Convert back to datetime objects...
    return mpl.dates.num2date(starts), mpl.dates.num2date(stops)

if __name__ == '__main__':
    main()

On a side note, for events that start on one day and end on the next, this will extend the y-axis into the next day. You can handle it in other ways if you prefer, but I think this is the simplest option.

这篇关于如何在matplotlib中创建折断的垂直条形图?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆