MTable is the base class for generating tables and outputting them to different formats. It takes a pandas (Multiindex) DataFrame as its core input and formats it. DTable and ETable are subclasses of MTable that inherit its functionality and add specific output capabilities for their purpose. You can use MTable to add your own custom table needs, either by calling it directly or by subclassing it.
The simplest way to create a table is to pass a pandas DataFrame to MTable():
# Import necessary librariesimport sysimport numpy as npimport pandas as pdimport maketables as mtdf = pd.DataFrame(np.random.randn(4, 4).round(2), columns=["A", "B", "C", "D"])# Create tablemt.MTable(df)
A
B
C
D
0
-1.91
-0.86
-0.41
1.89
1
0.56
-1.34
0.49
-1.55
2
1.08
-0.47
-0.09
1.33
3
-1.29
-1.4
-0.58
1.04
When the respective dataframe has a mutiindex for the columns, columns spanners are generated from the index. The row index can also be a multiindex (of at most two levels). In this case the first index level is used to generate group rows (for instance using the index name as headline and separating the groups by a horizontal line) and the second index level is used to generate the row labels.
# Create a multiindex dataframe with random datarow_index = pd.MultiIndex.from_tuples( [ ("Group 1", "Variable 1"), ("Group 1", "Variable 2"), ("Group 1", "Variable 3"), ("Group 2", "Variable 4"), ("Group 2", "Variable 5"), ("Group 3", "Variable 6"), ])col_index = pd.MultiIndex.from_product([["A", "B"], ["X", "Y"], ["High", "Low"]])df = pd.DataFrame(np.random.randn(6, 8).round(3), index=row_index, columns=col_index)mt.MTable(df=df, caption="This is a caption", notes="These are notes")
This is a caption
A
B
X
Y
X
Y
High
Low
High
Low
High
Low
High
Low
Group 1
Variable 1
-1.519
-2.832
-0.451
0.552
1.2
-0.463
-0.411
1.154
Variable 2
-1.87
-0.389
0.19
0.449
-0.51
0.034
-2.488
-0.658
Variable 3
0.454
-0.982
0.059
0.447
-0.343
0.17
-0.963
-0.207
Group 2
Variable 4
0.61
0.157
-0.587
0.224
0.715
-2.05
1.159
-0.336
Variable 5
0.425
1.197
-1.372
-0.709
-0.289
-0.784
1.735
-0.857
Group 3
Variable 6
-0.556
0.204
-1.202
-0.396
0.317
-0.333
-0.093
-0.529
These are notes
Example: Generating a Correlation Table
Here we for instance build a correlation table with MTable:
# Example: Correlation Table with Simulated Data and Significance Starsfrom scipy.stats import pearsonr# Simulate data for 8 variablesnp.random.seed(42)n =500data = {'Income': np.random.normal(50000, 15000, n),'Age': np.random.normal(40, 12, n),'Education': np.random.normal(14, 3, n),'Experience': np.random.normal(15, 8, n),'Hours': np.random.normal(40, 8, n),'Job satisfaction': np.random.normal(7, 2, n),}sim_df = pd.DataFrame(data)variables = sim_df.columnscorr_matrix = pd.DataFrame(index=variables, columns=variables)p_values = pd.DataFrame(index=variables, columns=variables)for i, var1 inenumerate(variables):for j, var2 inenumerate(variables):if i <= j: # Only calculate for upper triangle and diagonalif i == j: corr_matrix.loc[var1, var2] =1.0 p_values.loc[var1, var2] =0.0else: corr, pval = pearsonr(sim_df[var1], sim_df[var2]) corr_matrix.loc[var1, var2] = corr p_values.loc[var1, var2] = pval# Format correlations with significance starsdef add_stars(corr_val, p_val):if pd.isna(corr_val):return'' corr_str =f'{float(corr_val):.2f}'if corr_val ==1.0:return corr_striffloat(p_val) <0.01:return corr_str +'***'eliffloat(p_val) <0.05:return corr_str +'**'eliffloat(p_val) <0.10:return corr_str +'*'else:return corr_str# Apply formattingcorr_display = pd.DataFrame(index=corr_matrix.index, columns=corr_matrix.columns)for i in corr_matrix.index:for j in corr_matrix.columns: corr_display.loc[i, j] = add_stars(corr_matrix.loc[i, j], p_values.loc[i, j])# Create table with custom column widthsct= mt.MTable( corr_display, caption="Correlation Matrix of Labor Market Variables", notes="Pearson correlation coefficients. * p<0.10, ** p<0.05, *** p<0.01", tab_label="tab:correlation", gt_style={"first_col_width": "150px", "table_width": "80%"},)ct
Export your table to different formats. Currently maketables supports LaTeX, HTML (via great_tables), Word (docx), and Typst. Note that we can also add different output specific formatting settings:
# Save correlation table to LaTeXct.save(type='tex', file_name='../output/correlation_table.tex', replace=True, show=False, tex_style={"first_col_width": "3cm"})# Save to Word documentct.save(type='docx', file_name='../output/correlation_table.docx', docx_style={"first_col_width": "2in", "arraystretch": 1.2})# Save to HTMLct.save(type='html', file_name='../output/correlation_table.html')
Updating Documents
For LaTex, Word, and Typst, you can also update existing documents with the respective update_tex, update_docx, and update_typst methods. For LaTex and Typst, the methods search for a table with the same label in the respective document and replace it with the rendered table object. For Word documents, you specify the table number and the respective table is replaced (see the respective documentation for the output formats). In both cases, if a table with the label (or number) is not found in the document, the rendered table is appended to the end of the document.