Переместить расположение отметок на линии Seaborn - PullRequest
0 голосов
/ 02 марта 2020

Я сделал заговор, используя пакет с морскими корнями. Это код:

ax = sns.pointplot(x='latency_condition', y='flow', color=colors[0], ci=95, data=df_new,
                   scale=.5, linestyles='dotted', errwidth=2, capsize=.3)
ax.set_xticklabels(ax.get_xticklabels(), rotation=45)
ax.set_xlabel("E(latency)", fontweight='bold')
ax.set_ylabel("Flow score", fontweight='bold')
ax.set_yticklabels(['min','','','neutral','','','max'])
ax.set(ylim = (10,70))
plt.axhline(y=40, color=colors[3], linestyle='--', linewidth=1)
plt.savefig("fig4_flow.pdf", bbox_inches='tight')
plt.show()

Это все отлично работает. Теперь у меня есть категориальные уровни по оси X на интервальном уровне. Они представляют значения задержки, которые, к сожалению, являются «некрасивыми»: [162, 245, 328, 412, 495, 578]

Я бы предпочел, чтобы, например, на моей оси х имелись отметки на 100 , чтобы улучшить читаемость. Тем не менее, Seaborn видит их (справедливо) как категориальные уровни, поэтому я не могу просто изменить ось X. enter image description here

То, что я хочу сделать, это:

  • удалить текущие метки и заменить их новыми (например, на 100)
  • сделать так, чтобы новые метки учитывали систему координат (так как старые также были равномерно распределены, представляющий основной континуум).

Ответы [ 2 ]

1 голос
/ 03 марта 2020

Идея состоит в том, чтобы использовать вторичную ось х и установить пределы, соответствующие точкам -0,5 и 5,5:

import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
import numpy as np

# create some random data
N = 100
a = [162, 245, 328, 412, 495, 578]
x = np.random.choice(a, N)
y = np.random.normal(65 - x / 20, 10, N)
df_new = pd.DataFrame({'latency_condition':x, 'flow': y})

fig, ax1 = plt.subplots()

ax2 = ax1.twiny()
sns.pointplot(ax=ax2, x='latency_condition', y='flow', color='dodgerblue', ci=95, data=df_new,
              scale=.5, linestyles='dotted', errwidth=2, capsize=.3)

# ax2.tick_params(axis='x', rotation=45)
# ax1.tick_params(axis='x', rotation=45)
ax2.set_xlabel("")
ax1.set_xlabel("E(latency)", fontweight='bold')
ax1.set_xlim(1.5*a[0] - 0.5*a[1], -0.5*a[-2] + 1.5*a[-1])
ax1.set_ylabel("Flow score", fontweight='bold')
ax1.set_yticklabels(['min','','','neutral','','','max'])
ax1.set(ylim = (10,70))

ax1.axhline(y=40, color='crimson', linestyle='--', linewidth=1)
#plt.savefig("fig4_flow.pdf", bbox_inches='tight')
plt.tight_layout()
plt.show()

resulting plot

1 голос
/ 03 марта 2020

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

В любом случае, в Seaborn pointplot(), уровни категориальных переменных нанесены на ось х в координатах 0,1, ..., N-1. Поскольку вы знаете значение задержки в каждой из этих точек, вам нужно просто выполнить линейную интерполяцию, чтобы найти значение x, для которого вам нужно иметь округленное число по вашему выбору:

ticks = [162, 245, 328, 412, 495, 578]
new_ticks = [150,250,350,450,550]
df = pd.DataFrame({'value': np.random.random(size=(100,)), 'cat': np.random.choice(ticks, size=(100,))})

fig, (ax1, ax2)= plt.subplots(1,2, figsize=(8,4))
ax1.set_title('original')
sns.pointplot(x='cat',y='value',data=df, ax=ax1)
ax2.set_title('rescaled')
sns.pointplot(x='cat',y='value',data=df, ax=ax2)

x_ticks = ax2.get_xticks()
s = (x_ticks[-1]-x_ticks[0])/(ticks[-1]-ticks[0])
i = x_ticks[0] - s*ticks[0]
new_x_ticks = s*np.asarray(new_ticks) + i

ax2.set_xticks(new_x_ticks)
ax2.set_xticklabels(new_ticks)

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...