使用pandas数据帧的简单线性回归

时间:2018-02-13 13:29:54

标签: python pandas numpy linear-regression

我希望检查多个实体的趋势(SysNr)

我的数据跨越3年(2014,2015,2016)

我正在查看大量变量,但会将此问题限制为一个(' res_f_r')

我的DataFrame看起来像这样

d = [
    {'RegnskabsAar': 2014, 'SysNr': 1, 'res_f_r': 350000},
    {'RegnskabsAar': 2015, 'SysNr': 1, 'res_f_r': 400000},
    {'RegnskabsAar': 2016, 'SysNr': 1, 'res_f_r': 450000},
    {'RegnskabsAar': 2014, 'SysNr': 2, 'res_f_r': 350000},
    {'RegnskabsAar': 2015, 'SysNr': 2, 'res_f_r': 300000},
    {'RegnskabsAar': 2016, 'SysNr': 2, 'res_f_r': 250000},
]

df = pd.DataFrame(d)



   RegnskabsAar  SysNr  res_f_r
0          2014      1   350000
1          2015      1   400000
2          2016      1   450000
3          2014      2   350000
4          2015      2   300000
5          2016      2   250000

我的愿望是对每个实体(SysNr)进行线性回归并返回斜率和截距

我想要的输出是

   SysNr  intercept  slope
0      1     300000  50000
1      2     400000 -50000

有什么想法吗?

2 个答案:

答案 0 :(得分:5)

所以我不知道为什么我们的拦截值不同(也许我犯了一个错误,或者您的给定数据不是您期望处理的完整数据),但我建议您使用np.polyfit或者您选择的工具(scikit-learnscipy.stats.linregress,...)与groupby结合使用:

In [25]: df.groupby("SysNr").apply(lambda g: np.polyfit(g.RegnskabsAar, g.res_f_r, 1))
Out[25]:
SysNr
1    [49999.99999999048, -100349999.99998075]
2    [-49999.99999999045, 101049999.99998072]
dtype: object

之后,美化它:

In [43]: df.groupby("SysNr").apply(
    ...:     lambda g: np.polyfit(g.RegnskabsAar, g.res_f_r, 1)).apply(
    ...:     pd.Series).rename(columns={0:'slope', 1:'intercept'}).reset_index()
Out[43]:
   SysNr    slope     intercept
0      1  50000.0 -1.003500e+08
1      2 -50000.0  1.010500e+08

编辑:

因为您在评论的另一个答案中询问了如何处理某些SysNr的缺失年份: 只需删除NaNs即可获得有效的线性回归。当然你也可以根据你想要达到的目标来填充它们,但从我的观点来看,这并没有那么有用。

如果实体只有一年的数据,则无法对其进行有用的线性回归。但是你可以(如果你想要并且适合你的情况,请在需要时提供有关数据的更多信息)以某种方式推断其他实体的斜率到这个并计算截距。当然,你必须对实体斜率的分布做一些假设(例如线性,然后sysNr 3的斜率为-150000.0)。

答案 1 :(得分:2)

您也可以使用linregress中的scipy.statsgroupby中的pandas

from scipy.stats import linregress

# groupby column
grouped = df.groupby('SysNr')

# https://stackoverflow.com/a/14775604/5916727
# apply linear regression to each group
result_df = pd.DataFrame(grouped.apply(lambda x: linregress(x['RegnskabsAar'], x['res_f_r']))).reset_index()

# https://stackoverflow.com/a/29550458/5916727
# expand result to each column
result_df[['slope', 'intercept', 'r_value', 'p_value', 'std_err']] = result_df[0].apply(pd.Series)

# drop initial column with all in one
del result_df[0]

result_df

结果:

   SysNr    slope    intercept  r_value       p_value  std_err
0      1  50000.0 -100350000.0      1.0  9.003163e-11      0.0
1      2 -50000.0  101050000.0     -1.0  9.003163e-11      0.0
相关问题