Как удалить один элемент в подзаголовке (сетку фасетов seaborn), сохраняя при этом порядок в другом?

#python #matplotlib #seaborn

Вопрос:

Я пытаюсь удалить один xticks (один столбец на категориальной оси) из графика сетки фасеток Seaborn. Я также не уверен, как сохранить расстояние между каждым тиком одинаковым между подзаголовками.
Картинка стоит тысячи слов, смотрите картинки ниже:

Исходное изображение Идеальным результатом было бы: Как это должно выглядеть

 # Testing code
df = pd.DataFrame()
df['Value'] = np.random.rand(100)
df['Cat1']  = np.random.choice(['yes', 'no', 'maybe'], 100)
df['Cat2']  = np.random.choice(['Blue', 'Red'], 100)

df = df[~((df.Cat1 == 'maybe') amp; (df.Cat2 == 'Red'))]
g = sns.catplot(
    data=df,
    x='Cat1',
    y='Value',
    col='Cat2',
    col_order=['Red', 'Blue'],
    order=['yes', 'no', 'maybe'],
    sharex=False,
    color='black')
 

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

Какие-нибудь советы? Спасибо!

Ответ №1:

Подход, который я придумал, состоит в том, чтобы заменить «возможно» в метке галочки первого подзаголовка пустым и переместить положение второго подзаголовка влево, взяв координаты второго и вычитая значение смещения. По какой-то причине высота второго подзаголовка изменилась, поэтому я вручную добавил корректирующее значение.

 g = sns.catplot(
    data=df,
    x='Cat1',
    y='Value',
    col='Cat2',
    col_order=['Red', 'Blue'],
    order=['yes', 'no', 'maybe'],
    sharex=False,
    color='black')

labels = g.fig.axes[0].get_xticklabels()
print(labels)
g.fig.axes[0].set_xticklabels(['yes','no',''])
g_pos2 = g.fig.axes[1].get_position()
print(g_pos2)
offset = 0.095
g.fig.axes[1].set_position([g_pos2.x0 - offset, g_pos2.y0, g_pos2.x1 - g_pos2.x0, g_pos2.y1 - 0.11611])
print(g.fig.axes[1].get_position())
 

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

Комментарии:

1. Спасибо! это работает довольно хорошо, хотя я бы хотел, чтобы нам не понадобился такой взлом.

2. используя это, мы должны быть осторожны, хотя, так как он изменяет только имя xtickslabel, он не перемещает данные над ним

Ответ №2:

На самом деле я нашел обходной путь, который является более общим, чем предыдущий ответ.

 df = pd.DataFrame()
df['Value'] = np.random.rand(100)
df['Cat1'] = np.random.choice(['yes', 'no', 'maybe'], 100)
df['Cat2'] = np.random.choice(['Blue', 'Red'], 100)
cat_ordered = ['yes', 'no', 'maybe']

# Set to categorical
df.loc[:, 'Cat1'] = df.Cat1.astype('category').cat.set_categories(cat_ordered)
# Reorder dataframe based on the categories (ordered)
df = df.sort_values(by='Cat1')
# Unset the categorical type so that the empty categories don't interfere in plot
df.loc[:, 'Cat1'] = df.Cat1.astype(str)

df = df[~((df.Cat1 == 'maybe') amp; (df.Cat2 == 'Red'))]
g = sns.FacetGrid(
    data=df,
    col='Cat2',
    col_order=['Red', 'Blue'],
    sharex=False, height=4, aspect=0.8,
    # use this to squeeze plot to right dimensions
    gridspec_kws={'width_ratios': [2, 3]} # easy to parameterize also
)
g.map_dataframe(
    sns.swarmplot,
    x='Cat1',
    y='Value',
    color='black', s=4
)
g.fig.subplots_adjust(wspace=0, hspace=0)
 

Результат:
Результат