Сгруппированный блокпост с 2 осями y, 2 нанесенными на график переменными - PullRequest
0 голосов
/ 13 сентября 2018

Я пытаюсь составить коробку с 18-летним рекордом месячных осадков и частоты наводнений. каждый тик x является месяцем, и каждый тик x связан с двумя коробочными диаграммами, одним из осадков и частотой наводнений. До сих пор мне удалось построить их с помощью seaborn (см. Следующий код и изображение), однако я не знаю, как создать коробочную диаграмму с двумя осями y, что мне нужно, потому что шкалы для каждой переменной различаются.

Данные выглядят следующим образом (наибольшее значение потока_фреков в наборе данных равно 7, здесь не показано):

    Group   Rainfall    Flood_freq
0   Jan     115.679997  0
1   Jan     72.929999   0
2   Jan     39.719999   0
3   Jan     46.799999   1
4   Jan     54.989998   0
...
212 Dec     51.599998   0
213 Dec     45.359999   0
214 Dec     10.260000   0
215 Dec     52.709998   0

Это код, который я использовал:

dd=pd.melt(FBPdf,id_vars=['Group'],value_vars=['Rainfall','Flood_freq'],var_name='Data')
sns.boxplot(x='Group',y='value',data=dd,hue='Data')

Что приводит к этому:

enter image description here

С тех пор я просмотрел документацию по морскому судну, и кажется, что она не допускает 2 оси y ( Коробочный участок Seaborn с 2 осями y ). Может ли кто-нибудь предложить потенциальные альтернативы тому, чего я пытаюсь достичь? Решения по приведенной выше ссылке не относятся к этой проблеме двойных осей и сгруппированных коробочных диаграмм.

Заранее большое спасибо!

1 Ответ

0 голосов
/ 13 сентября 2018

С некоторыми поддельными данными и небольшой помощью этого урока и этого ответа , вот минимальный пример того, как добиться того, чего вы хотите, используя только numpy и matplotlib:

from matplotlib import pyplot as plt
import numpy as np

rainfall = np.random.rand((12*18))*300
floods =   np.random.rand((12*18))*2

t = np.arange(0.01, 10.0, 0.01)
data1 = np.exp(t)
data2 = np.sin(2 * np.pi * t)

fig, ax1 = plt.subplots()

months = [
    'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
    'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec',
]


ax1.set_xlabel('month')
ax1.set_ylabel('rainfall', color='tab:blue')
res1 = ax1.boxplot(
    rainfall.reshape(-1,12), positions = np.arange(12)-0.25, widths=0.4,
    patch_artist=True,
)
for element in ['boxes', 'whiskers', 'fliers', 'means', 'medians', 'caps']:
    plt.setp(res1[element], color='k')

for patch in res1['boxes']:
    patch.set_facecolor('tab:blue')



ax2 = ax1.twinx()  # instantiate a second axes that shares the same x-axis
ax2.set_ylabel('floods', color='tab:orange')
res2 = ax2.boxplot(
    floods.reshape(-1,12), positions = np.arange(12)+0.25, widths=0.4,
    patch_artist=True,
)
##from https://stackoverflow.com/a/41997865/2454357
for element in ['boxes', 'whiskers', 'fliers', 'means', 'medians', 'caps']:
    plt.setp(res2[element], color='k')

for patch in res2['boxes']:
    patch.set_facecolor('tab:orange')

ax1.set_xlim([-0.55, 11.55])
ax1.set_xticks(np.arange(12))
ax1.set_xticklabels(months)

fig.tight_layout()  # otherwise the right y-label is slightly clipped
plt.show()

Результат выглядит примерно так:

result of above code

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

...