Несколько осей Y со шипами на графике с несколькими столбиками - PullRequest
1 голос
/ 14 июля 2020

У меня есть некоторые данные, которые я хотел бы представить на гистограмме с несколькими осями Y. В настоящее время я могу представить их только на линейном графике, как показано на рис. 1.

Fig 1: Current Line Plot

Below is my code:

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

def make_patch_spines_invisible(ax):
    ax.set_frame_on(True)
    ax.patch.set_visible(False)
    for sp in ax.spines.values():
        sp.set_visible(False)

dataset = pd.read_csv('Model Selection (Humidity)_csv.csv')

feature1 = dataset.iloc[:5, 2].values
feature2 = dataset.iloc[:5, 3].values
feature3 = dataset.iloc[:5, 4].values
feature4 = dataset.iloc[:5, 5].values
xaxis = dataset.iloc[:5,1].values

fig, f1 = plt.subplots(figsize= (25,15))
fig.subplots_adjust(right=0.75)

f2 = f1.twinx()
f3 = f1.twinx()
f4 = f1.twinx()

# Offset the right spine of par2.  The ticks and label have already been
# placed on the right by twinx above.
f3.spines["right"].set_position(("axes", 1.1))
f4.spines["left"].set_position(("axes", -0.1))

# Having been created by twinx, par2 has its frame off, so the line of its
# detached spine is invisible.  First, activate the frame but make the patch
# and spines invisible.
make_patch_spines_invisible(f3)
make_patch_spines_invisible(f4)

# Second, show the right spine.
f3.spines["right"].set_visible(True)
f4.spines["left"].set_visible(True)
f4.yaxis.set_label_position('left')
f4.yaxis.set_ticks_position('left')

p1, = f1.plot(xaxis, feature1, 'r-', label="Adjusted R2")
p2, = f2.plot(xaxis, feature2, 'g-', label="Max Absolute Error")
p3, = f3.plot(xaxis, feature3, 'b-', label="Max Error")
p4, = f4.plot(xaxis, feature4, 'y-', label="Root Mean Square Error")

f1.set_ylim(0, 1)
f2.set_ylim(0, 2)
f3.set_ylim(7, 25)
f4.set_ylim(1, 3)

f1.set_xlabel("Model")
f1.set_ylabel("Adjusted R2")
f2.set_ylabel("Max Absolute Error")
f3.set_ylabel("Max Error")
f4.set_ylabel("Root Mean Square Error")

f1.yaxis.label.set_color(p1.get_color())
f2.yaxis.label.set_color(p2.get_color())
f3.yaxis.label.set_color(p3.get_color())
f4.yaxis.label.set_color(p4.get_color())

tkw = dict(size=4, width=1.5)
f1.tick_params(axis='y', colors=p1.get_color(), **tkw)
f2.tick_params(axis='y', colors=p2.get_color(), **tkw)
f3.tick_params(axis='y', colors=p3.get_color(), **tkw)
f4.tick_params(axis='y', colors=p4.get_color(), **tkw)
f1.tick_params(axis='x', **tkw)

lines = [p1, p2, p3, p4]

f1.legend(lines, [l.get_label() for l in lines])

plt.show()

I would like to achieve something similar to Figure 2 below, but with multiple Y-axes each corresponding to their respective colored bars. Appreciate any help that I can get. Thanks!

Рис 2: Пример графика с несколькими столбиками

1 Ответ

0 голосов
/ 15 июля 2020
  • Проблема возникает из-за того, что api matplotlib возвращает разные объекты в зависимости от типа графика (например, plot & bar имеют разные результаты).
  • Данные линии, вероятно, были построены с использованием Multiple Yaxis With Spines , что не работает с bar
  • Я предлагаю вам два варианта:
    1. Постройте полосу с одной осью Y, а затем установите ее в логарифмическом масштабе, чтобы компенсировать изменение диапазона значений
    2. Постройте полосу, используя дополнительную ось y , и установите ее в масштабе журнала.
  • Оставьте данные в фрейме данных, чтобы упростить построение.

Настроить фрейм данных

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np

# test data
np.random.seed(10)
rows = 5
feature1 = np.random.randint(10, size=(rows,)) / 10
feature2 = np.random.randint(20, size=(rows,)) / 10
feature3 = np.random.randint(8, 25, size=(rows,))
feature4 = np.random.randint(1, 3, size=(rows,))
xaxis = range(rows)

# create dataframe
df = pd.DataFrame({'Adj. R2': feature1, 'Max Abs. Error': feature2, 'Max Error': feature3, 'RMS Error': feature4},
                  index=['SVR', 'DTR', 'RFR', 'PR', 'MLR'])

# display(df)
     Adj. R2  Max Abs. Error  Max Error  RMS Error
SVR      0.9             1.6         18          2
DTR      0.4             1.7         16          2
RFR      0.0             0.8         12          1
PR       0.1             0.9         24          1
MLR      0.9             0.0         12          2

Построение

secondary_y

ax = df.plot(secondary_y=['Max Error', 'RMS Error'], kind='bar')
ax.right_ax.set_yscale('log')
plt.show()

enter image description here

single y-axis

df.plot(kind='bar', logy=True)
plt.show()

введите описание изображения здесь

...