В matplotlib.pyplot как построить два набора данных, используя чередующиеся гистограммы? - PullRequest
11 голосов
/ 26 апреля 2011

Я прохожу Подумайте Статистика , и я хотел бы сравнить несколько наборов данных визуально. Из примеров книги видно, что с помощью модуля, предоставленного автором книги, можно создать чередующуюся гистограмму с разным цветом для каждого набора данных, как получить тот же результат в pyplot?

Спасибо
Tunnuz

Ответы [ 4 ]

11 голосов
/ 15 июля 2011

В документации представлен замечательный пример / демо:

http://matplotlib.sourceforge.net/examples/api/barchart_demo.html

8 голосов
/ 26 апреля 2011

Вызовите функцию бара несколько раз, по одному для каждой серии. Вы можете контролировать левое положение баров, используя левый параметр, и вы можете использовать это для предотвращения перекрытия.

Полностью непроверенный код:

pyplot.bar( numpy.arange(10) * 2, data1, color = 'red' )
pyplot.bar( numpy.arange(10) * 2 + 1, data2, color = 'red' )

Данные2 будут отображаться со смещением вправо по сравнению с местом, в котором данные будут отображаться.

3 голосов
/ 15 сентября 2014

Я столкнулся с этой проблемой некоторое время назад и создал функцию-обертку, которая берет двумерный массив и автоматически создает из него мульти-диаграмму:

Multi-category bar chart

Код:

import matplotlib.pyplot as plt
import matplotlib.cm as cm
import operator as o

import numpy as np

dpoints = np.array([['rosetta', '1mfq', 9.97],
           ['rosetta', '1gid', 27.31],
           ['rosetta', '1y26', 5.77],
           ['rnacomposer', '1mfq', 5.55],
           ['rnacomposer', '1gid', 37.74],
           ['rnacomposer', '1y26', 5.77],
           ['random', '1mfq', 10.32],
           ['random', '1gid', 31.46],
           ['random', '1y26', 18.16]])

fig = plt.figure()
ax = fig.add_subplot(111)

def barplot(ax, dpoints):
    '''
    Create a barchart for data across different categories with
    multiple conditions for each category.

    @param ax: The plotting axes from matplotlib.
    @param dpoints: The data set as an (n, 3) numpy array
    '''

    # Aggregate the conditions and the categories according to their
    # mean values
    conditions = [(c, np.mean(dpoints[dpoints[:,0] == c][:,2].astype(float))) 
                  for c in np.unique(dpoints[:,0])]
    categories = [(c, np.mean(dpoints[dpoints[:,1] == c][:,2].astype(float))) 
                  for c in np.unique(dpoints[:,1])]

    # sort the conditions, categories and data so that the bars in
    # the plot will be ordered by category and condition
    conditions = [c[0] for c in sorted(conditions, key=o.itemgetter(1))]
    categories = [c[0] for c in sorted(categories, key=o.itemgetter(1))]

    dpoints = np.array(sorted(dpoints, key=lambda x: categories.index(x[1])))

    # the space between each set of bars
    space = 0.3
    n = len(conditions)
    width = (1 - space) / (len(conditions))

    # Create a set of bars at each position
    for i,cond in enumerate(conditions):
        indeces = range(1, len(categories)+1)
        vals = dpoints[dpoints[:,0] == cond][:,2].astype(np.float)
        pos = [j - (1 - space) / 2. + i * width for j in indeces]
        ax.bar(pos, vals, width=width, label=cond, 
               color=cm.Accent(float(i) / n))

    # Set the x-axis tick labels to be equal to the categories
    ax.set_xticks(indeces)
    ax.set_xticklabels(categories)
    plt.setp(plt.xticks()[1], rotation=90)

    # Add the axis labels
    ax.set_ylabel("RMSD")
    ax.set_xlabel("Structure")

    # Add a legend
    handles, labels = ax.get_legend_handles_labels()
    ax.legend(handles[::-1], labels[::-1], loc='upper left')

barplot(ax, dpoints)
plt.show()

Если вам интересно, что делает эта функция и какая логика стоит за ней, вот (бесстыдно саморекламируемая) ссылка на пост в блоге, описывающий ее.

2 голосов
/ 11 июня 2018

Пример кода Matplotlib для чередующихся гистограмм хорошо работает для произвольных действительных координат x (как упомянуто в @ db42).

Однако, если ваши координаты x являются категориальными значениями (как в случае словарей в связанном вопросе *1006*), преобразование из категориальных координат x в действительные координаты x является громоздким и ненужным.

Вы можете расположить два словаря рядом друг с другом, используя api matplotlib. Хитрость для построения двух гистограмм со смещением друг к другу заключается в том, чтобы установить align=edge и положительную ширину (+width) для построения одной гистограммы, тогда как отрицательную ширину (-width) для построения другой.

Пример кода, модифицированного для построения двух словарей, выглядит следующим образом:

"""
========
Barchart
========

A bar plot with errorbars and height labels on individual bars
"""
import matplotlib.pyplot as plt

# Uncomment the following line if you use ipython notebook
# %matplotlib inline

width = 0.35       # the width of the bars

men_means = {'G1': 20, 'G2': 35, 'G3': 30, 'G4': 35, 'G5': 27}
men_std = {'G1': 2, 'G2': 3, 'G3': 4, 'G4': 1, 'G5': 2}

rects1 = plt.bar(men_means.keys(), men_means.values(), -width, align='edge',
                yerr=men_std.values(), color='r', label='Men')

women_means = {'G1': 25, 'G2': 32, 'G3': 34, 'G4': 20, 'G5': 25}
women_std = {'G1': 3, 'G2': 5, 'G3': 2, 'G4': 3, 'G5': 3}

rects2 = plt.bar(women_means.keys(), women_means.values(), +width, align='edge',
                yerr=women_std.values(), color='y', label='Women')

# add some text for labels, title and axes ticks
plt.xlabel('Groups')
plt.ylabel('Scores')
plt.title('Scores by group and gender')
plt.legend()

def autolabel(rects):
    """
    Attach a text label above each bar displaying its height
    """
    for rect in rects:
        height = rect.get_height()
        plt.text(rect.get_x() + rect.get_width()/2., 1.05*height,
                '%d' % int(height),
                ha='center', va='bottom')

autolabel(rects1)
autolabel(rects2)

plt.show()

Результат:

barchart_demo.png

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...