多条形图上带有脊柱的多个 Y 轴

Multiple Y-axes with Spines on Multiple Bar Plot

我有一些数据想在多 Y 轴条形图上表示。目前,我只能用线图表示它们,如图 1 所示。

下面是我的代码:

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()

我想实现与下面的图 2 类似的效果,但具有多个 Y 轴,每个 Y 轴对应于各自的彩色条。感谢我能得到的任何帮助。谢谢!

Fig 2: Example of Multiple Bar Plot

  • 问题源于 matplotlib api returns 不同对象的方式,具体取决于绘图类型(例如 plot & bar 有不同的 returns)。
  • 线条数据可能是使用 Multiple Yaxis With Spines 绘制的,它不适用于 bar
  • 我给你两个选择:
    1. 用一个 y 轴绘制条形图,然后将其设置为对数刻度以补偿值范围内的变化
    2. 使用 a secondary y-axis 绘制条形图并将其设置为对数刻度。
  • 将数据保留在数据框中以使绘图更容易。

设置数据框

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()

单y轴

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