当前位置: 首页 > 面试题库 >

Python中的Fama Macbeth回归(pandas或Statsmodels)

尉迟哲瀚
2023-03-14
问题内容

计量经济学背景

Fama Macbeth回归是指对面板数据进行回归的过程(其中有N个不同的个体,每个个体对应多个时期T,例如日,月,年)。因此,总共有N x T
obs。请注意,如果面板数据不平衡,则可以。

Fama Macbeth回归法是对每个时期进行跨部门回归,即在给定时期t中将N个个体合并在一起。并针对t = 1,…
T执行此操作。因此,总共进行了T回归。然后,对于每个自变量,我们都有一个系数的时间序列。然后,我们可以使用系数的时间序列执行假设检验。通常我们将平均值作为每个自变量的最终系数。并且我们使用t统计量来检验显着性。

我的问题

我的问题是在熊猫中实现这一点。从熊猫的源代码中,我注意到有一个名为的过程fama_macbeth。但是我找不到关于此的任何文档。

该操作也可以轻松完成groupby。目前,我正在这样做:

def fmreg(data,formula):
    return smf.ols(formula,data=data).fit().params[1]

res=df.groupby('date').apply(fmreg,'ret~var1')

res是一个由索引date的Series
params[1],Series的值是,它是的系数var1。但是现在我想拥有更多的自变量,我需要提取所有这些自变量的系数,但是我无法弄清楚。我试过了

def fmreg(data,formula):
    return smf.ols(formula,data=data).fit().params

res=df.groupby('date').apply(fmreg,'ret~var1+var2+var3')

这行不通。期望的结果是,res是由索引的数据帧date,以及数据帧的每列应包含各变量的系数interceptvar1var2var3

我还检查了statsmodels,他们也没有这样的内置程序。

是否有任何软件包可以生成发布质量的回归表?像outreg2在Stata和texregR中一样?谢谢你的帮助!


问题答案:

更新以反映截至2018年秋季的Fama-MacBeth的库状况。此fama_macbeth功能已删除pandas了一段时间。那么您有什么选择呢?

  1. 如果您使用的是python 3,则可以在LinearModels中使用Fama-MacBeth方法:https : //github.com/bashtage/linearmodels/blob/master/linearmodels/panel/model.py

  2. 如果您使用的是python 2或只是不想使用LinearModels,那么最好的选择就是自己动手。

例如,假设您在类似以下的面板中拥有Fama-French行业投资组合(您还计算了一些变量,例如过往的beta或过往的收益用作x变量):

In [1]: import pandas as pd
        import numpy as np
        import statsmodels.formula.api as smf

In [4]: df = pd.read_csv('industry.csv',parse_dates=['caldt'])
        df.query("caldt == '1995-07-01'")

In [5]: Out[5]: 
      industry      caldt    ret    beta  r12to2  r36to13
18432     Aero 1995-07-01   6.26  0.9696  0.2755   0.3466
18433    Agric 1995-07-01   3.37  1.0412  0.1260   0.0581
18434    Autos 1995-07-01   2.42  1.0274  0.0293   0.2902
18435    Banks 1995-07-01   4.82  1.4985  0.1659   0.2951

Fama-
MacBeth主要涉及逐月计算相同的横截面回归模型,因此您可以使用来实现groupby。您可以创建一个函数dataframe(该函数来自groupby)和patsy公式;然后拟合模型并返回参数估计值。这是如何实现它的准系统版本(请注意,这是几年前原始提问者试图做的事情……不确定为什么它不起作用,尽管可能那时statsmodels结果对象方法params未返回pandas
Series因此需要将返回值Series显式转换为…在当前版本的pandas0.23.4中确实可以正常工作):

def ols_coef(x,formula):
    return smf.ols(formula,data=x).fit().params

In [9]: gamma = (df.groupby('caldt')
                .apply(ols_coef,'ret ~ 1 + beta + r12to2 + r36to13'))
        gamma.head()

In [10]: Out[10]: 
            Intercept      beta     r12to2   r36to13
caldt                                               
1963-07-01  -1.497012 -0.765721   4.379128 -1.918083
1963-08-01  11.144169 -6.506291   5.961584 -2.598048
1963-09-01  -2.330966 -0.741550  10.508617 -4.377293
1963-10-01   0.441941  1.127567   5.478114 -2.057173
1963-11-01   3.380485 -4.792643   3.660940 -1.210426

然后只需计算均值,均值的标准误和t检验(或所需的任何统计数据)即可。类似于以下内容:

def fm_summary(p):
    s = p.describe().T
    s['std_error'] = s['std']/np.sqrt(s['count'])
    s['tstat'] = s['mean']/s['std_error']
    return s[['mean','std_error','tstat']]

In [12]: fm_summary(gamma)
Out[12]: 
               mean  std_error     tstat
Intercept  0.754904   0.177291  4.258000
beta      -0.012176   0.202629 -0.060092
r12to2     1.794548   0.356069  5.039896
r36to13    0.237873   0.186680  1.274230

提高速度

使用statsmodels的回归有显著的开销(特别是考虑到你只需要估计系数)。如果您想提高效率,则可以从切换statsmodelsnumpy.linalg.lstsq。编写一个执行ols估计的新函数…类似以下内容(注意,我没有做类似检查这些矩阵的等级的操作…):

def ols_np(data,yvar,xvar):
    gamma,_,_,_ = np.linalg.lstsq(data[xvar],data[yvar],rcond=None)
    return pd.Series(gamma)

如果您仍在使用旧版本的pandas,则可以使用以下功能:

这是在中使用fama_macbeth函数的示例pandas

>>> df

                y    x
date       id
2012-01-01 1   0.1  0.4
           2   0.3  0.6
           3   0.4  0.2
           4   0.0  1.2
2012-02-01 1   0.2  0.7
           2   0.4  0.5
           3   0.2  0.1
           4   0.1  0.0
2012-03-01 1   0.4  0.8
           2   0.6  0.1
           3   0.7  0.6
           4   0.4 -0.1

注意,结构。该fama_macbeth函数期望y-var和x-vars具有一个以日期为第一个变量,以股票/公司/实体id为第二个变量的多重索引

>>> fm  = pd.fama_macbeth(y=df['y'],x=df[['x']])
>>> fm


----------------------Summary of Fama-MacBeth Analysis-------------------------

Formula: Y ~ x + intercept
# betas :   3

----------------------Summary of Estimated Coefficients------------------------
     Variable          Beta       Std Err        t-stat       CI 2.5%      CI 97.5%
          (x)       -0.0227        0.1276         -0.18       -0.2728        0.2273
  (intercept)        0.3531        0.0842          4.19        0.1881        0.5181

--------------------------------End of Summary---------------------------------

请注意,仅打印fm调用fm.summary

>>> fm.summary

----------------------Summary of Fama-MacBeth Analysis-------------------------

Formula: Y ~ x + intercept
# betas :   3

----------------------Summary of Estimated Coefficients------------------------
     Variable          Beta       Std Err        t-stat       CI 2.5%      CI 97.5%
          (x)       -0.0227        0.1276         -0.18       -0.2728        0.2273
  (intercept)        0.3531        0.0842          4.19        0.1881        0.5181

--------------------------------End of Summary---------------------------------

另外,请注意,该fama_macbeth函数会自动添加一个拦截器(与statsmodels例程相反)。而且x-
var必须是a,dataframe因此,如果您仅传递一列,则需要将其传递为df[['x']]

如果您不想拦截,则必须执行以下操作:

>>> fm  = pd.fama_macbeth(y=df['y'],x=df[['x']],intercept=False)


 类似资料:
  • 我正在运行我在buitin网站上看到的一个关于张量流线性回归的代码,它总是给我一个错误,我不知道代码有什么问题。首先我以为这是我的ide,然后当我切换到jupyter实验室时,它显示了我在这一点上的错误 首先我以为这是我的ide,然后当我切换到jupyter实验室时,它显示了我在这一点上的错误

  • 本文向大家介绍基于python中theano库的线性回归,包括了基于python中theano库的线性回归的使用技巧和注意事项,需要的朋友参考一下 theano库是做deep learning重要的一部分,其最吸引人的地方之一是你给出符号化的公式之后,能自动生成导数。本文使用梯度下降的方法,进行数据拟合,现在把代码贴在下方 代码块 其基本思想是随机梯度下降。 以上就是本文的全部内容,希望对大家的学

  • 问题内容: 我有一个熊猫系列。如果要获取按元素划分的地板或天花板,是否有内置方法,还是必须编写函数并使用apply?我问,因为数据很大,所以我很欣赏效率。同样,对于熊猫包装,也没有问过这个问题。 问题答案: 您可以使用NumPy的内置方法来执行此操作:或。 两者都返回Series对象(而不是数组),因此保留了索引信息。

  • 本文向大家介绍用scikit-learn和pandas学习线性回归的方法,包括了用scikit-learn和pandas学习线性回归的方法的使用技巧和注意事项,需要的朋友参考一下 对于想深入了解线性回归的童鞋,这里给出一个完整的例子,详细学完这个例子,对用scikit-learn来运行线性回归,评估模型不会有什么问题了。 1. 获取数据,定义问题 没有数据,当然没法研究机器学习啦。:) 这里我们用

  • 我正在编写一个python类来寻找8皇后问题的解决方案。如何在方法中正确实现回溯?我认为递归应该可以工作,但是,程序在第一次尝试没有找到解决方案后停止,回溯也不会发生。所有helper方法都能正常工作。 我的问题是在添加女王之前缺少一个板子的深度副本,还是仅仅是缺少回溯?

  • 问题内容: def foo(a): a.append(1) if len(a) > 10: print a return a else: foo(a) 为什么此递归函数返回None(请参见下面的脚本)?我不太明白我在做什么错。 问题答案: 您不会在该子句中返回任何内容: