在Matplotlib中绘制多个直方图 - 使用颜色或并排柱形图

5
问题:在Matplotlib中绘制多个直方图时,我无法区分一个图形和另一个图形。
问题图片:** Problem **小问题:左侧标签“Count”部分超出图像。为什么?
描述:
我想绘制3个不同集合的直方图。每个集合都是由0和1组成的数组。我想要每个集合的直方图,以便检测数据集中的不平衡情况。
我已经将它们单独绘制出来了,但我希望将它们一起绘制成一个图形。
可以将条形并排绘制成不同的图形,或者甚至可以将其绘制为三维图形,但我不知道阅读或理解该图形有多容易。
现在,我想在同一图形的每侧绘制[训练]、[验证]和[测试]条形。就像这样:

I want it like this

PS:我的搜索没有返回任何我能理解的代码。另外,我希望有人检查一下我的代码是否存在任何疯狂行为。

非常感谢大家!

代码:

def generate_histogram_from_array_of_labels(Y=[], labels=[], xLabel="Class/Label", yLabel="Count", title="Histogram of Trainset"):
    plt.figure()
    plt.clf()

    colors = ["b", "r", "m", "w", "k", "g", "c", "y"]

    information = []
    for index in xrange(0, len(Y)):
        y = Y[index]

        if index > len(colors):
            color = colors[0]
        else:
            color = colors[index]

        if labels is None:
            label = "?"
        else:
            if index < len(labels):
                label = labels[index]
            else:
                label = "?"

        unique, counts = np.unique(y, return_counts=True)
        unique_count = np.empty(shape=(unique.shape[0], 2), dtype=np.uint32)

        for x in xrange(0, unique.shape[0]):
            unique_count[x, 0] = unique[x]
            unique_count[x, 1] = counts[x]

        information.append(unique_count)

        # the histogram of the data
        n, bins, patches = plt.hist(y, unique.shape[0], normed=False, facecolor=color, alpha=0.75, range=[np.min(unique), np.max(unique) + 1], label=label)

    xticks_pos = [0.5 * patch.get_width() + patch.get_xy()[0] for patch in patches]

    plt.xticks(xticks_pos, unique)

    plt.xlabel(xLabel)
    plt.ylabel(yLabel)
    plt.title(title)
    plt.grid(True)
    plt.legend()
    # plt.show()

    string_of_graphic_image = cStringIO.StringIO()

    plt.savefig(string_of_graphic_image, format='png')
    string_of_graphic_image.seek(0)

    return base64.b64encode(string_of_graphic_image.read()), information

编辑

根据hashcode的回答,这段新代码:

def generate_histogram_from_array_of_labels(Y=[], labels=[], xLabel="Class/Label", yLabel="Count", title="Histogram of Trainset"):
    plt.figure()
    plt.clf()

    colors = ["b", "r", "m", "w", "k", "g", "c", "y"]
    to_use_colors = []
    information = []


    for index in xrange(0, len(Y)):
        y = Y[index]

        if index > len(colors):
            to_use_colors.append(colors[0])
        else:
            to_use_colors.append(colors[index])

        unique, counts = np.unique(y, return_counts=True)
        unique_count = np.empty(shape=(unique.shape[0], 2), dtype=np.uint32)

        for x in xrange(0, unique.shape[0]):
            unique_count[x, 0] = unique[x]
            unique_count[x, 1] = counts[x]

        information.append(unique_count)

    unique, counts = np.unique(Y[0], return_counts=True)
    histrange = [np.min(unique), np.max(unique) + 1]
    # the histogram of the data
    n, bins, patches = plt.hist(Y, 1000, normed=False, alpha=0.75, range=histrange, label=labels)


    #xticks_pos = [0.5 * patch.get_width() + patch.get_xy()[0] for patch in patches]

    #plt.xticks(xticks_pos, unique)

    plt.xlabel(xLabel)
    plt.ylabel(yLabel)
    plt.title(title)
    plt.grid(True)
    plt.legend()

正在生产这个:

Result

-- 新编辑:
def generate_histogram_from_array_of_labels(Y=[], labels=[], xLabel="Class/Label", yLabel="Count", title="Histogram of Trainset"):
    plt.figure()
    plt.clf()

    information = []

    for index in xrange(0, len(Y)):
        y = Y[index]

        unique, counts = np.unique(y, return_counts=True)
        unique_count = np.empty(shape=(unique.shape[0], 2), dtype=np.uint32)

        for x in xrange(0, unique.shape[0]):
            unique_count[x, 0] = unique[x]
            unique_count[x, 1] = counts[x]

        information.append(unique_count)

    n, bins, patches = plt.hist(Y, normed=False, alpha=0.75, label=labels)

    plt.xticks((0.25, 0.75), (0, 1))

    plt.xlabel(xLabel)
    plt.ylabel(yLabel)
    plt.title(title)
    plt.grid(True)
    plt.legend()

现在工作了,但左侧的标签有点超出边界,我想更好地居中条形图... 我该怎么做?
结果:enter image description here

您已删除了 bins 参数,默认设置为 10。只需像这样添加一个 bins 参数 - n,bins,patches = plt.hist(Y,bins = 2,normed=False,alpha=0.75,range=histrange,label=labels) - hashcode55
你尝试将箱子设置为2了吗? - hashcode55
关于标签未显示的问题,我猜想这可能是机器特定的问题。您可以尝试调整子图...请查看http://matplotlib.org/examples/pylab_examples/subplots_adjust.html - hashcode55
是的,您可以通过设置 rcparams 来完成。从 matplotlib 中导入 rcParams - hashcode55
1
默认值为 rcParams['figure.figsize'] = (1, 1)? - KenobiBastila
显示剩余3条评论
2个回答

13

我试过并得到了这个结果。您可以在代码中更改xticks位置。您需要做的只是向plt.hist传递一个元组,再简单不过了!因此,假设您有两个0和1的列表,则需要执行以下操作:

a = np.random.randint(2, size=1000)
b = np.random.randint(2, size=1000)
plt.hist((a, b), 2, label = ("data1", "data2"))
plt.legend()
plt.xticks((0.25, 0.75), (0, 1))

输入图像描述

我尝试运行的确切代码(在将箱数更改为2后)-

a = np.random.randint(2, size=1000)
b = np.random.randint(2, size=1000)
y = [a, b]
labels = ["data1", "data2"]
generate_histogram_from_array_of_labels(Y = y, labels = labels)

我也得到了同样的结果...


1
现在看起来好像可以工作了!不过,你能帮我修复这些小问题吗?我想更好地将条形图居中于x轴标签上!另外,左侧标签超出了边界! - KenobiBastila

2
如果您的数据集长度相等,您可能可以轻松使用pandas完成此操作。因此,假设您有:
import numpy

N = 1000
train, validation, test = [numpy.random.randint(2, size=N) for _ in range(3)]
Y = [train, validation, test]

你可以简单地做
import pandas

df = pandas.DataFrame(list(zip(*Y)), columns=['Train', 'Validation', 'Test'])
df.apply(pandas.value_counts).plot.bar()

这导致了下面的图表:

automatic count graph with pandas

如果您还要导入 seaborn,它会看起来更好一些:

automatic count graph with seaborn


我需要保存这张图片..您所提供的这段代码可以实现吗? - KenobiBastila
@ScientistGirl 是的,只需像平常一样使用 savefig。 - chthonicdaemon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接