diff --git a/.coverage b/.coverage index cdebb149..2599c7be 100644 Binary files a/.coverage and b/.coverage differ diff --git a/docs/stargazer.ipynb b/docs/stargazer.ipynb index 0b6e1371..da6da198 100644 --- a/docs/stargazer.ipynb +++ b/docs/stargazer.ipynb @@ -25,7 +25,7 @@ "data": { "text/html": [ "\n", - "
\n", + "
\n", " \n", @@ -65,7 +65,7 @@ "data": { "text/html": [ "\n", - "
\n", + "
\n", " \n", @@ -143,124 +143,124 @@ "data": { "text/html": [ "\n", - "\n", + "
\n", " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", "
Significance levels: * p < 0.05, ** p < 0.01, *** p < 0.001. Format of coefficient cell:\n", "Coefficient (Std. Error)
est1est2est3est4est5est1est2est3est4est5
depvarYYYYYdepvarYYYYY
X1-0.949*** (0.069)-0.919*** (0.065)-0.950*** (0.067)-0.924*** (0.061)-0.924*** (0.061)X1-0.949*** (0.069)-0.919*** (0.065)-0.950*** (0.067)-0.924*** (0.061)-0.924*** (0.061)
X2-0.174*** (0.018)-0.174*** (0.015)-0.185*** (0.025)X2-0.174*** (0.018)-0.174*** (0.015)-0.185*** (0.025)
X1:X20.011 (0.018)X1:X20.011 (0.018)
f2-x-xxf1xxxxx
f1xxxxxf2-x-xx
R20.4370.6090.4890.6590.659R20.4370.6090.4890.6590.659
S.E. typeby: f1by: f1by: f1by: f1by: f1S.E. typeby: f1by: f1by: f1by: f1by: f1
Observations997997997997997Observations997997997997997
\n" ], "text/plain": [ - "" + "" ] }, "execution_count": 2, @@ -288,116 +288,116 @@ "data": { "text/html": [ "\n", - "\n", + "
\n", " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", "
Significance levels: * p < 0.05, ** p < 0.01, *** p < 0.001. Format of coefficient cell:\n", "Coefficient (Std. Error)
est1est2est3est4est5est1est2est3est4est5
depvarYYYYYdepvarYYYYY
X1-0.949*** (0.069)-0.919*** (0.065)-0.950*** (0.067)-0.924*** (0.061)-0.924*** (0.061)X1-0.949*** (0.069)-0.919*** (0.065)-0.950*** (0.067)-0.924*** (0.061)-0.924*** (0.061)
X1:X20.011 (0.018)X1:X20.011 (0.018)
f2-x-xxf1xxxxx
f1xxxxxf2-x-xx
R20.4370.6090.4890.6590.659R20.4370.6090.4890.6590.659
S.E. typeby: f1by: f1by: f1by: f1by: f1S.E. typeby: f1by: f1by: f1by: f1by: f1
Observations997997997997997Observations997997997997997
\n" ], "text/plain": [ - "" + "" ] }, "execution_count": 3, @@ -425,116 +425,116 @@ "data": { "text/html": [ "\n", - "\n", + "
\n", " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", "
Significance levels: * p < 0.05, ** p < 0.01, *** p < 0.001. Format of coefficient cell:\n", "Coefficient (Std. Error)
est1est2est3est4est5est1est2est3est4est5
depvarYYYYYdepvarYYYYY
X1-0.949*** (0.069)-0.919*** (0.065)-0.950*** (0.067)-0.924*** (0.061)-0.924*** (0.061)X1-0.949*** (0.069)-0.919*** (0.065)-0.950*** (0.067)-0.924*** (0.061)-0.924*** (0.061)
X2-0.174*** (0.018)-0.174*** (0.015)-0.185*** (0.025)X2-0.174*** (0.018)-0.174*** (0.015)-0.185*** (0.025)
f2-x-xxf1xxxxx
f1xxxxxf2-x-xx
R20.4370.6090.4890.6590.659R20.4370.6090.4890.6590.659
S.E. typeby: f1by: f1by: f1by: f1by: f1S.E. typeby: f1by: f1by: f1by: f1by: f1
Observations997997997997997Observations997997997997997
\n" ], "text/plain": [ - "" + "" ] }, "execution_count": 4, @@ -562,108 +562,108 @@ "data": { "text/html": [ "\n", - "\n", + "
\n", " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", "
Significance levels: * p < 0.05, ** p < 0.01, *** p < 0.001. Format of coefficient cell:\n", "Coefficient (Std. Error)
est1est2est3est4est5est1est2est3est4est5
depvarYYYYYdepvarYYYYY
X2-0.174*** (0.018)-0.174*** (0.015)-0.185*** (0.025)X2-0.174*** (0.018)-0.174*** (0.015)-0.185*** (0.025)
f2-x-xxf1xxxxx
f1xxxxxf2-x-xx
R20.4370.6090.4890.6590.659R20.4370.6090.4890.6590.659
S.E. typeby: f1by: f1by: f1by: f1by: f1S.E. typeby: f1by: f1by: f1by: f1by: f1
Observations997997997997997Observations997997997997997
\n" ], "text/plain": [ - "" + "" ] }, "execution_count": 5, @@ -692,124 +692,124 @@ "data": { "text/html": [ "\n", - "\n", + "
\n", " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", "
Significance levels: * p < 0.05, ** p < 0.01, *** p < 0.001. Format of coefficient cell:\n", "Coefficient (Std. Error) [p-value]
est1est2est3est4est5est1est2est3est4est5
depvarYYYYYdepvarYYYYY
X1-0.949*** (0.069) [0.000]-0.919*** (0.065) [0.000]-0.950*** (0.067) [0.000]-0.924*** (0.061) [0.000]-0.924*** (0.061) [0.000]X1-0.949*** (0.069) [0.000]-0.919*** (0.065) [0.000]-0.950*** (0.067) [0.000]-0.924*** (0.061) [0.000]-0.924*** (0.061) [0.000]
X2-0.174*** (0.018) [0.000]-0.174*** (0.015) [0.000]-0.185*** (0.025) [0.000]X2-0.174*** (0.018) [0.000]-0.174*** (0.015) [0.000]-0.185*** (0.025) [0.000]
X1:X20.011 (0.018) [0.565]X1:X20.011 (0.018) [0.565]
f2-x-xxf1xxxxx
f1xxxxxf2-x-xx
R20.4370.6090.4890.6590.659R20.4370.6090.4890.6590.659
S.E. typeby: f1by: f1by: f1by: f1by: f1S.E. typeby: f1by: f1by: f1by: f1by: f1
Observations997997997997997Observations997997997997997
\n" ], "text/plain": [ - "" + "" ] }, "execution_count": 6, @@ -838,124 +838,124 @@ "data": { "text/html": [ "\n", - "\n", + "
\n", " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", " \n", " \n", "
Significance levels: * p < 0.1, ** p < 0.05, *** p < 0.01. Format of coefficient cell:\n", "Coefficient (Std. Error)
est1est2est3est4est5est1est2est3est4est5
depvarYYYYYdepvarYYYYY
X1-0.94944*** (0.06886)-0.91925*** (0.06539)-0.94953*** (0.06652)-0.92405*** (0.06093)-0.92417*** (0.06094)X1-0.94944*** (0.06886)-0.91925*** (0.06539)-0.94953*** (0.06652)-0.92405*** (0.06093)-0.92417*** (0.06094)
X2-0.17423*** (0.01840)-0.17411*** (0.01461)-0.18550*** (0.02516)X2-0.17423*** (0.01840)-0.17411*** (0.01461)-0.18550*** (0.02516)
X1:X20.01057 (0.01818)X1:X20.01057 (0.01818)
f2-x-xxf1xxxxx
f1xxxxxf2-x-xx
R20.437080.609030.488990.659040.65916R20.437080.609030.488990.659040.65916
S.E. typeby: f1by: f1by: f1by: f1by: f1S.E. typeby: f1by: f1by: f1by: f1by: f1
Observations997997997997997Observations997997997997997
\n" ], "text/plain": [ - "" + "" ] }, "execution_count": 7, @@ -991,8 +991,8 @@ "X2 -0.17423*** (0.01840) -0.17411*** (0.01461) -0.18550*** (0.02516)\n", "X1:X2 0.01057 (0.01818)\n", "-------------------------------------------------------------------------------------------------------------------------------\n", - "f2 - x - x x\n", "f1 x x x x x\n", + "f2 - x - x x\n", "-------------------------------------------------------------------------------------------------------------------------------\n", "R2 0.43708 0.60903 0.48899 0.65904 0.65916\n", "S.E. type by: f1 by: f1 by: f1 by: f1 by: f1\n", @@ -1008,6 +1008,305 @@ "pf.etable([fit1, fit2, fit3, fit4, fit5], signif_code=[0.01, 0.05, 0.1], digits = 5, type = \"md\")" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "You can also rename variables if you want to have a more readable output. Just pass a dictionary to the `labels` argument. Note that interaction terms will also be relabeled using the specified labels for the interacted variables (if you want to manually relabel an interaction term differently, add it to the dictionary)." + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Significance levels: * p < 0.05, ** p < 0.01, *** p < 0.001. Format of coefficient cell:\n", + "Coefficient (Std. Error)
est1est2est3est4est5
depvarWageWageWageWageWage
Age-0.949*** (0.069)-0.919*** (0.065)-0.950*** (0.067)-0.924*** (0.061)-0.924*** (0.061)
Years of Schooling-0.174*** (0.018)-0.174*** (0.015)-0.185*** (0.025)
Age × Years of Schooling0.011 (0.018)
Industryxxxxx
Year-x-xx
R20.4370.6090.4890.6590.659
S.E. typeby: f1by: f1by: f1by: f1by: f1
Observations997997997997997
\n" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "labels={\n", + " \"X1\": \"Age\",\n", + " \"X2\": \"Years of Schooling\",\n", + " \"Y\": \"Wage\",\n", + " \"f1\": \"Industry\",\n", + " \"f2\": \"Year\"\n", + "}\n", + "\n", + "pf.etable([fit1, fit2, fit3, fit4, fit5], labels=labels)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If you want to label the rows indicating the inclusion of fixed effects not with the variable label but with a custom label, you can pass on a separate dictionary to the `felabels` argument." + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Significance levels: * p < 0.05, ** p < 0.01, *** p < 0.001. Format of coefficient cell:\n", + "Coefficient (Std. Error)
est1est2est3est4est5
depvarWageWageWageWageWage
Age-0.949*** (0.069)-0.919*** (0.065)-0.950*** (0.067)-0.924*** (0.061)-0.924*** (0.061)
Years of Schooling-0.174*** (0.018)-0.174*** (0.015)-0.185*** (0.025)
Age × Years of Schooling0.011 (0.018)
Industry Fixed Effectsxxxxx
Year Fixed Effects-x-xx
R20.4370.6090.4890.6590.659
S.E. typeby: f1by: f1by: f1by: f1by: f1
Observations997997997997997
\n" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\n", + "pf.etable([fit1, fit2, fit3, fit4, fit5], labels=labels, felabels={\"f1\": \"Industry Fixed Effects\", \"f2\": \"Year Fixed Effects\"})" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -1032,9 +1331,20 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 10, "metadata": {}, "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "rmse1.7296950763721533\n", + "rmse1.4414995715974865\n", + "rmse1.6480033852100044\n", + "rmse1.3461516723563165\n", + "rmse1.3459213070070806\n" + ] + }, { "data": { "text/html": [ @@ -1050,14 +1360,14 @@ "(0.018)(0.015)(0.025)\n", "\n", "\n", - "Observations997997997997997R20.4370.6090.4890.6590.659\n", + "Observations997997997997997R20.4370.6090.4890.6590.659Adjusted R2nannannannannan\n", "Note:*p<0.1; **p<0.05; ***p<0.01" ], "text/plain": [ - "" + "" ] }, - "execution_count": 9, + "execution_count": 10, "metadata": {}, "output_type": "execute_result" } @@ -1076,7 +1386,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 11, "metadata": {}, "outputs": [], "source": [ @@ -1086,7 +1396,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 12, "metadata": {}, "outputs": [ { @@ -1104,14 +1414,14 @@ "(0.018)(0.015)(0.025)\n", "\n", "\n", - "Fixed Effectsf1f1+f2f1f1+f2f1+f2X1: Romano-Wolf P-Value0.00.00.00.00.0Observations997997997997997R20.4370.6090.4890.6590.659\n", + "Fixed Effectsf1f1+f2f1f1+f2f1+f2X1: Romano-Wolf P-Value0.00.00.00.00.0Observations997997997997997R20.4370.6090.4890.6590.659Adjusted R2nannannannannan\n", "Note:*p<0.1; **p<0.05; ***p<0.01" ], "text/plain": [ - "" + "" ] }, - "execution_count": 11, + "execution_count": 12, "metadata": {}, "output_type": "execute_result" } @@ -1146,7 +1456,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.8" + "version": "3.9.13" } }, "nbformat": 4, diff --git a/pyfixest/report/summarize.py b/pyfixest/report/summarize.py index f16391d3..9c21fc38 100644 --- a/pyfixest/report/summarize.py +++ b/pyfixest/report/summarize.py @@ -21,6 +21,8 @@ def etable( keep: Optional[Union[list, str]] = None, drop: Optional[Union[list, str]] = None, exact_match: Optional[bool] = False, + labels: Optional[dict] = None, + felabels: Optional[dict] = None, **kwargs, ) -> Union[pd.DataFrame, str, None]: r""" @@ -60,6 +62,16 @@ def etable( Whether to use exact match for `keep` and `drop`. Default is False. If True, the pattern will be matched exactly to the coefficient name instead of using regular expressions. + labels: dict, optional + A dictionary to relabel the variables. The keys are the original variable + names and the values the new names. Note that interaction terms will also be + relabeled using the labels of the individual variables. + The command is applied after the `keep` and `drop` commands. + felabels: dict, optional + A dictionary to relabel the fixed effects. Only needed if you want to relabel + the FE lines with a different label than the one specied for the respective + variable in the labels dictionary. + The command is applied after the `keep` and `drop` commands. digits: int The number of digits to round to. thousands_sep: bool, optional @@ -249,6 +261,36 @@ def etable( res.rename(columns={"Coefficient": "index"}, inplace=True) nobs_fixef_df.columns = res.columns + if labels is not None: + # Relabel dependent variables + dep_var_list = [labels.get(k, k) for k in dep_var_list] + + # Set symbol for interaction terms depending on output type + if type in ["df", "html"]: + interactionSymbol = " × " + elif type == "tex": + interactionSymbol = " $\\times$ " + else: + interactionSymbol = " x " + + # Relabel explanatory variables + res["index"] = res["index"].apply( + lambda x: _relabel_expvar(x, labels, interactionSymbol) + ) + + # Relabel fixed effects + if felabels is not None: + # When the user provides a dictionary for fixed effects, then use it + # When a corresponsing variable is not in the felabel dictionary, then use the labels dictionary + # When in neither then just use the original variable name + nobs_fixef_df["index"] = nobs_fixef_df["index"].apply( + lambda x: felabels.get(x, labels.get(x, x)) + ) + else: + nobs_fixef_df["index"] = nobs_fixef_df["index"].apply( + lambda x: labels.get(x, x) + ) + depvars = pd.DataFrame({"depvar": dep_var_list}).T.reset_index() depvars.columns = res.columns @@ -601,3 +643,33 @@ def _number_formatter(x: float, **kwargs) -> str: _int, _float = str(x_str).split(".") _float = _float.ljust(digits, "0") return _int if digits == 0 else f"{_int}.{_float}" + + +def _relabel_expvar(varname: str, labels: dict, interaction_symbol: str): + """ + Relabel a variable name using the labels dictionary + Also automatically relabel interaction terms using the labels of the individual variables. + + Parameters + ---------- + varname: str + The varname in the regression. + labels: dict + A dictionary to relabel the variables. The keys are the original variable names and the values the new names. + interaction_symbol: str + The symbol to use for displaying the interaction term. + + Returns + ------- + str + The relabeled variable + """ + # When varname in labels dictionary, then relabel (note: this allows also to manually rename interaction terms in the dictionary) + # Otherwise: When interaction term, then split by vars, relabel, and join using interaction symbol + if varname in labels: + return labels[varname] + elif ":" in varname: + vars = varname.split(":") + relabeled_vars = [labels.get(v, v) for v in vars] + return interaction_symbol.join(relabeled_vars) + return varname diff --git a/tests/test_summarise.py b/tests/test_summarise.py index 9babd96a..6e04d367 100644 --- a/tests/test_summarise.py +++ b/tests/test_summarise.py @@ -17,6 +17,7 @@ def test_summary(): df2 = get_data(model="Fepois") fit1 = feols("Y ~ X1 + X2 | f1", data=df1) + fit1a = feols("Y ~ X1 + X2 + f1", data=df1) fit2 = fepois("Y ~ X1 + X2 + f2 | f1", data=df2, vcov={"CRV1": "f1+f2"}) fit3 = feols("Y ~ X1", data=df1) fit4 = feols("Y ~ X1", data=df1, weights="weights") @@ -88,6 +89,16 @@ def test_summary(): etable([fit1, fit2, fit3], coef_fmt="b (se)\nt [p]", keep="X") etable([fit1, fit2, fit3], coef_fmt="b (se)\nt [p]", drop=r"\d$") + # test labels, felabels args + etable([fit1, fit1a], labels={"X1": "X1_label"}, felabels={"f1": "f1_label"}) + etable( + [fit1, fit1a], labels={"X1": "X1_label"}, felabels={"f1": "f1_label"}, keep="X1" + ) + etable( + [fit1, fit1a], labels={"X1": "X1_label"}, felabels={"f1": "f1_label"}, drop="X1" + ) + etable([fit1, fit1a], felabels={"f1": "f1_renamed2"}, keep=["f1"]) + cols = ["x1", "x2", "x11", "x21"] assert _select_order_coefs(cols, keep=["x1"]) == ["x1", "x11"] assert _select_order_coefs(cols, drop=["x1"]) == ["x2", "x21"]