如何在时间序列线图上绘制回归线

4
我有一个问题,关于下面我计算出来的斜率角度值:
import pandas as pd
import yfinance as yf
import matplotlib.pyplot as plt
import datetime as dt
import numpy as np

df = yf.download('aapl', '2015-01-01', '2021-01-01')
df.rename(columns = {'Adj Close' : 'Adj_close'}, inplace= True)

x1 = pd.Timestamp('2019-01-02')
x2 = df.index[-1]
y1 = df[df.index == x1].Adj_close[0]
y2 = df[df.index == x2].Adj_close[0]

slope = (y2 - y1)/ (x2 - x1).days
angle = round(np.rad2deg(np.arctan2(y2 - y1, (x2 - x1).days)), 1)

fig, ax1 = plt.subplots(figsize= (15, 6))
ax1.grid(True, linestyle= ':')
ax1.set_zorder(1)
ax1.set_frame_on(False)
ax1.plot(df.index, df.Adj_close, c= 'k', lw= 0.8)
ax1.plot([x1, x2], [y1, y2], c= 'k')


ax1.set_xlim(df.index[0], df.index[-1])
plt.show()

它返回了坡度角的值为7.3度。但是从图表上看,这似乎不正确:enter image description here 它看起来接近45度。这里有什么问题?
这是我需要计算角度的线:enter image description here
1个回答

9
  • OP中的实现方式不是确定或绘制线性模型的正确方法。因此,关于确定绘制线条的角度的问题被绕过,并展示了更严格的绘制回归线的方法。
  • 通过将日期时间转换为序数,可以添加回归线。该模型可以使用sklearn计算,也可以使用seaborn.regplot添加到图中,如下所示。
  • 使用pandas.DataFrame.plot绘制完整数据
  • python 3.8.11pandas 1.3.2matplotlib 3.4.3seaborn 0.11.2sklearn 0.24.2中测试通过

导入和数据

import yfinance as yf
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
from sklearn.linear_model import LinearRegression

# download the data
df = yf.download('aapl', '2015-01-01', '2021-01-01')

# convert the datetime index to ordinal values, which can be used to plot a regression line
df.index = df.index.map(pd.Timestamp.toordinal)

# display(df.iloc[:5, [4]])
        Adj Close
Date             
735600  24.782110
735603  24.083958
735604  24.086227
735605  24.423975
735606  25.362394

# convert the regression line start date to ordinal
x1 = pd.to_datetime('2019-01-02').toordinal()

# data slice for the regression line
data=df.loc[x1:].reset_index()

使用seaborn绘制回归线

  • 使用seaborn.regplot函数,无需进行计算即可将回归线添加到数据的折线图中。
  • 将x轴标签转换为日期时间格式。
  • 如果需要调整端点,请尝试调整xticks和标签。
# plot the Adj Close data
ax1 = df.plot(y='Adj Close', c='k', figsize=(15, 6), grid=True, legend=False,
              title='Adjusted Close with Regression Line from 2019-01-02')

# add a regression line
sns.regplot(data=data, x='Date', y='Adj Close', ax=ax1, color='magenta', scatter_kws={'s': 7}, label='Linear Model', scatter=False)

ax1.set_xlim(df.index[0], df.index[-1])

# convert the axis back to datetime
xticks = ax1.get_xticks()
labels = [pd.Timestamp.fromordinal(int(label)).date() for label in xticks]
ax1.set_xticks(xticks)
ax1.set_xticklabels(labels)

ax1.legend()

plt.show()

enter image description here

计算线性模型

# create the model
model = LinearRegression()

# extract x and y from dataframe data
x = data[['Date']]
y = data[['Adj Close']]

# fit the mode
model.fit(x, y)

# print the slope and intercept if desired
print('intercept:', model.intercept_)
print('slope:', model.coef_)

intercept: [-90078.45713565]
slope: [[0.1222514]]

# calculate y1, given x1
y1 = model.predict(np.array([[x1]]))

print(y1)
array([[28.27904095]])

# calculate y2, given the last date in data
x2 = data.Date.iloc[-1]
y2 = model.predict(np.array([[x2]]))

print(y2)
array([[117.40030862]])

# this can be added to `ax1` with
ax1 = df.plot(y='Adj Close', c='k', figsize=(15, 6), grid=True, legend=False,
              title='Adjusted Close with Regression Line from 2019-01-02')
ax1.plot([x1, x2], [y1[0][0], y2[0][0]], label='Linear Model', c='magenta')
ax1.legend()

enter image description here

坡度角度

  • 这是由于 axes 的方面不同导致的人工制品,xy 不相等。当方面相等时,可以看到坡度为7.0度。
x = x2 - x1
y = y2[0][0] - y1[0][0]
slope = y / x

print(round(slope, 7) == round(model.coef_[0][0], 7))
[out]:
True

angle = round(np.rad2deg(np.arctan2(y, x)), 1)
print(angle)
[out]:
7.0

# given the existing plot
ax1 = df.plot(y='Adj Close', c='k', figsize=(15, 6), grid=True, legend=False,
              title='Adjusted Close with Regression Line from 2019-01-02')
ax1.plot([x1, x2], [y1[0][0], y2[0][0]], label='Linear Model', c='magenta')

# make the aspect equal
ax1.set_aspect('equal', adjustable='box')

enter image description here


1
好的,明白了。这是因为图像大小的长宽比让人感觉应该有更大的角度。 - Raj Nair

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接