Объединить несколько боксов в Pandas с разными диапазонами? - PullRequest
2 голосов
/ 13 октября 2019

У меня есть 2 набора данных, один из которых представляет корневую зону (мм), а другой - древесный покров (%). Я могу построить эти наборы данных рядом (как показано ниже). Используемый код был:

    fig = plt.subplots(figsize = (16,7))
    ax = [
        plt.subplot(121),
        plt.subplot(122)]
    classified_data.boxplot(grid=False, rot=90, fontsize=10, ax = ax[0])
    classified_treecover.boxplot(grid=False, rot=90, fontsize=10, ax = ax[1])
    ax[0].set_ylabel('Rootzone Storage Capacity (mm)', fontsize = '12')
    ax[1].set_ylabel('Tree Cover (%)', fontsize = '12')
    ax[0].set_title('Rootzone Storage Capacity (mm)')
    ax[1].set_title('Tree Cover (%)')

enter image description here

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

enter image description here

1 Ответ

1 голос
/ 13 октября 2019

Чтобы построить два набора данных с разными диапазонами на одном и том же рисунке, вам необходимо преобразовать все значения в соответствующие z-оценки (стандартизировать ваши данные). Вы можете использовать параметр hue в функции boxplot() в seaborn для построения двух наборов данных рядом. Рассмотрим следующий пример с набором данных 'mpg'.

   displacement  horsepower origin
0         307.0       130.0    usa
1         350.0       165.0    usa
2         318.0       150.0    usa
3         304.0       150.0    usa
4         302.0       140.0    usa

import seaborn as sns
import matplotlib.pyplot as plt

df = sns.load_dataset('mpg')

df1 = df[['displacement', 'origin']].copy()
df2 = df[['horsepower', 'origin']].copy()

# Convert values to z scores.
df1['z_score'] = df1['displacement'].\
apply(lambda x: (x - df1['displacement'].mean()) / df1['displacement'].std())
df2['z_score'] = df2['horsepower'].\
apply(lambda x: (x - df2['horsepower'].mean()) / df2['horsepower'].std())

df1.drop(['displacement'], axis= 1, inplace=True)
df2.drop(['horsepower'], axis=1, inplace=True)

# Add extra column to use it as the 'hue' parameter.
df1['value'] = 'displacement'
df2['value'] = 'horsepower'

df_cat = pd.concat([df1, df2])

ax = sns.boxplot(x='origin', y='z_score', hue='value', data=df_cat)

plt.yticks([])
ax.set_ylabel('')

# Add the left y axis.
ax1 = ax.twinx()
ax1.set_yticks(np.linspace(df['displacement'].min(), df['displacement'].max(), 5))
ax1.spines['right'].set_position(('axes', -0.2))
ax1.set_ylabel('displacement')

# Add the right y axis.
ax2 = ax.twinx()
ax2.set_yticks(np.linspace(df['horsepower'].min(), df['horsepower'].max(), 5))
ax2.spines['right'].set_position(('axes', 1))
ax2.set_ylabel('horsepower')
plt.show()

Figure

...