当我将 Jupyter Notebook 转换为 PDF 时,我可以漂亮地打印 linearmodels.panel.results.compare() 的输出吗?

Can I pretty print the output of linearmodels.panel.results.compare() when I convert a Jupyter Notebook to PDF?

我使用 Python 分析 Jupyter Notebooks 中的数据,我将其转换为 PDF 以与共同作者 (jupyter nbconvert --to pdf) 共享。 我经常使用 linearmodels.panel.results.compare() 来比较 linearmodels 包中的面板回归估计。 但是,PDF 转换过程将 compare() 输出转换为固定宽度的字体,这对于 PDF 来说太宽了(我将在下面提供代码):

当我将 Jupyter Notebook 转换为 PDF 时,我可以漂亮地打印 compare() 的输出吗?

一种可能的解决方案是将 compare() 输出转换为数据帧。 当我转换为 PDF 时,选项 pd.options.display.latex.repr = True 会漂亮地打印数据框。 例如:

在笔记本中,compare() 输出格式很好,看起来像 数据框。 但是,它不是数据框,我也未能将其转换为数据框。

是否有替代解决方案来比较 linearmodels 包输出结果的漂亮打印?

下面是生成上述表格的代码(复制并粘贴到 Jupyter Notebook 代码单元格中):

import pandas as pd
from linearmodels.panel import FamaMacBeth
from linearmodels.panel.results import compare

pd.options.display.latex.repr = True

from statsmodels.datasets import grunfeld
df = grunfeld.load_pandas().data
df.set_index(['firm','year'], inplace=True)

display(df.head())

table = {
    '(1)': FamaMacBeth.from_formula(formula='value ~ 1 + invest + capital', data=df).fit(),
    '(2)': FamaMacBeth.from_formula(formula='value ~ 1 + invest + capital', data=df).fit(),
    '(3)': FamaMacBeth.from_formula(formula='value ~ 1 + invest + capital', data=df).fit(),
    '(4)': FamaMacBeth.from_formula(formula='value ~ 1 + invest + capital', data=df).fit()
}

display(compare(table))

comparereturns一个PanelModelComparison。这个 class 有一个 属性 summary 其中 returns 一个 linearmodels.compat.statsmodels.Summary 实际上与 statsmodels 中可用的 Summary 对象相同。 Summary 个实例有一个方法 as_latex() 将 table 转换为 LaTeX。

import pandas as pd
from linearmodels.panel import FamaMacBeth
from linearmodels.panel.results import compare

pd.options.display.latex.repr = True

from statsmodels.datasets import grunfeld
df = grunfeld.load_pandas().data
df.set_index(['firm','year'], inplace=True)

display(df.head())

table = {
    '(1)': FamaMacBeth.from_formula(formula='value ~ 1 + invest + capital', data=df).fit(),
    '(2)': FamaMacBeth.from_formula(formula='value ~ 1 + invest + capital', data=df).fit(),
    '(3)': FamaMacBeth.from_formula(formula='value ~ 1 + invest + capital', data=df).fit(),
    '(4)': FamaMacBeth.from_formula(formula='value ~ 1 + invest + capital', data=df).fit()
}

display(compare(table))
comparrison = compare(table)
summary = comparrison.summary
print(summary.as_latex())

这会打印

\begin{center}
\begin{tabular}{lcccc}
\toprule
                               &         \textbf{(1)}        &         \textbf{(2)}        &         \textbf{(3)}        &         \textbf{(4)}         \
\midrule
\textbf{Dep. Variable}         &            value            &            value            &            value            &            value             \
\textbf{Estimator}             &         FamaMacBeth         &         FamaMacBeth         &         FamaMacBeth         &         FamaMacBeth          \
\textbf{No. Observations}      &             220             &             220             &             220             &             220              \
\textbf{Cov. Est.}             &  Fama-MacBeth Standard Cov  &  Fama-MacBeth Standard Cov  &  Fama-MacBeth Standard Cov  &  Fama-MacBeth Standard Cov   \
\textbf{R-squared}             &            0.6964           &            0.6964           &            0.6964           &            0.6964            \
\textbf{R-Squared (Within)}    &           -1.8012           &           -1.8012           &           -1.8012           &           -1.8012            \
\textbf{R-Squared (Between)}   &            0.8660           &            0.8660           &            0.8660           &            0.8660            \
\textbf{R-Squared (Overall)}   &            0.6964           &            0.6964           &            0.6964           &            0.6964            \
\textbf{F-statistic}           &            248.83           &            248.83           &            248.83           &            248.83            \
\textbf{P-value (F-stat)}      &            0.0000           &            0.0000           &            0.0000           &            0.0000            \
\textbf{=====================} & =========================== & =========================== & =========================== & ===========================  \
\textbf{Intercept}             &            114.16           &            114.16           &            114.16           &            114.16            \
\textbf{ }                     &           (3.8390)          &           (3.8390)          &           (3.8390)          &           (3.8390)           \
\textbf{capital}               &            0.1457           &            0.1457           &            0.1457           &            0.1457            \
\textbf{ }                     &           (0.8510)          &           (0.8510)          &           (0.8510)          &           (0.8510)           \
\textbf{invest}                &            6.3899           &            6.3899           &            6.3899           &            6.3899            \
\textbf{ }                     &           (11.618)          &           (11.618)          &           (11.618)          &           (11.618)           \
\bottomrule
\end{tabular}
%\caption{Model Comparison}
\end{center}

T-stats reported in parentheses

这是一个使用 Kevin S. 的 .summary.as_latex() 的替代方案。 下面的函数使用 compare().summary 创建一个数据框,jupyter nbconvert --to pdf 将其转换为 table.

from io import StringIO
import warnings

def compare_df(x, fit_stats=['Estimator', 'R-squared', 'No. Observations']):
    with warnings.catch_warnings():
        warnings.simplefilter(action='ignore', category=FutureWarning)
        y = pd.read_csv(StringIO(compare(x, stars=True).summary.as_csv()), skiprows=1, skipfooter=1, engine='python')
    z = pd.DataFrame(
        data=y.iloc[:, 1:].values,
        index=y.iloc[:, 0].str.strip(),
        columns=pd.MultiIndex.from_arrays(
            arrays=[y.columns[1:], y.iloc[0][1:]],
            names=['Model', 'Dep. Var.']
        )
    )
    return pd.concat([z.iloc[11:], z.loc[fit_stats]])

PDF 输出为:

请注意,此解决方案需要 pd.options.display.latex.repr = True