Как создать иерархические метки в matplotlib

#python #matplotlib #plot #axis-labels

#python #matplotlib #график #ось-метки

Вопрос:

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

штриховая диаграмма

это сравнивает двух конкурентов за 5 запусков. Я хочу получить метку, похожую на

 Competitor1 Competitor2      Competitor1 Competitor2
           1                            2 
  

и т.д.

Возможно ли это в matplotlib или мне придется добавлять их вручную после?

Спасибо

Мой код:

 # imports
import pandas as pd
import sys
import itertools
import os
import matplotlib as mpl
from matplotlib import pyplot as plt
import numpy as np

# axes limits
x_min = 1
y_min = 0
x_max = None
y_max = None

bar_width = 0.4

bar_offset = -bar_width

for method in methods:

    # load method's data
    data = pd.read_table(fpath, sep='t', index_col=0)

    # update x position with offset
    x = data.index   bar_offset

    # grey is always higher than black
    y_grey = data['grey']
    y_black = data['black']

    # update x-axis upper limit
    x_max = max(x) if x_max is None else max(max(x), x_max)

    # update y-axis upper limit
    if y_max is None:
        y_max = max(y_grey   y_grey)
    else:
        y_max = max(max(y_grey   y_grey), y_max)

    # plot grey and black bars
    color = 'k'
    plt.bar(x, y_grey, color=color, alpha=0.65, width=bar_width)
    plt.bar(x, y_black, color=color, alpha=1, width=bar_width)

    # update offset
    bar_offset  = bar_width   0.01


# labels and limits
xlabel = 'Classes'
plt.xlabel(xlabel)
plt.xlim(x_min - 0.6, x_max   0.6)
plt.ylim(y_min - 1, y_max   1)

# squared aspect
ax = plt.axes()
aspect = np.diff(ax.get_xlim()) / np.diff(ax.get_ylim())
ax.set_aspect(aspect)

# save figure
plt.savefig(output_fn)
plt.close()
  

Комментарии:

1. Я бы предложил добавить связанный код построения графика.

2. Акк, я забыл. Вот оно..

Ответ №1:

Я добился этого хакерским способом, но он служит цели:

штриховая диаграмма

В основном я размещаю метки самостоятельно и увеличиваю расстояние между ними и осью.

 # imports
import pandas as pd
import sys
import itertools
import os
import matplotlib as mpl
from matplotlib import pyplot as plt
import numpy as np

# increase margin
mpl.rcParams['xtick.major.pad'] = 35.

# axes limits
x_min = 1
y_min = 0
x_max = None
y_max = None

bar_width = 0.4

bar_offset = -bar_width

for method in methods:

    # load method's data
    data = pd.read_table(fpath, sep='t', index_col=0)

    # get label from data for method (not shown here)
    label = get_label(data)   

    # update x position with offset
    x = data.index   bar_offset

    # grey is always higher than black
    y_grey = data['grey']
    y_black = data['black']

    # update x-axis upper limit
    x_max = max(x) if x_max is None else max(max(x), x_max)

    # update y-axis upper limit
    if y_max is None:
        y_max = max(y_grey   y_grey)
    else:
        y_max = max(max(y_grey   y_grey), y_max)

    # plot grey and black bars
    color = 'k'
    plt.bar(x, y_grey, color=color, alpha=0.65, width=bar_width)
    plt.bar(x, y_black, color=color, alpha=1, width=bar_width)

    # put the labels
    for xx in x:
    plt.text(xx   bar_width / 2 - 0.1, -8, label, rotation=60,
             color=mpl.rcParams['xtick.color'],
             size=mpl.rcParams['xtick.labelsize'])

    # update offset
    bar_offset  = bar_width   0.01


# labels and limits
xlabel = 'Classes'
plt.xlabel(xlabel)
plt.xlim(x_min - 0.6, x_max   0.6)
plt.ylim(y_min - 1, y_max   1)

# squared aspect
ax = plt.axes()
aspect = np.diff(ax.get_xlim()) / np.diff(ax.get_ylim())
ax.set_aspect(aspect)

# save figure
plt.savefig(output_fn)
plt.close()
  

Комментарии:

1. взгляните на scipy.dendrogram

2. Спасибо @tcaswell, я попробую.