Захват дисперсии при сглаживании тренда - могу ли я изменить толщину линии? [Дубликат]

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

26
задан Hamid 15 October 2013 в 21:55
поделиться

4 ответа

Используйте LineCollections. Способ сделать это по линиям этого примера Matplotlib -

import numpy as np
from matplotlib.collections import LineCollection
import matplotlib.pyplot as plt
x = np.linspace(0,4*np.pi,10000)
y = np.cos(x)
lwidths=1+x[:-1]
points = np.array([x, y]).T.reshape(-1, 1, 2)
segments = np.concatenate([points[:-1], points[1:]], axis=1)
lc = LineCollection(segments, linewidths=lwidths,color='blue')
fig,a = plt.subplots()
a.add_collection(lc)
a.set_xlim(0,4*np.pi)
a.set_ylim(-1.1,1.1)
fig.show()

output [/g1]

58
ответ дан gg349 21 August 2018 в 21:04
поделиться
  • 1
    Ницца! Таким образом, вы разрезаете линию на несколько частей и используете LineCollection для указания свойств в каждой части. – Hamid 25 January 2014 в 20:05
  • 2
    Совсем не то, что я искал, но это довольно круто, поэтому я проголосовал :) – tommy.carstensen 7 July 2015 в 15:55
  • 3
    Кривая обучения крутая с matplotlib - пытаясь понять, как адаптировать это к графику, где x -аксис содержит timestamps и, по-видимому, сегменты ожидают float, а не timestamp ... какие-либо подсказки? В противном случае это точно то, что я ищу, за исключением невозможности фактически создать граф с ним ... – dwanderson 5 October 2016 в 15:27
  • 4
    Я бы предложил опубликовать новый вопрос, ссылаясь на этот вопрос как ссылку – gg349 9 October 2016 в 01:40

Альтернатива ответу Джулио Гирардо, который разделяет линии в сегментах, вы можете использовать встроенную функцию разворота matplotlib, которые строят линию, используя круги:

from matplotlib import pyplot as plt
import numpy as np

x = np.linspace(0,10,10000)
y = 2 - 0.5*np.abs(x-4)
lwidths = (1+x)**2 # scatter 'o' marker size is specified by area not radius 
plt.scatter(x,y, s=lwidths, color='blue')
plt.xlim(0,9)
plt.ylim(0,2.1)
plt.show()

По моему опыту я нашел два проблемы с делением линии на сегменты:

  1. По какой-то причине сегменты всегда делятся на очень тонкие белые линии. Цвета этих линий смешиваются с цветами сегментов при использовании очень большого количества сегментов. Из-за этого цвет линии не такой, как предполагаемый.
  2. Он не очень хорошо обрабатывает очень резкие разрывы.
3
ответ дан J.Bet 21 August 2018 в 21:04
поделиться

Ответ gg349 работает красиво, но режет линию на многие части, что часто может создавать плохой рендеринг.

Вот альтернативный пример, который генерирует сплошные линии, когда ширина однородна:

import numpy as np
import matplotlib.pyplot as plt

fig, ax = plt.subplots(1)
xs = np.cos(np.linspace(0, 8 * np.pi, 200)) * np.linspace(0, 1, 200)
ys = np.sin(np.linspace(0, 8 * np.pi, 200)) * np.linspace(0, 1, 200)
widths = np.round(np.linspace(1, 5, len(xs)))

def plot_widths(xs, ys, widths, ax=None, color='b', xlim=None, ylim=None,
                **kwargs):
    if not (len(xs) == len(ys) == len(widths)):
        raise ValueError('xs, ys, and widths must have identical lengths')
    fig = None
    if ax is None:
        fig, ax = plt.subplots(1)

    segmentx, segmenty = [xs[0]], [ys[0]]
    current_width = widths[0]
    for ii, (x, y, width) in enumerate(zip(xs, ys, widths)):
        segmentx.append(x)
        segmenty.append(y)
        if (width != current_width) or (ii == (len(xs) - 1)):
            ax.plot(segmentx, segmenty, linewidth=current_width, color=color,
                    **kwargs)
            segmentx, segmenty = [x], [y]
            current_width = width
    if xlim is None:
        xlim = [min(xs), max(xs)]
    if ylim is None:
        ylim = [min(ys), max(ys)]
    ax.set_xlim(xlim)
    ax.set_ylim(ylim)

    return ax if fig is None else fig

plot_widths(xs, ys, widths)
plt.show()
0
ответ дан kingjr 21 August 2018 в 21:04
поделиться
  • 1
    Однако эта реализация может быть хорошей в некоторых случаях, если вы попробуете ее на синусоидальном примере, приведенном gg349, это страдает. Оба не выглядят так хорошо и довольно медленны, так как он добавляет новый объект линии для каждого сегмента, потому что ширина постоянно меняется. – Hamid 2 June 2015 в 01:48

Вы можете отображать каждый сегмент линии отдельно, с отдельной шириной линии, например:

from pylab import *
x = [1, 2, 3, 4, 5]
y = [1, 2, 2, 0, 0]
width = [.5, 1, 1.5, .75, .75]

for i in range(len(x)-1):
    plot(x[i:i+2], y[i:i+2], linewidth=width[i])
show()
0
ответ дан piokuc 21 August 2018 в 21:04
поделиться
  • 1
    Хотя это работает, у него есть две проблемы: 1) для больших наборов данных (например, 10 000 точек) это создает примерно такое же количество объектов линии, что является бременем для рендеринга. 2) Соединения выглядят не очень хорошо, поскольку они состоят из перекрывающихся прямоугольных углов. – Hamid 16 October 2013 в 02:58
Другие вопросы по тегам:

Похожие вопросы: