Сортировать гистограмму по отдельности в Matplotlib - PullRequest
3 голосов
/ 13 октября 2019

Я пытаюсь отсортировать компоненты гистограммы по отдельности для лучшей читабельности (либо в самом DataFrame), либо после того, как диаграмма построена, и я не могу понять, есть ли хороший способ сделать это.

Например, у меня есть этот словарь игроков и время, проведенное против их противников -

so_oppo_dict = {
  'Player 1': {'Opponent 1': 2.15, 'Opponent 2': 3.5333, 'Opponent 3': 3.1}, 
  'Player 2': {'Opponent 1': 2.2167, 'Opponent 2': 1.8667, 'Opponent 3': 2.3333}, 
  'Player 3': {'Opponent 1': 1.5333, 'Opponent 2': 4.3833, 'Opponent 3': 4.15}
}

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

fig, ax = plt.subplots()
ax = plt.subplot(111)
so_oppo_df.T.plot(kind="barh", stacked=True, ax=ax)
fig.tight_layout()
fig.savefig('opponents-stacked.png')

Мой результирующий график выглядит следующим образом, и каждый компонент гистограммы с накоплением отсортирован в том же порядке. Что я хотел бы сделать, так это переставить компоненты баров, чтобы отсортировать их по убыванию (так, чтобы зеленые и оранжевые столбцы располагались перед синими столбцами) - возможно ли это сделать?

enter image description here

1 Ответ

0 голосов
/ 15 октября 2019

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

x = so_oppo_df.index
indexes = np.argsort(so_oppo_df.values).T
widths = np.sort(so_oppo_df.values).T
order = -1
lefts = widths[::order].cumsum(axis=0)
lefts = np.insert(lefts, 0, np.zeros(len(lefts[0])), axis=0)

mpp_colors = dict(zip(so_oppo_df.columns, plt.cm.get_cmap("tab20c").colors))

for k, (idxs, vals) in enumerate(list(zip(indexes, widths))[::order]):
    mps = np.take(np.array(so_oppo_df.columns), idxs)
    ax1.barh(x, width=vals, left=lefts[k], color=[mpp_colors[m] for m in mps])

ax1.legend((np.take(np.array(so_oppo_df.columns), np.argsort(so_oppo_df.values)[0]))[::-1], bbox_to_anchor=(1.05, 1), loc='upper left', ncol=1)
ax1.title.set_text(f"Team Opposition - 5v5 Sorted TOI")

Horizontal Bar Chart (Sorted by Individual Values)

...