Как избежать наложения баров ошибок в matplotlib? - PullRequest
0 голосов
/ 19 сентября 2019

Я хочу создать график для двух разных наборов данных, аналогичный представленному в этом ответе :

enter image description here

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

В моей задаче я должен построить похожую графику, но с некоторыми категориальными данными по оси x:

enter image description here

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

Ответы [ 2 ]

2 голосов
/ 21 сентября 2019

Вы можете перевести каждую панель ошибок, добавив преобразование данных по умолчанию к предыдущему преобразованию в пространстве данных.Это возможно, если знать, что категории, как правило, находятся на расстоянии одного блока данных друг от друга.

import numpy as np; np.random.seed(42)
import matplotlib.pyplot as plt
from matplotlib.transforms import Affine2D

x = list("ABCDEF")
y1, y2 = np.random.randn(2, len(x))
yerr1, yerr2 = np.random.rand(2, len(x))*4+0.3

fig, ax = plt.subplots()

trans1 = Affine2D().translate(-0.1, 0.0) + ax.transData
trans2 = Affine2D().translate(+0.1, 0.0) + ax.transData
er1 = ax.errorbar(x, y1, yerr=yerr1, marker="o", linestyle="none", transform=trans1)
er2 = ax.errorbar(x, y2, yerr=yerr2, marker="o", linestyle="none", transform=trans2)

plt.show()

enter image description here

В качестве альтернативы вы можете перевести полосы ошибок после применения преобразования данных и, следовательно, переместить их в единицах точек.

import numpy as np; np.random.seed(42)
import matplotlib.pyplot as plt
from matplotlib.transforms import ScaledTranslation

x = list("ABCDEF")
y1, y2 = np.random.randn(2, len(x))
yerr1, yerr2 = np.random.rand(2, len(x))*4+0.3

fig, ax = plt.subplots()

trans1 = ax.transData + ScaledTranslation(-5/72, 0, fig.dpi_scale_trans)
trans2 = ax.transData + ScaledTranslation(+5/72, 0, fig.dpi_scale_trans)
er1 = ax.errorbar(x, y1, yerr=yerr1, marker="o", linestyle="none", transform=trans1)
er2 = ax.errorbar(x, y2, yerr=yerr2, marker="o", linestyle="none", transform=trans2)

plt.show()

enter image description here

Хотя результаты выглядят одинаково в обоих случаях, они принципиально различны.Вы увидите эту разницу при интерактивном увеличении осей или изменении размера фигуры.

0 голосов
/ 19 сентября 2019

Рассмотрим следующий подход к выделению графиков - сочетание errorbar и fill_between с ненулевой прозрачностью:

import random
import matplotlib.pyplot as plt

# create sample data
N = 8
data_1 = {
    'x': list(range(N)),
    'y': [10. + random.random() for dummy in range(N)],
    'yerr': [.25 + random.random() for dummy in range(N)]}
data_2 = {
    'x': list(range(N)),
    'y': [10.25 + .5 * random.random() for dummy in range(N)],
    'yerr': [.5 * random.random() for dummy in range(N)]}

# plot
plt.figure()
# only errorbar
plt.subplot(211)
for data in [data_1, data_2]:
    plt.errorbar(**data, fmt='o')
# errorbar + fill_between
plt.subplot(212)
for data in [data_1, data_2]:
    plt.errorbar(**data, alpha=.75, fmt=':', capsize=3, capthick=1)
    data = {
        'x': data['x'],
        'y1': [y - e for y, e in zip(data['y'], data['yerr'])],
        'y2': [y + e for y, e in zip(data['y'], data['yerr'])]}
    plt.fill_between(**data, alpha=.25)

Результат:

enter image description here

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