@@ -36,6 +36,8 @@ def __init__(
36
36
multicolumn : bool = False ,
37
37
multicolumn_format : Optional [str ] = None ,
38
38
multirow : bool = False ,
39
+ caption : Optional [str ] = None ,
40
+ label : Optional [str ] = None ,
39
41
):
40
42
self .fmt = formatter
41
43
self .frame = self .fmt .frame
@@ -45,11 +47,14 @@ def __init__(
45
47
self .multicolumn = multicolumn
46
48
self .multicolumn_format = multicolumn_format
47
49
self .multirow = multirow
50
+ self .caption = caption
51
+ self .label = label
48
52
self .escape = self .fmt .escape
49
53
50
54
def write_result (self , buf : IO [str ]) -> None :
51
55
"""
52
- Render a DataFrame to a LaTeX tabular/longtable environment output.
56
+ Render a DataFrame to a LaTeX tabular, longtable, or table/tabular
57
+ environment output.
53
58
"""
54
59
55
60
# string representation of the columns
@@ -114,12 +119,12 @@ def pad_empties(x):
114
119
"not {typ}" .format (typ = type (column_format ))
115
120
)
116
121
117
- if not self .longtable :
118
- buf .write ("\\ begin{{tabular}}{{{fmt}}}\n " .format (fmt = column_format ))
119
- buf .write ("\\ toprule\n " )
122
+ if self .longtable :
123
+ self ._write_longtable_begin (buf , column_format )
120
124
else :
121
- buf .write ("\\ begin{{longtable}}{{{fmt}}}\n " .format (fmt = column_format ))
122
- buf .write ("\\ toprule\n " )
125
+ self ._write_tabular_begin (buf , column_format )
126
+
127
+ buf .write ("\\ toprule\n " )
123
128
124
129
ilevels = self .frame .index .nlevels
125
130
clevels = self .frame .columns .nlevels
@@ -183,11 +188,10 @@ def pad_empties(x):
183
188
if self .multirow and i < len (strrows ) - 1 :
184
189
self ._print_cline (buf , i , len (strcols ))
185
190
186
- if not self .longtable :
187
- buf .write ("\\ bottomrule\n " )
188
- buf .write ("\\ end{tabular}\n " )
191
+ if self .longtable :
192
+ self ._write_longtable_end (buf )
189
193
else :
190
- buf . write ( " \\ end{longtable} \n " )
194
+ self . _write_tabular_end ( buf )
191
195
192
196
def _format_multicolumn (self , row : List [str ], ilevels : int ) -> List [str ]:
193
197
r"""
@@ -268,3 +272,107 @@ def _print_cline(self, buf: IO[str], i: int, icol: int) -> None:
268
272
buf .write ("\\ cline{{{cl:d}-{icol:d}}}\n " .format (cl = cl [1 ], icol = icol ))
269
273
# remove entries that have been written to buffer
270
274
self .clinebuf = [x for x in self .clinebuf if x [0 ] != i ]
275
+
276
+ def _write_tabular_begin (self , buf , column_format ):
277
+ """
278
+ Write the beginning of a tabular environment or
279
+ nested table/tabular environments including caption and label.
280
+
281
+ Parameters
282
+ ----------
283
+ buf : string or file handle
284
+ File path or object. If not specified, the result is returned as
285
+ a string.
286
+ column_format : str, default None
287
+ The columns format as specified in `LaTeX table format
288
+ <https://en.wikibooks.org/wiki/LaTeX/Tables>`__ e.g 'rcl'
289
+ for 3 columns
290
+
291
+ """
292
+ if self .caption is not None or self .label is not None :
293
+ # then write output in a nested table/tabular environment
294
+ if self .caption is None :
295
+ caption_ = ""
296
+ else :
297
+ caption_ = "\n \\ caption{{{}}}" .format (self .caption )
298
+
299
+ if self .label is None :
300
+ label_ = ""
301
+ else :
302
+ label_ = "\n \\ label{{{}}}" .format (self .label )
303
+
304
+ buf .write ("\\ begin{{table}}\n \\ centering{}{}\n " .format (caption_ , label_ ))
305
+ else :
306
+ # then write output only in a tabular environment
307
+ pass
308
+
309
+ buf .write ("\\ begin{{tabular}}{{{fmt}}}\n " .format (fmt = column_format ))
310
+
311
+ def _write_tabular_end (self , buf ):
312
+ """
313
+ Write the end of a tabular environment or nested table/tabular
314
+ environment.
315
+
316
+ Parameters
317
+ ----------
318
+ buf : string or file handle
319
+ File path or object. If not specified, the result is returned as
320
+ a string.
321
+
322
+ """
323
+ buf .write ("\\ bottomrule\n " )
324
+ buf .write ("\\ end{tabular}\n " )
325
+ if self .caption is not None or self .label is not None :
326
+ buf .write ("\\ end{table}\n " )
327
+ else :
328
+ pass
329
+
330
+ def _write_longtable_begin (self , buf , column_format ):
331
+ """
332
+ Write the beginning of a longtable environment including caption and
333
+ label if provided by user.
334
+
335
+ Parameters
336
+ ----------
337
+ buf : string or file handle
338
+ File path or object. If not specified, the result is returned as
339
+ a string.
340
+ column_format : str, default None
341
+ The columns format as specified in `LaTeX table format
342
+ <https://en.wikibooks.org/wiki/LaTeX/Tables>`__ e.g 'rcl'
343
+ for 3 columns
344
+
345
+ """
346
+ buf .write ("\\ begin{{longtable}}{{{fmt}}}\n " .format (fmt = column_format ))
347
+
348
+ if self .caption is not None or self .label is not None :
349
+ if self .caption is None :
350
+ pass
351
+ else :
352
+ buf .write ("\\ caption{{{}}}" .format (self .caption ))
353
+
354
+ if self .label is None :
355
+ pass
356
+ else :
357
+ buf .write ("\\ label{{{}}}" .format (self .label ))
358
+
359
+ # a double-backslash is required at the end of the line
360
+ # as discussed here:
361
+ # https://tex.stackexchange.com/questions/219138
362
+ buf .write ("\\ \\ \n " )
363
+ else :
364
+ pass
365
+
366
+ @staticmethod
367
+ def _write_longtable_end (buf ):
368
+ """
369
+ Write the end of a longtable environment.
370
+
371
+ Parameters
372
+ ----------
373
+ buf : string or file handle
374
+ File path or object. If not specified, the result is returned as
375
+ a string.
376
+
377
+ """
378
+ buf .write ("\\ end{longtable}\n " )
0 commit comments