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