为扩展回归找到 y = 0 的 x 值

Find x-value where y = 0 for extended regression

我有以下数据集:

ID        DATE            VALUE
1         01-01-2020      98
1         02-01-2020      96
1         03-01-2020      94
2         01-01-2020      99
2         02-01-2020      90
2         05-01-2020      85

对于每个id,我想通过线性回归计算值达到0的日期。我成功地绘制了一条延长线,我可以通过以下代码直观地看到它达到 0 的点,但我没有成功提取确切的日期。

现在我的代码如下所示:

# convert date to ordinal 
df['DATE_ord']=df['DATE'].map(dt.datetime.toordinal)

# Create plot with current values
ax = sns.regplot(data=df,x='DATE_ord',y='VALUE')

# Set x-axis values (ordinal dates)
date_range = np.arange(730000, 760000, 1000)

# Calculate extended values
slope, intercept, r_value, p_value, std_err = stats.linregress(x = df[
        "DATE_ord"].values, y = df["VALUE"].values)

line = [slope*xi + intercept for xi in date_range]

plt.plot(date_range, line, label="Fitting Line", linewidth=1)

# Convert x-axis values back to date
ax.set_xlabel('date')
new_labels = [date.fromordinal(int(item)) for item in ax.get_xticks()]
ax.set_xticklabels(new_labels)

我现在需要找到 Y 值 (VALUE) 达到 0 的日期。我发现 或多或少想要达到相同的目的,但这不起作用,因为值在我的斜率与 x 轴的预测值不同,我不知道如何进行这项工作。我唯一能想到的就是用回归表达式计算它并填写数字,但我不确定如何以一种可以在我仍然需要创建的 for 循环中工作的方式来做到这一点遍历不同的 ID。

让我们尝试只用 pandas 来做这个,不要循环

加载示例数据

import pandas as pd
from io import StringIO
data = StringIO(
'''
ID        DATE            VALUE
1         01-01-2020      98
1         02-01-2020      96
1         03-01-2020      94
2         01-01-2020      99
2         02-01-2020      90
2         05-01-2020      85
''')
df = pd.read_csv(data, sep = '\s+')
df['DATE'] = pd.to_datetime(df['DATE'], dayfirst = True)

生成序数并计算每组的回归系数:

import datetime as dt
from scipy import stats
df['DATE_ord']=df['DATE'].map(dt.datetime.toordinal)
dfr = (df.groupby('ID').apply(lambda g: stats.linregress(x = g[
        "DATE_ord"].values, y = g["VALUE"].values)[0:2])
  .apply(pd.Series)
  .rename(columns = {0 : 'slope', 1:'intercept'}))
dfr

我们明白了


     slope      intercept
ID      
1   -2.000000   1.474948e+06
2   -3.076923   2.269096e+06

现在 'zero' 日期就是 0 = s * x + i 的解,即 x0 = -intercept/slope。我们计算序数并转换回日期

dfr['zd_ord'] = -dfr['intercept']/dfr['slope']
dfr['zd'] = dfr['zd_ord'].astype(int).map(dt.datetime.fromordinal)

得到


     slope      intercept       zd_ord      zd
ID              
1   -2.000000   1.474948e+06    737474.00   2020-02-19
2   -3.076923   2.269096e+06    737456.35   2020-02-01