Package: pymalts2
IntroductionPyMALTS is a learning-to-matching interpretable causal inference method. PyMALTS implements MALTS algorithm proposed by Harsh Parikh, Cynthia Rudin and Alexander Volfovsky in their 2019 paper titled "MALTS: Matching After Learning to Stretch"DependenciesPyMALTS is a Python3 library and it requires Numpy, Pandas, Scipy, Scikit-Learn, Matplotlib and Seaborn.importpymaltsimportnumpyasnpimportpandasaspdimportmatplotlib.pyplotaspltimportseabornassnsnp.random.seed(0)sns.set()Reading Datadf=pd.read_csv('example/example_data.csv',index_col=0)print(df.shape)df.head()(2500, 20)X1X2X3X4X5X6X7X8X9X10X11X12X13X14X15X16X17X18outcometreated13551.8813351.6841640.5323322.0022541.4350321.4501961.9747631.3216590.709443-1.1412440.8831300.9567212.4982292.2516770.375271-0.5451293.3342200.081259-15.679894013200.6664761.2630650.6575580.4987801.0961351.0025690.8819160.7403922.780857-0.7658891.230980-1.214324-0.0400291.5544774.2355133.5962130.9590220.513409-7.06858701233-0.1932000.9618231.6527231.1173160.5903180.5667650.7757150.938379-2.0551241.942873-0.6060743.329552-1.8229383.2409452.1061210.8571900.577264-2.370578-5.13320007061.3786601.7946250.7011581.8155181.1299201.1884770.8450631.2172705.8473790.566517-0.0456070.7362300.9416770.835420-0.5603880.4272552.239003-0.63283239.68498414380.4342970.2966560.5457850.1103660.151758-0.2573260.6019650.499884-0.973684-0.552586-0.7784770.9369560.8311052.0600403.1537990.0276650.376857-1.221457-2.9543240Using MALTSDistance Metric LearningSetting up the model for learning the distance metric.Variable name for the outcome variable: 'outcome'.Variable name for the treatment variable: 'treated'Data is assigned to python variable dfm=pymalts.malts_mf(outcome='outcome',treatment='treated',data=df)# running MALTS with default settingMatched GroupsMatched Group matrix (MG_matrix) is NxN matrix with each row corresponding to each query unit and each column corresponds to matched units. Cell (i,j) in the matrix corresponds to the weight of unit j in the matched group of unit i. The weight corresponds to the numbers of times a unit is included in a matched group across M-folds.m.MG_matrix13551320123370643818411081612816131...1181169891659226715201408909603228513554.00.00.02.00.00.00.00.00.00.0...0.00.00.00.00.00.00.03.00.03.013200.04.00.00.00.00.00.01.04.00.0...0.00.00.00.00.00.00.00.00.00.012330.00.04.00.00.00.00.00.00.00.0...0.00.00.00.00.00.00.00.00.00.07060.00.00.04.00.00.00.01.00.00.0...0.00.00.00.00.00.00.01.00.00.04380.00.00.00.04.00.00.00.00.00.0...0.00.00.00.00.01.00.00.00.00.0..................................................................15200.00.00.00.02.00.00.00.00.00.0...0.00.00.00.00.04.00.00.00.00.014080.00.00.00.00.00.00.00.03.00.0...0.00.00.00.00.00.04.00.00.00.09090.00.00.01.00.00.00.00.00.00.0...0.00.00.00.00.00.00.04.00.00.06030.00.00.00.00.00.00.00.00.00.0...0.02.00.00.00.00.00.00.04.00.022850.00.00.00.00.00.00.00.00.00.0...0.00.00.00.00.00.00.00.00.04.02500 rows Ã— 2500 columnsVisualizing matched group matrix as heatmapfig=plt.figure(figsize=(10,10))sns.heatmap(m.MG_matrix)Accessing the matched group for an example unit with index equal to "1" and visualizing the weights as bar-chartMG1=m.MG_matrix.loc[1]#matched group for unit "1"MG1[MG1>1].sort_values(ascending=False).plot(kind='bar',figsize=(20,5))#Visualizing all the units matched to unit 1 more than onceATE and CATE Estimatesm.CATE_df#each row is a cate estimate for a corresponding unitavg.CATEstd.CATEoutcometreated047.23206121.808950-15.3130910.0140.60064321.958906-16.9632020.0240.87732022.2045709.5279291.0337.76857819.740320-3.9402180.0439.92025721.744433-8.0119150.0...............249549.22778821.581176-14.5298710.0249642.35235521.38586119.5700551.0249743.73776319.859275-16.3426660.0249841.18929720.346711-9.1652420.0249945.42703723.762884-17.6048290.02500 rows Ã— 4 columnsEstimate Average Treatment Effect (ATE)ATE=m.CATE_df['avg.CATE'].mean()ATE42.29673993471417Visualizing ATE and probability density function of CATE (using KDE plot)fig=plt.figure(figsize=(10,5))sns.kdeplot(m.CATE_df['avg.CATE'],shade=True)plt.axvline(ATE,c='black')plt.text(ATE-4,0.04,'$\hat{ATE}$',rotation=90)Text(38.29673993471417, 0.04, '$\\hat{ATE}$')MALTS Argumentsoutcome: 	Name of the outcome variable column in the datatreatment: 	Name of the treatment variable column in the datadata: 			Data in the pandas Dataframe formatdiscrete: 		List of column names which are discrete (dummified); Default=[]C: 				Regularization constant; Default=1k_tr: 			Size of matched group in training step; Default=15k_est: 			Size of matched group in estimation step; Default=50estimator: 		CATE estimator inside a matched group; Default='linear'; Options: 'linear','mean' or 'RF'smooth_cate: 	Boolean to smoothen CATE estimates by fitting a regression model; Default=Truereweight: 		Reweight treated and control groups as per their respective sample sizes in training step; Default=False,n_splits: 		Number of splits of the data for n_split-fold procedure; Default=5n_repeats: 		Number of repeats of the whole procedure; Default=1output_format: 	Output format of CATE dataframe; Default='brief'; Options: 'brief' or 'full'VisualizationLooking Inside a Matched-GroupPlotting the X1 and X2 marginal of matched-group of unit "0"MG0=m.MG_matrix.loc[0]#fetching the matched groupmatched_units_idx=MG0[MG0!=0].index#getting the indices of the matched unitsmatched_units=df.loc[matched_units_idx]#fetching the data of matched unitssns.lmplot(x='X1',y='X2',hue='treated',data=matched_units,palette="Set1")#plotting the MG on (X1,X2)plt.scatter(x=[df.loc[0,'X1']],y=[df.loc[0,'X2']],c='black',s=100)#plotting the unit-0 on (X1,X2)plt.title('Matched Group for Unit-0')#setting title of the plotText(0.5, 1, 'Matched Group for Unit-0')Plotting CATE versus covariatePlotting CATE v.s. X1data_w_cate=df.join(m.CATE_df,rsuffix='_').drop(columns=['outcome_','treated_'])#joining cate dataframe with datasns.regplot(x='X1',y='avg.CATE',data=data_w_cate,scatter_kws={'alpha':0.5,'s':2},line_kws={'color':'black'},order=2)#fitting a degree 2 polynomial X1 on CATE