使用 matplotlib 绘制水平线
Posted
技术标签:
【中文标题】使用 matplotlib 绘制水平线【英文标题】:Plot a horizontal line using matplotlib 【发布时间】:2016-01-27 17:29:25 【问题描述】:我已经使用样条插值来平滑时间序列,并且还想在图中添加一条水平线。但似乎有一个问题超出了我的掌握。任何帮助都会非常有帮助。这是我所拥有的:
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()
问题似乎与我使用[0,len(xs)]
进行水平线绘图有关。
【问题讨论】:
【参考方案1】:使用matplotlib.pyplot.hlines
:
通过将list
传递给y
参数来绘制多条水平线。
y
可以作为单个位置传递:y=40
y
可以作为多个位置传递:y=[39, 40, 41]
如果您要绘制带有 fig, ax = plt.subplots()
之类的图形,请将 plt.hlines
或 plt.axhline
分别替换为 ax.hlines
或 ax.axhline
。
matplotlib.pyplot.axhline
只能绘制一个位置(例如y=40
)
请参阅此answer 以获取带有.vlines
的垂直线
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)
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()
时间序列轴
xmin
和 xmax
将接受像 '2020-09-10'
或 datetime(2020, 9, 10)
这样的日期
使用from datetime import datetime
xmin=datetime(2020, 9, 10), xmax=datetime(2020, 9, 10) + timedelta(days=3)
给定date = df.index[9]
、xmin=date, xmax=date + pd.Timedelta(days=3)
,其中索引为DatetimeIndex
。
轴上的日期列必须是datetime dtype
。如果使用 pandas,则使用 pd.to_datetime
。对于数组或列表,请分别参考Converting numpy array of strings to datetime 或Convert datetime list into date python。
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; the Date index is already downloaded as datetime dtype
df = web.DataReader('^gspc', data_source='yahoo', start='2020-09-01', end='2020-09-28').iloc[:, :2]
# display(df.head(2))
High Low
Date
2020-09-01 3528.030029 3494.600098
2020-09-02 3588.110107 3535.229980
# 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()
如果web.DataReader
不起作用,则采样时间序列数据。
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')
条形图和直方图
请注意,无论轴标签如何,条形图的索引通常为 0,因此请根据条形索引而不是刻度标签选择xmin
和 xmax
。
ax.get_xticklabels()
将显示位置和标签。
import pandas as pd
import seaborn as sns # for tips data
# load data
tips = sns.load_dataset('tips')
# histogram
ax = tips.plot(kind='hist', y='total_bill', bins=30, ec='k', title='Histogram with Horizontal Line')
_ = ax.hlines(y=6, xmin=0, xmax=55, colors='r')
# barplot
ax = tips.loc[5:25, ['total_bill', 'tip']].plot(kind='bar', figsize=(15, 4), title='Barplot with Vertical Lines', rot=0)
_ = ax.hlines(y=6, xmin=3, xmax=15, colors='r')
【讨论】:
【参考方案2】:您正在寻找axhline
(水平轴线)。例如,下面将在y = 0.5
处为您提供一条水平线:
import matplotlib.pyplot as plt
plt.axhline(y=0.5, color='r', linestyle='-')
plt.show()
【讨论】:
【参考方案3】:如果你想在坐标轴上画一条水平线,你也可以试试ax.hlines()
方法。您需要在数据坐标中指定y
位置和xmin
和xmax
(即您在x 轴上的实际数据范围)。示例代码 sn -p 为:
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()
上面的 sn-p 将在 y=0.2
的坐标轴上绘制一条水平线。水平线从x=4
开始,到x=20
结束。生成的图像是:
【讨论】:
【参考方案4】:你可以使用plt.grid
画一条水平线。
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()
【讨论】:
【参考方案5】:除了此处投票最多的答案外,还可以在pandas
的DataFrame
上调用plot
后链接axhline
。
import pandas as pd
(pd.DataFrame([1, 2, 3])
.plot(kind='bar', color='orange')
.axhline(y=1.5));
【讨论】:
【参考方案6】:对于那些总是忘记命令axhline
的人来说,一个简单的方法如下
plt.plot(x, [y]*len(x))
在您的情况下,xs = x
和 y = 40
。
如果 len(x) 很大,那么这将变得低效,你应该真正使用axhline
。
【讨论】:
【参考方案7】:你是对的,我认为[0,len(xs)]
让你失望了。您需要重用原始 x 轴变量 xs
并将其与另一个长度相同且包含您的变量的 numpy 数组绘制。
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()
希望能解决问题!
【讨论】:
这行得通,但不是特别有效,尤其是当您根据数据创建一个可能非常大的数组时。如果你打算这样做,那么有两个数据点会更聪明,一个在开头,一个在结尾。尽管如此,matplotlib 已经有一个专门的水平线功能。以上是关于使用 matplotlib 绘制水平线的主要内容,如果未能解决你的问题,请参考以下文章
python使用matplotlib绘制水平条形图并在条形图上添加实际数值标签实战
Python使用matplotlib绘制柱状图(bar plot)实战:水平条形图垂直条形图分组条形图堆叠条形图
一个Python函数解决散点图绘制——Matplotlib库示例
一个Python函数解决散点图绘制——Matplotlib库示例