在matplotlib中,如何绘制多个数据集的条形图以将最小的条形放在前面?

发布于 2024-08-20 07:28:01 字数 281 浏览 2 评论 0原文

我想将多个数据集放在条形图上,并防止较小的条形被较大的条形遮挡,并且我不想抵消它们。例如,

bar(0, 1.)

bar(0, 2.)

仅显示高度为 2.0 的第二个条形,第一个条形被隐藏。有没有办法让 matplotlib 绘制顶部最小的条形?注意:我不需要堆叠条形图或在 x 方向上偏移条形图。

我可以按条形高度对所有数据集中的所有数据进行排序,并按此顺序单独绘制每个条形,但我更喜欢单独绘制每个条形,而不是依次绘制每个数据集有人知道这样做的方法吗?

非常感谢

I want to put multiple datasets on a bar graph and stop the smaller bars being obscured by the larger ones, and I don't want to offset them. For example,

bar(0, 1.)

bar(0, 2.)

only shows the second bar of height of 2.0, the first bar is hidden. Is there a way to get matplotlib to draw the bars with the smallest on top? NB I don't want a stacked bar graph or to offset the bars in x-directions.

I can order all the data, from all datasets, by bar height and plot each bar individually in this order, but I'd prefer to plot each bar individually instead plot each dataset in turn Does anyone know a way of doing this?

Many thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

葬﹪忆之殇 2024-08-27 07:28:01

我知道这是一个老问题,但我出于自己的目的遇到了它,并且因为这似乎是我一遍又一遍地做的事情,所以我为 hist 函数编写了一个包装器(这就是我将要使用的) ;对 bar 的修改应该是微不足道的):

from matplotlib import pyplot as mpl
from numpy import argsort, linspace

def hist_sorted(*args, **kwargs):
    all_ns = []
    all_patches = []

    labels = kwargs.pop('labels', None)
    if not labels:
        labels = ['data %d' % (i+1) for i in range(len(args))]
    elif len(labels) != len(args):
        raise ValueError('length of labels not equal to length of data')

    bins = kwargs.pop('bins', linspace(min(min(a) for a in args),
                                       max(max(a) for a in args),
                                       num = 11))

    for data, label in zip(args, labels):
        ns, bins, patches = mpl.hist(data, bins=bins, label=label, **kwargs)
        all_ns.append(ns)
        all_patches.append(patches)
    z_orders = -argsort(all_ns, axis=0)

    for zrow, patchrow in zip(z_orders, all_patches):
        assert len(zrow) == len(patchrow)
        for z_val, patch in zip(zrow, patchrow): 
            patch.set_zorder(z_val)

    return all_ns, bins, all_patches

这将数据集作为匿名参数,将任何标签作为关键字参数(用于图例),以及可与 hist 一起使用的任何其他关键字参数。

I know this is an old question, but I came across it for my own purposes, and since it seemed like something I'd do over and over, I put together a wrapper for the hist function (which is what I'll be using; modification to bar should be trivial):

from matplotlib import pyplot as mpl
from numpy import argsort, linspace

def hist_sorted(*args, **kwargs):
    all_ns = []
    all_patches = []

    labels = kwargs.pop('labels', None)
    if not labels:
        labels = ['data %d' % (i+1) for i in range(len(args))]
    elif len(labels) != len(args):
        raise ValueError('length of labels not equal to length of data')

    bins = kwargs.pop('bins', linspace(min(min(a) for a in args),
                                       max(max(a) for a in args),
                                       num = 11))

    for data, label in zip(args, labels):
        ns, bins, patches = mpl.hist(data, bins=bins, label=label, **kwargs)
        all_ns.append(ns)
        all_patches.append(patches)
    z_orders = -argsort(all_ns, axis=0)

    for zrow, patchrow in zip(z_orders, all_patches):
        assert len(zrow) == len(patchrow)
        for z_val, patch in zip(zrow, patchrow): 
            patch.set_zorder(z_val)

    return all_ns, bins, all_patches

This takes the datasets as anonymous arguments, and any labels as keyword arguments (for the legend), as well as any other keyword argument usable with hist.

混吃等死 2024-08-27 07:28:01

bar 方法将返回一个 matplotlib.patches.Rectangle 对象。该对象有一个 set_zorder 方法。将第一个的 zorder 设置为高于第二个会将其置于顶部。

您可以通过检查元素是否处于相同的 x 位置并根据高度进行 z 排序来“轻松”对元素的 z 顺序进行排序。

from matplotlib import pylab
pylab.bar([0, 1], [1.0, 2.0])
pylab.bar([0, 1], [2.0, 1.0])

# loop through all patch objects and collect ones at same x
all_patches = pylab.axes().patches
patch_at_x = {}
for patch in all_patches:
    if patch.get_x() not in patch_at_x: patch_at_x[patch.get_x()] = []
    patch_at_x[patch.get_x()].append(patch)

# custom sort function, in reverse order of height
def yHeightSort(i,j):
    if j.get_height() > i.get_height(): return 1
    else: return -1

# loop through sort assign z-order based on sort
for x_pos, patches in patch_at_x.iteritems():
    if len(patches) == 1: continue
    patches.sort(cmp=yHeightSort)
    [patch.set_zorder(patches.index(patch)) for patch in patches]

pylab.show()

替代文本 http://img697.imageshack.us/img697/8381/tmpp.png< /a>

The bar method will return a matplotlib.patches.Rectangle object. The object has a set_zorder method. Setting the zorder of the first one higher than the second will place it on top.

You could "easily" order the z-order of elements by checking if they are at the same x and zordering based by height.

from matplotlib import pylab
pylab.bar([0, 1], [1.0, 2.0])
pylab.bar([0, 1], [2.0, 1.0])

# loop through all patch objects and collect ones at same x
all_patches = pylab.axes().patches
patch_at_x = {}
for patch in all_patches:
    if patch.get_x() not in patch_at_x: patch_at_x[patch.get_x()] = []
    patch_at_x[patch.get_x()].append(patch)

# custom sort function, in reverse order of height
def yHeightSort(i,j):
    if j.get_height() > i.get_height(): return 1
    else: return -1

# loop through sort assign z-order based on sort
for x_pos, patches in patch_at_x.iteritems():
    if len(patches) == 1: continue
    patches.sort(cmp=yHeightSort)
    [patch.set_zorder(patches.index(patch)) for patch in patches]

pylab.show()

alt text http://img697.imageshack.us/img697/8381/tmpp.png

欢烬 2024-08-27 07:28:01

原始:

>>> from matplotlib import pylab
>>> data1 = [0.3, 0.9, 0.1]
>>> data2 = [3.0, 0.2, 0.5]
>>> colors = ['b','magenta','cyan']
>>> data_list = [data1,data2]
>>> num_bars = len(data_list)
>>> for i, d in enumerate(data_list):
...     for j,value in enumerate(sorted(d,reverse=True)):
...         c = colors[j]
...         obj_list = pylab.bar(i*0.4,value,width=0.8/num_bars,color=c)
... 

你可以按顺序绘制它们,就像这样,或者做 zorder

编辑:

我稍微修饰了一下。基本上,关键是在调用 bar 之前将每个 bar 的数据从最大到最小排序。但您可以稍后返回并执行 set_zorder 等操作。事实上,我保存了从 bar () 返回的对象,以防万一您想检查它们。

import numpy as np
from pylab import *

data = [[6.7, 1.5, 4.5], [2.0, 3.25, 5.7]]
w = 0.5
xlocations =  np.array(range(len(data)))+w
colors = ['r','b','cyan']

oL = list()
for x,d in zip(xlocations, data):
    for c,value in zip(colors, sorted(d,reverse=True)):
        b = bar(x, value, width=w, color=c)
        oL.extend(b)
show()

Original:

>>> from matplotlib import pylab
>>> data1 = [0.3, 0.9, 0.1]
>>> data2 = [3.0, 0.2, 0.5]
>>> colors = ['b','magenta','cyan']
>>> data_list = [data1,data2]
>>> num_bars = len(data_list)
>>> for i, d in enumerate(data_list):
...     for j,value in enumerate(sorted(d,reverse=True)):
...         c = colors[j]
...         obj_list = pylab.bar(i*0.4,value,width=0.8/num_bars,color=c)
... 

You can draw them in order, like this, or do the zorder

Edit:

I spiffed this up a little. Basically, the key is to sort the data for each bar from largest to smallest before calling bar. But you could go back later and do set_zorder etc. In fact, I save the objects returned from bar () just in case you wanted to inspect them.

import numpy as np
from pylab import *

data = [[6.7, 1.5, 4.5], [2.0, 3.25, 5.7]]
w = 0.5
xlocations =  np.array(range(len(data)))+w
colors = ['r','b','cyan']

oL = list()
for x,d in zip(xlocations, data):
    for c,value in zip(colors, sorted(d,reverse=True)):
        b = bar(x, value, width=w, color=c)
        oL.extend(b)
show()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文