2014-05-09 3 views
2

Я пытаюсь создать горизонтальную гистограмму со столом в matplotlib. Я почти там, но не могу выровнять таблицу с графиком. То, что я получил до сих пор:Переместить положение графика в пределах графика (matplotlib)

import matplotlib 
matplotlib.use('Agg') 
import numpy as np 
import matplotlib.pyplot as plt 


# Example data 
appsol = ['llolLl', 'nnM', 'lllld bbbblnl', 'x2x', 'foobar', 'EXZ', 'Flups', 'Flaps', 'Foobar Barfooment', 'ABC', 'FABAS', 'common', 'AQT', 'Faberjak', 'simsalsa', 'LESS', 'Wermut'] 
y_pos = np.arange(len(appsol)) - .3 
y_pos_2 = np.arange(len(appsol)) - .1 
y_pos_3 = np.arange(len(appsol)) + .1 
y_pos_4 = np.arange(len(appsol)) + .3 
num_tickets = [4, 4,3,2,6,7,8,1,4,4,3,2,6,7,8,1,9] 
num_tickets_2 = [7,6,5,4,3,4,2,1,2,4,1,0,3,0,2,1,0] 
num_tickets_3 = [1,2,1,1,1,2,2,3,1,1,2,1,3,1,1,2,3] 
num_tickets_4 = [8,7,6,2,13,6,8,9,7,6,5,4,3,6,8,9,12] 

bar_width = .2 

fig = plt.figure(figsize=(20,20)) 
ax = fig.add_subplot(111) 

# correct yticks 
plt.yticks(y_pos_2, appsol) 

plt.barh(y_pos, num_tickets, bar_width, align='center', alpha=0.4, color='r') 
plt.barh(y_pos_2, num_tickets_2, bar_width, align='center', alpha=0.4, color='b') 
plt.barh(y_pos_3, num_tickets_3, bar_width, align='center', alpha=0.4, color='y') 
plt.barh(y_pos_4, num_tickets_4, bar_width, align='center', alpha=0.4, color='g') 
plt.yticks(y_pos, appsol) 
plt.xlabel('Numbers') 
plt.title('Horizontal Bar Chart with table') 

# Table 

empty_labels = ['' for a in appsol ] 
plt.yticks(y_pos_2, empty_labels) 
plt.tick_params(\ 
    axis='y',   # changes apply to the x-axis 
    which='both',  # both major and minor ticks are affected 
    left='off',  # ticks along the bottom edge are off 
    right='off',   # ticks along the top edge are off 
    labelbottom='off') 

# Adjust layout to make room for the table: 
plt.subplots_adjust(left=0.4, bottom=0.2) 

cell_text = [] 
i = len(num_tickets) - 1 
for j in num_tickets: 
    cell_text.append([num_tickets[i], num_tickets_2[i], num_tickets_3[i], num_tickets_4[i]]) 
    i -= 1 

row_lables = appsol 
column_labels = ['So Huge\nMice', 'Elephants', 'Reptiles', 'Germs'] 

the_table = ax.table(cellText=cell_text, 
     rowLabels=row_lables, 
     colLabels=column_labels, 
     loc='left') 
the_table.set_fontsize(15) 
the_table.scale(.5,5.0) 
plt.savefig('barh_graph.png') 
plt.close('all') 

Это производит enter image description here почти то, что я хочу, за исключением того, что строки таблицы не выровнены с барами графа. Поэтому мне нужен способ сдвинуть график вниз на половину строки таблицы или таблицу на половину строки таблицы. Как я могу это сделать?

+0

Являются ли предметы даже выровнены? «Вермут», похоже, находится наверху барплота, но внизу стола. –

+0

Вы правы - это было испорчено. Спасибо за указание на это. Ура для обзора кода;) Теперь это исправлено. – Isaac

+0

Я рад, что вы разобрались в своей проблеме, однако лучше всего разместить _minimal_ количество кода, необходимое для репликации вашей проблемы (и большинство проблем mpl можно воспроизвести в <20 строк), вероятно, вы нашли бы свою собственную проблему. – tacaswell

ответ

4

Я думаю, что его проще, если создать два подзаговоры и добавьте таблицу в левый подзаголовок, вместо того, чтобы вывести новый подзаговор из единого подзаголовка, который у вас есть сейчас. Если вы добавите таблицу в существующий подзаговор, вы можете использовать bbox, чтобы растянуть его от 0 до 1 (так полностью) в направлении y. Поскольку таблица имеет заголовок, установка ylim правого графика на (0, n_items) приведет к правильному выравниванию и добавлению небольшого смещения, так как барам также присваивается смещение 0,4 (смещение внешнего бара + половина барьер). Это должно работать автоматически, если количество элементов изменяется.

bar_width = .2 

fig, axs = plt.subplots(1,2, figsize=(12,6)) 
fig.subplots_adjust(wspace=0, top=1, right=1, left=0, bottom=0) 

axs[1].barh(y_pos[::-1], num_tickets[::-1], bar_width, align='center', alpha=0.4, color='r') 
axs[1].barh(y_pos_2[::-1], num_tickets_2[::-1], bar_width, align='center', alpha=0.4, color='b') 
axs[1].barh(y_pos_3[::-1], num_tickets_3[::-1], bar_width, align='center', alpha=0.4, color='y') 
axs[1].barh(y_pos_4[::-1], num_tickets_4[::-1], bar_width, align='center', alpha=0.4, color='g') 


axs[1].set_yticks([]) 
axs[1].set_xlabel('Numbers') 
axs[1].set_title('Horizontal Bar Chart with table') 
axs[1].set_ylim(0 - .4, (len(appsol)) + .4) 

cell_text = list(zip(num_tickets, num_tickets_2, num_tickets_3, num_tickets_4)) 

row_lables = appsol 
column_labels = ['So Huge\nMice', 'Elephants', 'Reptiles', 'Germs'] 

axs[0].axis('off') 

the_table = axs[0].table(cellText=cell_text, 
        rowLabels=row_lables, 
        colLabels=column_labels, 
        bbox=[0.4, 0.0, 0.6, 1.0]) 

the_table.set_fontsize(15) 

plt.savefig('barh_graph.png') 
plt.close('all') 

enter image description here

Если вы посмотрите внимательно вы можете заметить, что стержни в пределах от верхней части таблицы в нижней части, вы можете настроить их немного, чтобы сделать их запуска в центре верхней и нижней ячейкой таблицы.

+0

Прохладный, это то, что я действительно хотел. Это не только более гибко, но и выглядит лучше. – Isaac

+0

Мне на самом деле пришлось использовать 'plt.savefig ('barh_graph.png', bbox_inches = 'tight')', чтобы получить его правильно - скопировать вставку вашей версии дал мне сюжет, который заполнил всю фигуру, поэтому никакой границы не было показано, нет xlegend или title. – Isaac

+0

Вы можете сузить область, на которую покрывает подзаголовки, установив там края ближе к фигуре, например: 'top = 0.9, right = 0.9, left = 0.1, bottom = 0.1' или даже больше, в зависимости от того, что вы хотите чтобы показать на рисунке. –

1

Я нашел обходной путь: я регулирую у-границы графика:

ax.set_ylim([-.5,17.5]) 

Конечно эти числа работают только с этими размерами данных. Итак, если кто-то лучше справляется, я бы хотел его увидеть. Для Комплектность, вот расширенная версия (также изменен размер шрифта и добавил легенда):

import matplotlib 
matplotlib.use('Agg') 
import numpy as np 
import matplotlib.pyplot as plt 

# set font and size 
font = {'family' : 'Bitstream Vera Sans', 
     'size' : 18} 
matplotlib.rc('font', **font) 

# Example data 
appsol = ['llolLl', 'nnM', 'lllld bbbblnl', 'x2x', 'foobar', 'EXZ', 'Flups', 'Flaps', 'Foobar Barfooment', 'ABC', 'FABAS', 'common', 'AQT', 'Faberjak', 'simsalsa', 'LESS', 'Wermut'] 
y_pos = np.arange(len(appsol)) - .3 
y_pos_2 = np.arange(len(appsol)) - .1 
y_pos_3 = np.arange(len(appsol)) + .1 
y_pos_4 = np.arange(len(appsol)) + .3 
num_tickets = [4, 4,3,2,6,7,8,1,4,4,3,2,6,7,8,1,9] 
num_tickets_2 = [7,6,5,4,3,4,2,1,2,4,1,0,3,0,2,1,0] 
num_tickets_3 = [1,2,1,1,1,2,2,3,1,1,2,1,3,1,1,2,3] 
num_tickets_4 = [8,7,6,2,13,6,8,9,7,6,5,4,3,6,8,9,12] 

fig = plt.figure(figsize=(20,20)) 
ax = fig.add_subplot(111) 

# correct yticks 
plt.yticks(y_pos_2, appsol) 
# this aligns table and graph!!! 
ax.set_ylim([-.5,17.5]) 

labels = ['So Huge Mice', 'Elephants', 'Reptiles', 'Germs'] 
bar_width = .2 

plt.barh(y_pos, num_tickets, bar_width, align='center', alpha=0.4, color='r', label=labels[0]) 
plt.barh(y_pos_2, num_tickets_2, bar_width, align='center', alpha=0.4, color='b', label=labels[1]) 
plt.barh(y_pos_3, num_tickets_3, bar_width, align='center', alpha=0.4, color='y', label=labels[2]) 
plt.barh(y_pos_4, num_tickets_4, bar_width, align='center', alpha=0.4, color='g', label=labels[3]) 
plt.yticks(y_pos, appsol) 
plt.xlabel('Numbers') 
plt.title('Horizontal Bar Chart with table') 

# Legend 
plt.legend(loc='lower center', shadow=True) 
num_plots = 4 
x_legend = 0.3 
y_legend = -0.1 
ax.legend(loc='lower center', 
    bbox_to_anchor=(x_legend, y_legend), 
    ncol=num_plots, # we want the legend on just one line 
    shadow=True) 
# Table 

empty_labels = ['' for a in appsol ] 
plt.yticks(y_pos_2, empty_labels) 
plt.tick_params(\ 
    axis='y',   # changes apply to the x-axis 
    which='both',  # both major and minor ticks are affected 
    left='off',  # ticks along the bottom edge are off 
    right='off',   # ticks along the top edge are off 
    labelbottom='off') 

# Adjust layout to make room for the table: 
plt.subplots_adjust(left=0.4, bottom=0.1) 

cell_text = [] 
i = len(num_tickets) - 1 
for j in num_tickets: 
    cell_text.append([num_tickets[i], num_tickets_2[i], num_tickets_3[i], num_tickets_4[i]]) 
    i -= 1 

row_lables = appsol 
column_labels = ['So Huge\nMice', 'Elephants', 'Reptiles', 'Germs'] 

the_table = ax.table(cellText=cell_text, 
     rowLabels=row_lables, 
     colLabels=column_labels, 
     loc='left') 
the_table.set_fontsize(18) 
the_table.scale(.5,5.34) 

plt.savefig('barh_graph.png') 
plt.close('all') 

И это то, что он выглядит следующим образом: enter image description here

Смежные вопросы