Skip to content

Commit 3e2dac9

Browse files
committed
BUG: fix to_latex bold_rows option
1 parent 3ff845b commit 3e2dac9

File tree

2 files changed

+109
-75
lines changed

2 files changed

+109
-75
lines changed

pandas/io/formats/format.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -943,6 +943,10 @@ def get_col_type(dtype):
943943
if x else '{}') for x in row]
944944
else:
945945
crow = [x if x else '{}' for x in row]
946+
if self.fmt.kwds.get('bold_rows', True) and self.fmt.index:
947+
# bold row labels
948+
crow = ['\\textbf{%s}' % x if j < ilevels and x.strip() not in ['', '{}'] else x
949+
for j, x in enumerate(crow)]
946950
if i < clevels and self.fmt.header and self.multicolumn:
947951
# sum up columns to multicolumns
948952
crow = self._format_multicolumn(crow, ilevels)

pandas/tests/io/formats/test_to_latex.py

Lines changed: 105 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@ def test_to_latex(self, frame):
5252
\toprule
5353
{} & a & b \\
5454
\midrule
55-
0 & 1 & b1 \\
56-
1 & 2 & b2 \\
55+
\textbf{0} & 1 & b1 \\
56+
\textbf{1} & 2 & b2 \\
5757
\bottomrule
5858
\end{tabular}
5959
"""
@@ -83,8 +83,8 @@ def test_to_latex_format(self, frame):
8383
\toprule
8484
{} & a & b \\
8585
\midrule
86-
0 & 1 & b1 \\
87-
1 & 2 & b2 \\
86+
\textbf{0} & 1 & b1 \\
87+
\textbf{1} & 2 & b2 \\
8888
\bottomrule
8989
\end{tabular}
9090
"""
@@ -110,9 +110,9 @@ def test_to_latex_with_formatters(self):
110110
\toprule
111111
{} & datetime64 & float & int & object \\
112112
\midrule
113-
index: 0 & 2016-01 & [ 1.0] & 0x1 & -(1, 2)- \\
114-
index: 1 & 2016-02 & [ 2.0] & 0x2 & -True- \\
115-
index: 2 & 2016-03 & [ 3.0] & 0x3 & -False- \\
113+
\textbf{index: 0} & 2016-01 & [ 1.0] & 0x1 & -(1, 2)- \\
114+
\textbf{index: 1} & 2016-02 & [ 2.0] & 0x2 & -True- \\
115+
\textbf{index: 2} & 2016-03 & [ 3.0] & 0x3 & -False- \\
116116
\bottomrule
117117
\end{tabular}
118118
"""
@@ -126,7 +126,7 @@ def test_to_latex_multiindex(self):
126126
{} & x \\
127127
{} & y \\
128128
\midrule
129-
0 & a \\
129+
\textbf{0} & a \\
130130
\bottomrule
131131
\end{tabular}
132132
"""
@@ -138,7 +138,7 @@ def test_to_latex_multiindex(self):
138138
\toprule
139139
& & 0 \\
140140
\midrule
141-
x & y & a \\
141+
\textbf{x} & \textbf{y} & a \\
142142
\bottomrule
143143
\end{tabular}
144144
"""
@@ -157,11 +157,11 @@ def test_to_latex_multiindex(self):
157157
\toprule
158158
& & 0 & 1 & 2 & 3 \\
159159
\midrule
160-
c1 & 0 & 0 & 1 & 2 & 3 \\
161-
& 1 & 4 & 5 & 6 & 7 \\
162-
c2 & 0 & 0 & 1 & 2 & 3 \\
163-
& 1 & 4 & 5 & 6 & 7 \\
164-
c3 & 0 & 0 & 1 & 2 & 3 \\
160+
\textbf{c1} & \textbf{0} & 0 & 1 & 2 & 3 \\
161+
& \textbf{1} & 4 & 5 & 6 & 7 \\
162+
\textbf{c2} & \textbf{0} & 0 & 1 & 2 & 3 \\
163+
& \textbf{1} & 4 & 5 & 6 & 7 \\
164+
\textbf{c3} & \textbf{0} & 0 & 1 & 2 & 3 \\
165165
\bottomrule
166166
\end{tabular}
167167
"""
@@ -174,13 +174,13 @@ def test_to_latex_multiindex(self):
174174
result = df.to_latex()
175175
expected = r"""\begin{tabular}{lrrrrr}
176176
\toprule
177-
a & \multicolumn{2}{l}{c1} & \multicolumn{2}{l}{c2} & c3 \\
178-
b & 0 & 1 & 0 & 1 & 0 \\
177+
\textbf{a} & \multicolumn{2}{l}{c1} & \multicolumn{2}{l}{c2} & c3 \\
178+
\textbf{b} & 0 & 1 & 0 & 1 & 0 \\
179179
\midrule
180-
0 & 0 & 4 & 0 & 4 & 0 \\
181-
1 & 1 & 5 & 1 & 5 & 1 \\
182-
2 & 2 & 6 & 2 & 6 & 2 \\
183-
3 & 3 & 7 & 3 & 7 & 3 \\
180+
\textbf{0} & 0 & 4 & 0 & 4 & 0 \\
181+
\textbf{1} & 1 & 5 & 1 & 5 & 1 \\
182+
\textbf{2} & 2 & 6 & 2 & 6 & 2 \\
183+
\textbf{3} & 3 & 7 & 3 & 7 & 3 \\
184184
\bottomrule
185185
\end{tabular}
186186
"""
@@ -194,12 +194,12 @@ def test_to_latex_multiindex(self):
194194
expected = r"""\begin{tabular}{llr}
195195
\toprule
196196
& & c \\
197-
a & b & \\
197+
\textbf{a} & \textbf{b} & \\
198198
\midrule
199-
0 & a & 1 \\
200-
& b & 2 \\
201-
1 & a & 3 \\
202-
& b & 4 \\
199+
\textbf{0} & \textbf{a} & 1 \\
200+
& \textbf{b} & 2 \\
201+
\textbf{1} & \textbf{a} & 3 \\
202+
& \textbf{b} & 4 \\
203203
\bottomrule
204204
\end{tabular}
205205
"""
@@ -211,10 +211,10 @@ def test_to_latex_multiindex(self):
211211
\toprule
212212
{} & \multicolumn{8}{l}{c} \\
213213
{} & count & mean & std & min & 25\% & 50\% & 75\% & max \\
214-
a & & & & & & & & \\
214+
\textbf{a} & & & & & & & & \\
215215
\midrule
216-
0 & 2.0 & 1.5 & 0.707107 & 1.0 & 1.25 & 1.5 & 1.75 & 2.0 \\
217-
1 & 2.0 & 3.5 & 0.707107 & 3.0 & 3.25 & 3.5 & 3.75 & 4.0 \\
216+
\textbf{0} & 2.0 & 1.5 & 0.707107 & 1.0 & 1.25 & 1.5 & 1.75 & 2.0 \\
217+
\textbf{1} & 2.0 & 3.5 & 0.707107 & 3.0 & 3.25 & 3.5 & 3.75 & 4.0 \\
218218
\bottomrule
219219
\end{tabular}
220220
"""
@@ -235,11 +235,11 @@ def test_to_latex_multicolumnrow(self):
235235
{} & \multicolumn{2}{l}{c1} & \multicolumn{2}{l}{c2} & c3 \\
236236
{} & 0 & 1 & 0 & 1 & 0 \\
237237
\midrule
238-
0 & 0 & 5 & 0 & 5 & 0 \\
239-
1 & 1 & 6 & 1 & 6 & 1 \\
240-
2 & 2 & 7 & 2 & 7 & 2 \\
241-
3 & 3 & 8 & 3 & 8 & 3 \\
242-
4 & 4 & 9 & 4 & 9 & 4 \\
238+
\textbf{0} & 0 & 5 & 0 & 5 & 0 \\
239+
\textbf{1} & 1 & 6 & 1 & 6 & 1 \\
240+
\textbf{2} & 2 & 7 & 2 & 7 & 2 \\
241+
\textbf{3} & 3 & 8 & 3 & 8 & 3 \\
242+
\textbf{4} & 4 & 9 & 4 & 9 & 4 \\
243243
\bottomrule
244244
\end{tabular}
245245
"""
@@ -251,11 +251,11 @@ def test_to_latex_multicolumnrow(self):
251251
{} & c1 & & c2 & & c3 \\
252252
{} & 0 & 1 & 0 & 1 & 0 \\
253253
\midrule
254-
0 & 0 & 5 & 0 & 5 & 0 \\
255-
1 & 1 & 6 & 1 & 6 & 1 \\
256-
2 & 2 & 7 & 2 & 7 & 2 \\
257-
3 & 3 & 8 & 3 & 8 & 3 \\
258-
4 & 4 & 9 & 4 & 9 & 4 \\
254+
\textbf{0} & 0 & 5 & 0 & 5 & 0 \\
255+
\textbf{1} & 1 & 6 & 1 & 6 & 1 \\
256+
\textbf{2} & 2 & 7 & 2 & 7 & 2 \\
257+
\textbf{3} & 3 & 8 & 3 & 8 & 3 \\
258+
\textbf{4} & 4 & 9 & 4 & 9 & 4 \\
259259
\bottomrule
260260
\end{tabular}
261261
"""
@@ -266,13 +266,13 @@ def test_to_latex_multicolumnrow(self):
266266
\toprule
267267
& & 0 & 1 & 2 & 3 & 4 \\
268268
\midrule
269-
\multirow{2}{*}{c1} & 0 & 0 & 1 & 2 & 3 & 4 \\
270-
& 1 & 5 & 6 & 7 & 8 & 9 \\
269+
\multirow{2}{*}{\textbf{c1}} & \textbf{0} & 0 & 1 & 2 & 3 & 4 \\
270+
& \textbf{1} & 5 & 6 & 7 & 8 & 9 \\
271271
\cline{1-7}
272-
\multirow{2}{*}{c2} & 0 & 0 & 1 & 2 & 3 & 4 \\
273-
& 1 & 5 & 6 & 7 & 8 & 9 \\
272+
\multirow{2}{*}{\textbf{c2}} & \textbf{0} & 0 & 1 & 2 & 3 & 4 \\
273+
& \textbf{1} & 5 & 6 & 7 & 8 & 9 \\
274274
\cline{1-7}
275-
c3 & 0 & 0 & 1 & 2 & 3 & 4 \\
275+
\textbf{c3} & \textbf{0} & 0 & 1 & 2 & 3 & 4 \\
276276
\bottomrule
277277
\end{tabular}
278278
"""
@@ -286,13 +286,13 @@ def test_to_latex_multicolumnrow(self):
286286
& & \multicolumn{2}{c}{c1} & \multicolumn{2}{c}{c2} & c3 \\
287287
& & 0 & 1 & 0 & 1 & 0 \\
288288
\midrule
289-
\multirow{2}{*}{c1} & 0 & 0 & 1 & 2 & 3 & 4 \\
290-
& 1 & 5 & 6 & 7 & 8 & 9 \\
289+
\multirow{2}{*}{\textbf{c1}} & \textbf{0} & 0 & 1 & 2 & 3 & 4 \\
290+
& \textbf{1} & 5 & 6 & 7 & 8 & 9 \\
291291
\cline{1-7}
292-
\multirow{2}{*}{c2} & 0 & 0 & 1 & 2 & 3 & 4 \\
293-
& 1 & 5 & 6 & 7 & 8 & 9 \\
292+
\multirow{2}{*}{\textbf{c2}} & \textbf{0} & 0 & 1 & 2 & 3 & 4 \\
293+
& \textbf{1} & 5 & 6 & 7 & 8 & 9 \\
294294
\cline{1-7}
295-
c3 & 0 & 0 & 1 & 2 & 3 & 4 \\
295+
\textbf{c3} & \textbf{0} & 0 & 1 & 2 & 3 & 4 \\
296296
\bottomrule
297297
\end{tabular}
298298
"""
@@ -315,8 +315,8 @@ def test_to_latex_escape(self):
315315
\toprule
316316
{} & co$e^x$ & co^l1 \\
317317
\midrule
318-
a & a & a \\
319-
b & b & b \\
318+
\textbf{a} & a & a \\
319+
\textbf{b} & b & b \\
320320
\bottomrule
321321
\end{tabular}
322322
'''
@@ -325,8 +325,8 @@ def test_to_latex_escape(self):
325325
\toprule
326326
{} & co\$e\textasciicircumx\$ & co\textasciicircuml1 \\
327327
\midrule
328-
a & a & a \\
329-
b & b & b \\
328+
\textbf{a} & a & a \\
329+
\textbf{b} & b & b \\
330330
\bottomrule
331331
\end{tabular}
332332
'''
@@ -351,8 +351,8 @@ def test_to_latex_longtable(self, frame):
351351
352352
\bottomrule
353353
\endlastfoot
354-
0 & 1 & b1 \\
355-
1 & 2 & b2 \\
354+
\textbf{0} & 1 & b1 \\
355+
\textbf{1} & 2 & b2 \\
356356
\end{longtable}
357357
"""
358358

@@ -387,16 +387,16 @@ def test_to_latex_escape_special_chars(self):
387387
\toprule
388388
{} & 0 \\
389389
\midrule
390-
0 & \& \\
391-
1 & \% \\
392-
2 & \$ \\
393-
3 & \# \\
394-
4 & \_ \\
395-
5 & \{ \\
396-
6 & \} \\
397-
7 & \textasciitilde \\
398-
8 & \textasciicircum \\
399-
9 & \textbackslash \\
390+
\textbf{0} & \& \\
391+
\textbf{1} & \% \\
392+
\textbf{2} & \$ \\
393+
\textbf{3} & \# \\
394+
\textbf{4} & \_ \\
395+
\textbf{5} & \{ \\
396+
\textbf{6} & \} \\
397+
\textbf{7} & \textasciitilde \\
398+
\textbf{8} & \textasciicircum \\
399+
\textbf{9} & \textbackslash \\
400400
\bottomrule
401401
\end{tabular}
402402
"""
@@ -409,8 +409,8 @@ def test_to_latex_no_header(self):
409409
withindex_result = df.to_latex(header=False)
410410
withindex_expected = r"""\begin{tabular}{lrl}
411411
\toprule
412-
0 & 1 & b1 \\
413-
1 & 2 & b2 \\
412+
\textbf{0} & 1 & b1 \\
413+
\textbf{1} & 2 & b2 \\
414414
\bottomrule
415415
\end{tabular}
416416
"""
@@ -436,8 +436,8 @@ def test_to_latex_specified_header(self):
436436
\toprule
437437
{} & AA & BB \\
438438
\midrule
439-
0 & 1 & b1 \\
440-
1 & 2 & b2 \\
439+
\textbf{0} & 1 & b1 \\
440+
\textbf{1} & 2 & b2 \\
441441
\bottomrule
442442
\end{tabular}
443443
"""
@@ -462,8 +462,8 @@ def test_to_latex_specified_header(self):
462462
\toprule
463463
{} & $A$ & $B$ \\
464464
\midrule
465-
0 & 1 & b1 \\
466-
1 & 2 & b2 \\
465+
\textbf{0} & 1 & b1 \\
466+
\textbf{1} & 2 & b2 \\
467467
\bottomrule
468468
\end{tabular}
469469
"""
@@ -484,8 +484,8 @@ def test_to_latex_decimal(self, frame):
484484
\toprule
485485
{} & a & b \\
486486
\midrule
487-
0 & 1,0 & b1 \\
488-
1 & 2,1 & b2 \\
487+
\textbf{0} & 1,0 & b1 \\
488+
\textbf{1} & 2,1 & b2 \\
489489
\bottomrule
490490
\end{tabular}
491491
"""
@@ -499,10 +499,40 @@ def test_to_latex_series(self):
499499
\toprule
500500
{} & 0 \\
501501
\midrule
502-
0 & a \\
503-
1 & b \\
504-
2 & c \\
502+
\textbf{0} & a \\
503+
\textbf{1} & b \\
504+
\textbf{2} & c \\
505505
\bottomrule
506506
\end{tabular}
507507
"""
508508
assert withindex_result == withindex_expected
509+
510+
def test_to_latex_bold_rows(self):
511+
# GH 16707
512+
df = DataFrame({'a': [1, 2], 'b': ['b1', 'b2']})
513+
observed = df.to_latex(bold_rows=True)
514+
expected = r"""\begin{tabular}{lrl}
515+
\toprule
516+
\textbf{} & a & b \\
517+
\midrule
518+
\textbf{0} & 1 & b1 \\
519+
\textbf{1} & 2 & b2 \\
520+
\bottomrule
521+
\end{tabular}
522+
"""
523+
assert observed == expected
524+
525+
def test_to_latex_no_bold_rows(self):
526+
# GH 16707
527+
df = DataFrame({'a': [1, 2], 'b': ['b1', 'b2']})
528+
observed = df.to_latex(bold_rows=False)
529+
expected = r"""\begin{tabular}{lrl}
530+
\toprule
531+
{} & a & b \\
532+
\midrule
533+
0 & 1 & b1 \\
534+
1 & 2 & b2 \\
535+
\bottomrule
536+
\end{tabular}
537+
"""
538+
assert observed == expected

0 commit comments

Comments
 (0)