Wykreśl linię poziomą za pomocą matplotlib

148

Użyłem interpolacji splajnów do wygładzenia szeregu czasowego i chciałbym również dodać poziomą linię do wykresu. Ale wydaje się, że jest problem, który jest poza moimi rękami. Każda pomoc byłaby naprawdę pomocna. Oto co mam:

annual = np.arange(1,21,1)
l = np.array(value_list) # a list with 20 values
spl = UnivariateSpline(annual,l)
xs = np.linspace(1,21,200)
plt.plot(xs,spl(xs),'b')

plt.plot([0,len(xs)],[40,40],'r--',lw=2)
pylab.ylim([0,200])
plt.show()

Wydaje się, że problem polega na tym, że używam programu [0,len(xs)]do kreślenia linii poziomej.

Ibe
źródło

Odpowiedzi:

8

Masz rację, myślę, że [0,len(xs)]to cię wyrzuca. Będziesz chciał ponownie użyć oryginalnej zmiennej osi X xsi wykreślić ją z inną tablicą numpy o tej samej długości, w której znajduje się twoja zmienna.

annual = np.arange(1,21,1)
l = np.array(value_list) # a list with 20 values
spl = UnivariateSpline(annual,l)
xs = np.linspace(1,21,200)
plt.plot(xs,spl(xs),'b')

#####horizontal line
horiz_line_data = np.array([40 for i in xrange(len(xs))])
plt.plot(xs, horiz_line_data, 'r--') 
###########plt.plot([0,len(xs)],[40,40],'r--',lw=2)
pylab.ylim([0,200])
plt.show()

Mam nadzieję, że to rozwiąże problem!

chill_turner
źródło
20
To działa, ale nie jest szczególnie wydajne, zwłaszcza, że ​​tworzysz potencjalnie bardzo dużą tablicę w zależności od danych. Jeśli zamierzasz to zrobić w ten sposób, mądrzej byłoby mieć dwa punkty danych, jeden na początku i jeden na końcu. Mimo to matplotlib ma już dedykowaną funkcję dla linii poziomych.
BlivetWidget
501

Szukasz axhline(pozioma linia osi). Na przykład poniższa linia da ci poziomą linię w y = 0.5:

import matplotlib.pyplot as plt
plt.axhline(y=0.5, color='r', linestyle='-')
plt.show()

przykładowa figura

BlivetWidget
źródło
17
Dokumenty: axhline.
uchwyt
1
Powyższy link do dokumentów nie działa - poprawiony link tutaj: matplotlib.org/api/_as_gen/matplotlib.pyplot.axhline.html
Ender2050
35

Jeśli chcesz narysować poziomą linię na osiach, możesz również wypróbować ax.hlines()metodę. Należy określić ypozycję i xmini xmaxw danych współrzędnych (czyli rzeczywiste dane wahają się w osi x). Przykładowy fragment kodu to:

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(1, 21, 200)
y = np.exp(-x)

fig, ax = plt.subplots()
ax.plot(x, y)
ax.hlines(y=0.2, xmin=4, xmax=20, linewidth=2, color='r')

plt.show()

Powyższy fragment wykreśli poziomą linię na osiach w y=0.2. Linia pozioma zaczyna się x=4i kończy na x=20. Wygenerowany obraz to:

wprowadź opis obrazu tutaj

jdhao
źródło
jest to o wiele wygodniejsze niż axhlinewtedy, gdy potrzebny jest określony zakres x linii, którą zamierzałeś narysować. Jaka jest różnica między „axhline” a „hlines”?
Jason Goal
W axhlineprogramie xmini xmaxsą pod względem współrzędnych osi, tak aby znajdowały się w zakresie [0, 1]. Możesz zobaczyć tutaj różnicę między różnymi układami współrzędnych.
jdhao
Dzięki, jeśli to xmini xmaxróżnica jest jedyną różnicą między axhlinei hlines, czy to drugie nie dominuje nad pierwszym?
Jason Goal
20

Zastosowanie matplotlib.pyplot.hlines:

  • Można wykreślić wiele linii poziomych, przekazując a listdo yparametru.
  • y można przekazać jako jedną lokalizację: y=40
  • y można przekazać jako wiele lokalizacji: y=[39, 40, 41]
  • Jeśli jesteś kreślenia postać z czymś takim fig, ax = plt.subplots(), czym zastąpić plt.hlinesalbo plt.axhlinez ax.hlinesalbo ax.axhline, odpowiednio.
  • matplotlib.pyplot.axhlinemoże wykreślić tylko jedną lokalizację (np. y=40)

plt.plot

import numpy as np
import matplotlib.pyplot as plt

xs = np.linspace(1, 21, 200)

plt.figure(figsize=(6, 3))
plt.hlines(y=39.5, xmin=100, xmax=175, colors='aqua', linestyles='-', lw=2, label='Single Short Line')
plt.hlines(y=[39, 40, 41], xmin=[0, 25, 50], xmax=[len(xs)], colors='purple', linestyles='--', lw=2, label='Multiple Lines')
plt.legend(bbox_to_anchor=(1.04,0.5), loc="center left", borderaxespad=0)

wprowadź opis obrazu tutaj

ax.plot

import numpy as np
import matplotlib.pyplot as plt

xs = np.linspace(1, 21, 200)
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(6, 6))

ax1.hlines(y=40, xmin=0, xmax=len(xs), colors='r', linestyles='--', lw=2)
ax1.set_title('One Line')

ax2.hlines(y=[39, 40, 41], xmin=0, xmax=len(xs), colors='purple', linestyles='--', lw=2)
ax2.set_title('Multiple Lines')

plt.tight_layout()
plt.show()

wprowadź opis obrazu tutaj

Oś szeregów czasowych

  • xmini xmaxzaakceptuje datę, taką jak '2020-09-10'lubdatetime(2020, 9, 10)
    • xmin=datetime(2020, 9, 10), xmax=datetime(2020, 9, 10) + timedelta(days=3)
    • Biorąc pod uwagę date = df.index[9], xmin=date, xmax=date + pd.Timedelta(days=3)gdzie indeks to DatetimeIndex.
import pandas_datareader as web  # conda or pip install this; not part of pandas
import pandas as pd
import matplotlib.pyplot as plt

# get test data
df = web.DataReader('^gspc', data_source='yahoo', start='2020-09-01', end='2020-09-28').iloc[:, :2]

# plot dataframe
ax = df.plot(figsize=(9, 6), title='S&P 500', ylabel='Price')

# add horizontal line
ax.hlines(y=3450, xmin='2020-09-10', xmax='2020-09-17', color='purple', label='test')

ax.legend()
plt.show()

wprowadź opis obrazu tutaj

  • Przykładowe dane szeregów czasowych, jeśli web.DataReadernie działają.
data = {pd.Timestamp('2020-09-01 00:00:00'): {'High': 3528.03, 'Low': 3494.6}, pd.Timestamp('2020-09-02 00:00:00'): {'High': 3588.11, 'Low': 3535.23}, pd.Timestamp('2020-09-03 00:00:00'): {'High': 3564.85, 'Low': 3427.41}, pd.Timestamp('2020-09-04 00:00:00'): {'High': 3479.15, 'Low': 3349.63}, pd.Timestamp('2020-09-08 00:00:00'): {'High': 3379.97, 'Low': 3329.27}, pd.Timestamp('2020-09-09 00:00:00'): {'High': 3424.77, 'Low': 3366.84}, pd.Timestamp('2020-09-10 00:00:00'): {'High': 3425.55, 'Low': 3329.25}, pd.Timestamp('2020-09-11 00:00:00'): {'High': 3368.95, 'Low': 3310.47}, pd.Timestamp('2020-09-14 00:00:00'): {'High': 3402.93, 'Low': 3363.56}, pd.Timestamp('2020-09-15 00:00:00'): {'High': 3419.48, 'Low': 3389.25}, pd.Timestamp('2020-09-16 00:00:00'): {'High': 3428.92, 'Low': 3384.45}, pd.Timestamp('2020-09-17 00:00:00'): {'High': 3375.17, 'Low': 3328.82}, pd.Timestamp('2020-09-18 00:00:00'): {'High': 3362.27, 'Low': 3292.4}, pd.Timestamp('2020-09-21 00:00:00'): {'High': 3285.57, 'Low': 3229.1}, pd.Timestamp('2020-09-22 00:00:00'): {'High': 3320.31, 'Low': 3270.95}, pd.Timestamp('2020-09-23 00:00:00'): {'High': 3323.35, 'Low': 3232.57}, pd.Timestamp('2020-09-24 00:00:00'): {'High': 3278.7, 'Low': 3209.45}, pd.Timestamp('2020-09-25 00:00:00'): {'High': 3306.88, 'Low': 3228.44}, pd.Timestamp('2020-09-28 00:00:00'): {'High': 3360.74, 'Low': 3332.91}}

df = pd.DataFrame.from_dict(data, 'index')
Trenton McKinney
źródło
12

Oprócz najbardziej upvoted odpowiedzi tutaj, można również łańcuch axhlinepo wywołaniu plotna a pandas„s DataFrame.

import pandas as pd

(pd.DataFrame([1, 2, 3])
   .plot(kind='bar', color='orange')
   .axhline(y=1.5));

wprowadź opis obrazu tutaj

ayorgo
źródło
4

Miły i łatwy sposób dla osób, które zawsze zapominają o poleceniu, axhlinejest następujący

plt.plot(x, [y]*len(x))

W twoim przypadku xs = xi y = 40. Jeśli len (x) jest duże, staje się to nieefektywne i naprawdę powinieneś użyć axhline.

LSchueler
źródło
2

Możesz użyć plt.griddo narysowania poziomej linii.

import numpy as np
from matplotlib import pyplot as plt
from scipy.interpolate import UnivariateSpline
from matplotlib.ticker import LinearLocator

# your data here
annual = np.arange(1,21,1)
l = np.random.random(20)
spl = UnivariateSpline(annual,l)
xs = np.linspace(1,21,200)

# plot your data
plt.plot(xs,spl(xs),'b')

# horizental line?
ax = plt.axes()
# three ticks:
ax.yaxis.set_major_locator(LinearLocator(3))
# plot grids only on y axis on major locations
plt.grid(True, which='major', axis='y')

# show
plt.show()

przykład losowego wykresu danych

Mehdi
źródło