Исключить значения выше / ниже порога из автоматического масштабирования в matplotlib - PullRequest
0 голосов
/ 23 января 2020

Предположим, у меня есть ряд точек данных, таких как [1,2,5,4, -50, 0,1,1,3,...], поэтому они имеют приблизительный диапазон значений, а затем есть несколько, которые намного, намного больше (или меньше). Если я просто нанесу их на график, автоматическая шкала c создаст бесполезный график, поскольку все детали сжаты за пределами видимости.

У меня есть хорошее представление о приблизительном диапазоне фактических данных, и

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

Мое текущее решение - установить значения за порогом на nan, используя что-то вроде

nandata[data<threshold] = np.nan

Эти значения затем игнорируются matplotlib при построении графика. Однако у этого подхода есть два недостатка: во-первых, мне либо приходится облажаться с моими данными и рисковать неприятными побочными эффектами, либо мне приходится делать копии каждый раз, что не очень хорошо для эффективности использования памяти. Во-вторых, эти значения полностью отбрасываются. Но хотя я не хочу, чтобы они скрывали детали, я хочу сказать, что там есть выбросы. При правильном масштабировании я мог бы просто уменьшить масштаб в интерактивном режиме, или у меня могла бы быть соединительная линия, которая выходит за пределы экрана.

Есть ли способ применить автомасштабирование только к значениям внутри диапазона?

1 Ответ

1 голос
/ 23 января 2020

Это может быть не совсем то, что вы ищете, но вы можете применить фильтрацию на этапе построения графика, отфильтровав отфильтрованные данные, но оставив исходные данные без изменений и не делая лишних копий. Затем вы можете получить автоматически масштабируемые пределы x и y, прежде чем наносить на график выбросы, после чего вы возвращаете пределы x и y к их значениям до выброса. Он не должен быть значительно более неэффективным, чем отдельный сюжет. Примерно так

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0,10,25)
y = np.sin(x)
y[-1] = -200
cond = y > -25
plt.scatter(x[cond],y[cond])
xlim = plt.xlim()
ylim = plt.ylim()
plt.scatter(x[cond == False], y[cond == False])
plt.xlim(xlim)
plt.ylim(ylim)
plt.show()

Без фильтрации это показывает

enter image description here

, а с фильтрацией показывает

enter image description here

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


Редактировать

Чтобы сделать это менее громоздким, его можно обернуть в удобную функцию следующим образом

import matplotlib.pyplot as plt
import numpy as np

def scaledScatter(x, y, cond, **kwargs):
    plt.scatter(x[cond],y[cond], **kwargs)
    xlim = plt.xlim()
    ylim = plt.ylim()
    plt.scatter(x[cond == False], y[cond == False], **kwargs)
    plt.xlim(xlim)
    plt.ylim(ylim)

x = np.linspace(0,10,25)
y = np.sin(x)
y[-1] = -200
cond = y > -25
scaledScatter(x, y, cond, color = 'k', marker = '.')
plt.show()

Обратите внимание, что эта формулировка позволяет передавать обычные ключевые аргументы для matplotlib.pyplot.scatter и распространяет их соответствующим образом.

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