{ "cells": [ { "cell_type": "markdown", "metadata": { "collapsed": true, "pycharm": { "name": "#%% md\n" } }, "source": [ "# 2SLS Estimation Examples" ] }, { "cell_type": "markdown", "metadata": { "pycharm": { "name": "#%% md\n" } }, "source": [ "We demonstrate the use of 2SLS from the package to estimate the average treatment effect by semi-synthetic data and full synthetic data." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "ExecuteTime": { "end_time": "2020-06-22T18:34:07.556482Z", "start_time": "2020-06-22T18:34:07.075342Z" }, "pycharm": { "name": "#%%\n" } }, "outputs": [], "source": [ "%reload_ext autoreload\n", "%autoreload 2\n", "%matplotlib inline" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "ExecuteTime": { "end_time": "2020-06-22T18:34:08.026503Z", "start_time": "2020-06-22T18:34:07.998418Z" }, "pycharm": { "name": "#%%\n" } }, "outputs": [], "source": [ "import os\n", "base_path = os.path.abspath(\"../\")\n", "os.chdir(base_path)" ] }, { "cell_type": "code", "execution_count": 52, "metadata": { "ExecuteTime": { "end_time": "2020-06-22T19:20:57.201672Z", "start_time": "2020-06-22T19:20:57.102105Z" }, "pycharm": { "name": "#%%\n" } }, "outputs": [], "source": [ "import logging\n", "from matplotlib import pyplot as plt\n", "import numpy as np\n", "import pandas as pd\n", "import sys\n", "from scipy import stats" ] }, { "cell_type": "code", "execution_count": 39, "metadata": { "ExecuteTime": { "end_time": "2020-06-22T19:04:33.015381Z", "start_time": "2020-06-22T19:04:32.964582Z" }, "pycharm": { "name": "#%%\n" } }, "outputs": [], "source": [ "import causalml\n", "from causalml.inference.iv import IVRegressor\n", "from sklearn.preprocessing import StandardScaler\n", "import statsmodels.api as sm" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Semi-Synthetic Data from NLSYM" ] }, { "cell_type": "markdown", "metadata": { "ExecuteTime": { "end_time": "2020-06-22T19:32:40.653280Z", "start_time": "2020-06-22T19:32:40.595806Z" } }, "source": [ "The data generation mechanism is described in Syrgkanis et al \"*Machine Learning Estimation of Heterogeneous Treatment Effects with Instruments*\" (2019)." ] }, { "cell_type": "markdown", "metadata": { "pycharm": { "name": "#%% md\n" } }, "source": [ "### Data Loading" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "ExecuteTime": { "end_time": "2020-06-22T18:34:16.787310Z", "start_time": "2020-06-22T18:34:16.720144Z" }, "pycharm": { "name": "#%%\n" } }, "outputs": [], "source": [ "df = pd.read_csv(\"examples/data/card.csv\")" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "ExecuteTime": { "end_time": "2020-06-22T18:34:17.310674Z", "start_time": "2020-06-22T18:34:17.231429Z" }, "pycharm": { "name": "#%%\n" } }, "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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
idnearc2nearc4educagefatheducmotheducweightmomdad14sinmom14...smsa66wageenrollkwwiqmarriedlibcrd14experlwageexpersq
0200729NaNNaN15841310...1548015.0NaN1.00.0166.306275256
130012278.08.038016610...1481035.093.01.01.096.17586781
2400123414.012.036747010...1721042.0103.01.01.0166.580639256
3511112711.012.038016610...1250025.088.01.01.0105.521461100
461112348.07.036747010...1729034.0108.01.00.0166.591674256
\n", "

5 rows × 34 columns

\n", "
" ], "text/plain": [ " id nearc2 nearc4 educ age fatheduc motheduc weight momdad14 \\\n", "0 2 0 0 7 29 NaN NaN 158413 1 \n", "1 3 0 0 12 27 8.0 8.0 380166 1 \n", "2 4 0 0 12 34 14.0 12.0 367470 1 \n", "3 5 1 1 11 27 11.0 12.0 380166 1 \n", "4 6 1 1 12 34 8.0 7.0 367470 1 \n", "\n", " sinmom14 ... smsa66 wage enroll kww iq married libcrd14 exper \\\n", "0 0 ... 1 548 0 15.0 NaN 1.0 0.0 16 \n", "1 0 ... 1 481 0 35.0 93.0 1.0 1.0 9 \n", "2 0 ... 1 721 0 42.0 103.0 1.0 1.0 16 \n", "3 0 ... 1 250 0 25.0 88.0 1.0 1.0 10 \n", "4 0 ... 1 729 0 34.0 108.0 1.0 0.0 16 \n", "\n", " lwage expersq \n", "0 6.306275 256 \n", "1 6.175867 81 \n", "2 6.580639 256 \n", "3 5.521461 100 \n", "4 6.591674 256 \n", "\n", "[5 rows x 34 columns]" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.head()" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "ExecuteTime": { "end_time": "2020-06-22T18:34:17.900311Z", "start_time": "2020-06-22T18:34:17.855260Z" }, "pycharm": { "name": "#%%\n" } }, "outputs": [ { "data": { "text/plain": [ "array(['id', 'nearc2', 'nearc4', 'educ', 'age', 'fatheduc', 'motheduc',\n", " 'weight', 'momdad14', 'sinmom14', 'step14', 'reg661', 'reg662',\n", " 'reg663', 'reg664', 'reg665', 'reg666', 'reg667', 'reg668',\n", " 'reg669', 'south66', 'black', 'smsa', 'south', 'smsa66', 'wage',\n", " 'enroll', 'kww', 'iq', 'married', 'libcrd14', 'exper', 'lwage',\n", " 'expersq'], dtype=object)" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.columns.values\n" ] }, { "cell_type": "code", "execution_count": 30, "metadata": { "ExecuteTime": { "end_time": "2020-06-22T19:02:35.660584Z", "start_time": "2020-06-22T19:02:35.515002Z" }, "pycharm": { "name": "#%%\n" } }, "outputs": [], "source": [ "data_filter = df['educ'] >= 6\n", "# outcome variable\n", "y=df[data_filter]['lwage'].values\n", "# treatment variable\n", "treatment=df[data_filter]['educ'].values\n", "# instrumental variable\n", "w=df[data_filter]['nearc4'].values\n", "\n", "Xdf=df[data_filter][['fatheduc', 'motheduc', 'momdad14', 'sinmom14', 'reg661', 'reg662',\n", " 'reg663', 'reg664', 'reg665', 'reg666', 'reg667', 'reg668',\n", " 'reg669', 'south66', 'black', 'smsa', 'south', 'smsa66',\n", " 'exper', 'expersq']]\n", "Xdf['fatheduc']=Xdf['fatheduc'].fillna(value=Xdf['fatheduc'].mean())\n", "Xdf['motheduc']=Xdf['motheduc'].fillna(value=Xdf['motheduc'].mean())\n", "Xscale=Xdf.copy()\n", "Xscale[['fatheduc', 'motheduc', 'exper', 'expersq']]=StandardScaler().fit_transform(Xscale[['fatheduc', 'motheduc', 'exper', 'expersq']])\n", "X=Xscale.values" ] }, { "cell_type": "code", "execution_count": 32, "metadata": { "ExecuteTime": { "end_time": "2020-06-22T19:02:47.412463Z", "start_time": "2020-06-22T19:02:47.251852Z" }, "pycharm": { "name": "#%%\n" } }, "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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
fatheducmotheducmomdad14sinmom14reg661reg662reg663reg664reg665reg666reg667reg668reg669south66blacksmsasouthsmsa66experexpersq
count2.991000e+032.991000e+032991.0000002991.0000002991.0000002991.0000002991.0000002991.0000002991.0000002991.0000002991.0000002991.0000002991.0000002991.0000002991.0000002991.0000002991.0000002991.0000002.991000e+032.991000e+03
mean-3.529069e-16-1.704346e-150.7903710.1003010.0468070.1614840.1969240.0645270.2059510.0949520.1099970.0284190.0909390.4108990.2313610.7151450.4002010.6516224.285921e-163.040029e-17
std1.000167e+001.000167e+000.4071120.3004510.2112610.3680390.3977410.2457300.4044630.2931970.3129380.1661930.2875710.4920790.4217730.4514210.4900210.4765361.000167e+001.000167e+00
min-3.101056e+00-3.502453e+000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.000000-2.159127e+00-1.147691e+00
25%-6.303764e-01-4.656485e-011.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.000000-6.858865e-01-7.077287e-01
50%0.000000e+002.091970e-011.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000001.0000000.0000001.000000-1.948066e-01-3.655360e-01
75%6.049634e-015.466197e-011.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000000.0000001.0000000.0000001.0000001.0000001.0000005.418134e-013.310707e-01
max2.457973e+002.571156e+001.0000001.0000001.0000001.0000001.0000001.0000001.0000001.0000001.0000001.0000001.0000001.0000001.0000001.0000001.0000001.0000003.242753e+004.767355e+00
\n", "
" ], "text/plain": [ " fatheduc motheduc momdad14 sinmom14 reg661 \\\n", "count 2.991000e+03 2.991000e+03 2991.000000 2991.000000 2991.000000 \n", "mean -3.529069e-16 -1.704346e-15 0.790371 0.100301 0.046807 \n", "std 1.000167e+00 1.000167e+00 0.407112 0.300451 0.211261 \n", "min -3.101056e+00 -3.502453e+00 0.000000 0.000000 0.000000 \n", "25% -6.303764e-01 -4.656485e-01 1.000000 0.000000 0.000000 \n", "50% 0.000000e+00 2.091970e-01 1.000000 0.000000 0.000000 \n", "75% 6.049634e-01 5.466197e-01 1.000000 0.000000 0.000000 \n", "max 2.457973e+00 2.571156e+00 1.000000 1.000000 1.000000 \n", "\n", " reg662 reg663 reg664 reg665 reg666 \\\n", "count 2991.000000 2991.000000 2991.000000 2991.000000 2991.000000 \n", "mean 0.161484 0.196924 0.064527 0.205951 0.094952 \n", "std 0.368039 0.397741 0.245730 0.404463 0.293197 \n", "min 0.000000 0.000000 0.000000 0.000000 0.000000 \n", "25% 0.000000 0.000000 0.000000 0.000000 0.000000 \n", "50% 0.000000 0.000000 0.000000 0.000000 0.000000 \n", "75% 0.000000 0.000000 0.000000 0.000000 0.000000 \n", "max 1.000000 1.000000 1.000000 1.000000 1.000000 \n", "\n", " reg667 reg668 reg669 south66 black \\\n", "count 2991.000000 2991.000000 2991.000000 2991.000000 2991.000000 \n", "mean 0.109997 0.028419 0.090939 0.410899 0.231361 \n", "std 0.312938 0.166193 0.287571 0.492079 0.421773 \n", "min 0.000000 0.000000 0.000000 0.000000 0.000000 \n", "25% 0.000000 0.000000 0.000000 0.000000 0.000000 \n", "50% 0.000000 0.000000 0.000000 0.000000 0.000000 \n", "75% 0.000000 0.000000 0.000000 1.000000 0.000000 \n", "max 1.000000 1.000000 1.000000 1.000000 1.000000 \n", "\n", " smsa south smsa66 exper expersq \n", "count 2991.000000 2991.000000 2991.000000 2.991000e+03 2.991000e+03 \n", "mean 0.715145 0.400201 0.651622 4.285921e-16 3.040029e-17 \n", "std 0.451421 0.490021 0.476536 1.000167e+00 1.000167e+00 \n", "min 0.000000 0.000000 0.000000 -2.159127e+00 -1.147691e+00 \n", "25% 0.000000 0.000000 0.000000 -6.858865e-01 -7.077287e-01 \n", "50% 1.000000 0.000000 1.000000 -1.948066e-01 -3.655360e-01 \n", "75% 1.000000 1.000000 1.000000 5.418134e-01 3.310707e-01 \n", "max 1.000000 1.000000 1.000000 3.242753e+00 4.767355e+00 " ] }, "execution_count": 32, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Xscale.describe()\n" ] }, { "cell_type": "markdown", "metadata": { "pycharm": { "name": "#%% md\n" } }, "source": [ "### Semi-Synthetic Data Generation" ] }, { "cell_type": "code", "execution_count": 29, "metadata": { "ExecuteTime": { "end_time": "2020-06-22T19:00:36.976866Z", "start_time": "2020-06-22T19:00:36.929353Z" }, "pycharm": { "name": "#%%\n" } }, "outputs": [], "source": [ "def semi_synth_nlsym(X, w, random_seed=None):\n", " np.random.seed(random_seed)\n", " nobs = X.shape[0]\n", " nv = np.random.uniform(0, 1, size=nobs)\n", " c0 = np.random.uniform(0.2, 0.3)\n", " C = c0 * X[:,1]\n", " # Treatment compliance depends on mother education\n", " treatment = C * w + X[:,1] + nv\n", " # Treatment effect depends no mother education and single-mom family at age 14\n", " theta = 0.1 + 0.05 * X[:,1] - 0.1*X[:,3]\n", " # Additional effect on the outcome from mother education\n", " f = 0.05 * X[:,1]\n", " y = theta * (treatment + nv) + f + np.random.normal(0, 0.1, size=nobs)\n", " \n", " return y, treatment, theta" ] }, { "cell_type": "code", "execution_count": 33, "metadata": { "ExecuteTime": { "end_time": "2020-06-22T19:02:58.593481Z", "start_time": "2020-06-22T19:02:58.548556Z" } }, "outputs": [], "source": [ "y_sim, treatment_sim, theta = semi_synth_nlsym(Xdf.values, w)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Estimation" ] }, { "cell_type": "code", "execution_count": 36, "metadata": { "ExecuteTime": { "end_time": "2020-06-22T19:03:22.190936Z", "start_time": "2020-06-22T19:03:22.118980Z" } }, "outputs": [ { "data": { "text/plain": [ "0.6089706667314586" ] }, "execution_count": 36, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# True value\n", "theta.mean()" ] }, { "cell_type": "code", "execution_count": 38, "metadata": { "ExecuteTime": { "end_time": "2020-06-22T19:03:30.561613Z", "start_time": "2020-06-22T19:03:30.501630Z" } }, "outputs": [ { "data": { "text/plain": [ "(0.6611532131769402, 0.013922622951893662)" ] }, "execution_count": 38, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# 2SLS estimate\n", "iv_fit = IVRegressor()\n", "iv_fit.fit(X, treatment_sim, y_sim, w)\n", "ate, ate_sd = iv_fit.predict()\n", "(ate, ate_sd)" ] }, { "cell_type": "code", "execution_count": 51, "metadata": { "ExecuteTime": { "end_time": "2020-06-22T19:07:04.924847Z", "start_time": "2020-06-22T19:07:04.875455Z" } }, "outputs": [ { "data": { "text/plain": [ "(0.7501211540497275, 0.012800163754977008)" ] }, "execution_count": 51, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# OLS estimate\n", "ols_fit=sm.OLS(y_sim, sm.add_constant(np.c_[treatment_sim, X], prepend=False)).fit()\n", "(ols_fit.params[0], ols_fit.bse[0])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Pure Synthetic Data" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The data generation mechanism is described in Hong et al \"*Semiparametric Efficiency in Nonlinear LATE Models*\" (2010)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Data Generation" ] }, { "cell_type": "code", "execution_count": 54, "metadata": { "ExecuteTime": { "end_time": "2020-06-22T19:25:40.879421Z", "start_time": "2020-06-22T19:25:40.825352Z" } }, "outputs": [], "source": [ "def synthetic_data(n=10000, random_seed=None):\n", " np.random.seed(random_seed)\n", " gamma0 = -0.5\n", " gamma1 = 1.0\n", " delta = 1.0\n", " x = np.random.uniform(size=n)\n", " v = np.random.normal(size=n)\n", " d1 = (gamma0 + x*gamma1 + delta + v>=0).astype(float)\n", " d0 = (gamma0 + x*gamma1 + v>=0).astype(float)\n", " \n", " alpha = 1.0\n", " beta = 0.5\n", " lambda11 = 2.0\n", " lambda00 = 1.0\n", " xi1 = np.random.poisson(np.exp(alpha+x*beta))\n", " xi2 = np.random.poisson(np.exp(x*beta))\n", " xi3 = np.random.poisson(np.exp(lambda11), size=n)\n", " xi4 = np.random.poisson(np.exp(lambda00), size=n)\n", " \n", " y1 = xi1 + xi3 * ((d1==1) & (d0==1)) + xi4 * ((d1==0) & (d0==0))\n", " y0 = xi2 + xi3 * ((d1==1) & (d0==1)) + xi4 * ((d1==0) & (d0==0))\n", " \n", " z = np.random.binomial(1, stats.norm.cdf(x))\n", " d = d1*z + d0*(1-z)\n", " y = y1*d + y0*(1-d)\n", " \n", " return y, x, d, z, y1[(d1>d0)].mean()-y0[(d1>d0)].mean()" ] }, { "cell_type": "code", "execution_count": 55, "metadata": { "ExecuteTime": { "end_time": "2020-06-22T19:25:45.345780Z", "start_time": "2020-06-22T19:25:45.287971Z" } }, "outputs": [], "source": [ "y, x, d, z, late = synthetic_data()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Estimation" ] }, { "cell_type": "code", "execution_count": 56, "metadata": { "ExecuteTime": { "end_time": "2020-06-22T19:26:26.235823Z", "start_time": "2020-06-22T19:26:26.191466Z" } }, "outputs": [ { "data": { "text/plain": [ "2.1789099526066353" ] }, "execution_count": 56, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# True value\n", "late" ] }, { "cell_type": "code", "execution_count": 57, "metadata": { "ExecuteTime": { "end_time": "2020-06-22T19:26:48.455795Z", "start_time": "2020-06-22T19:26:48.402675Z" } }, "outputs": [ { "data": { "text/plain": [ "(2.1900472390231775, 0.2623695460540134)" ] }, "execution_count": 57, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# 2SLS estimate\n", "iv_fit = IVRegressor()\n", "iv_fit.fit(x, d, y, z)\n", "ate, ate_sd = iv_fit.predict()\n", "(ate, ate_sd)" ] }, { "cell_type": "code", "execution_count": 59, "metadata": { "ExecuteTime": { "end_time": "2020-06-22T19:27:33.354806Z", "start_time": "2020-06-22T19:27:33.307105Z" } }, "outputs": [ { "data": { "text/plain": [ "(5.3482879532439975, 0.09201397327077365)" ] }, "execution_count": 59, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# OLS estimate\n", "ols_fit=sm.OLS(y, sm.add_constant(np.c_[d, x], prepend=False)).fit()\n", "(ols_fit.params[0], ols_fit.bse[0])" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.8" }, "toc": { "base_numbering": 1, "nav_menu": {}, "number_sections": true, "sideBar": true, "skip_h1_title": false, "title_cell": "Table of Contents", "title_sidebar": "Contents", "toc_cell": false, "toc_position": {}, "toc_section_display": true, "toc_window_display": false } }, "nbformat": 4, "nbformat_minor": 1 }