Skip to content

Commit dee05ac

Browse files
get latest change
1 parent 83fe6ca commit dee05ac

File tree

5 files changed

+88
-28
lines changed

5 files changed

+88
-28
lines changed

doc/source/whatsnew/v0.24.2.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ Bug Fixes
5656
- Bug in reading a HDF5 table-format ``DataFrame`` created in Python 2, in Python 3 (:issue:`24925`)
5757
- Bug in reading a JSON with ``orient='table'`` generated by :meth:`DataFrame.to_json` with ``index=False`` (:issue:`25170`)
5858
- Bug where float indexes could have misaligned values when printing (:issue:`25061`)
59-
-
59+
- Bug in :meth:`Series.to_string` adding a leading space when ``index=False`` (:issue:`24980`)
6060

6161
**Categorical**
6262

pandas/core/generic.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -2843,9 +2843,9 @@ def to_latex(self, buf=None, columns=None, col_space=None, header=True,
28432843
... 'mask': ['red', 'purple'],
28442844
... 'weapon': ['sai', 'bo staff']})
28452845
>>> df.to_latex(index=False) # doctest: +NORMALIZE_WHITESPACE
2846-
'\\begin{tabular}{lll}\n\\toprule\n name & mask & weapon
2847-
\\\\\n\\midrule\n Raphael & red & sai \\\\\n Donatello &
2848-
purple & bo staff \\\\\n\\bottomrule\n\\end{tabular}\n'
2846+
'\\begin{tabular}{lll}\n\\toprule\n name & mask & weapon
2847+
\\\\\n\\midrule\n Raphael & red & sai \\\\\nDonatello &
2848+
purple & bo staff \\\\\n\\bottomrule\n\\end{tabular}\n'
28492849
"""
28502850
# Get defaults from the pandas config
28512851
if self.ndim == 1:

pandas/io/formats/format.py

+31-5
Original file line numberDiff line numberDiff line change
@@ -252,8 +252,15 @@ def _get_formatted_index(self):
252252

253253
def _get_formatted_values(self):
254254
values_to_format = self.tr_series._formatting_values()
255+
256+
if self.index:
257+
leading_space = None
258+
else:
259+
leading_space = False
255260
return format_array(values_to_format, None,
256-
float_format=self.float_format, na_rep=self.na_rep)
261+
float_format=self.float_format,
262+
na_rep=self.na_rep,
263+
leading_space=leading_space)
257264

258265
def to_string(self):
259266
series = self.tr_series
@@ -703,9 +710,15 @@ def _format_col(self, i):
703710
frame = self.tr_frame
704711
formatter = self._get_formatter(i)
705712
values_to_format = frame.iloc[:, i]._formatting_values()
713+
714+
if self.index:
715+
leading_space = None
716+
else:
717+
leading_space = False
706718
return format_array(values_to_format, formatter,
707719
float_format=self.float_format, na_rep=self.na_rep,
708-
space=self.col_space, decimal=self.decimal)
720+
space=self.col_space, decimal=self.decimal,
721+
leading_space=leading_space)
709722

710723
def to_html(self, classes=None, notebook=False, border=None):
711724
"""
@@ -1087,7 +1100,11 @@ def format_values_with(float_format):
10871100
# The default is otherwise to use str instead of a formatting string
10881101
if self.float_format is None:
10891102
if self.fixed_width:
1090-
float_format = partial('{value: .{digits:d}f}'.format,
1103+
if self.leading_space is not False:
1104+
fmt_str = '{value: .{digits:d}f}'
1105+
else:
1106+
fmt_str = '{value:.{digits:d}f}'
1107+
float_format = partial(fmt_str.format,
10911108
digits=self.digits)
10921109
else:
10931110
float_format = self.float_format
@@ -1119,7 +1136,11 @@ def format_values_with(float_format):
11191136
(abs_vals > 0)).any()
11201137

11211138
if has_small_values or (too_long and has_large_values):
1122-
float_format = partial('{value: .{digits:d}e}'.format,
1139+
if self.leading_space is not False:
1140+
fmt_str = '{value: .{digits:d}e}'
1141+
else:
1142+
fmt_str = '{value:.{digits:d}e}'
1143+
float_format = partial(fmt_str.format,
11231144
digits=self.digits)
11241145
formatted_values = format_values_with(float_format)
11251146

@@ -1136,7 +1157,12 @@ def _format_strings(self):
11361157
class IntArrayFormatter(GenericArrayFormatter):
11371158

11381159
def _format_strings(self):
1139-
formatter = self.formatter or (lambda x: '{x: d}'.format(x=x))
1160+
if self.leading_space is False:
1161+
fmt_str = '{x:d}'
1162+
else:
1163+
fmt_str = '{x: d}'
1164+
formatter = self.formatter or (lambda x: fmt_str.format(x=x))
1165+
# formatter = self.formatter or (lambda x: '{x: d}'.format(x=x))
11401166
fmt_values = [formatter(x) for x in self.values]
11411167
return fmt_values
11421168

pandas/tests/io/formats/test_format.py

+42-8
Original file line numberDiff line numberDiff line change
@@ -1292,15 +1292,15 @@ def test_to_string_no_index(self):
12921292

12931293
df_s = df.to_string(index=False)
12941294
# Leading space is expected for positive numbers.
1295-
expected = (" x y z\n"
1296-
" 11 33 AAA\n"
1297-
" 22 -44 ")
1295+
expected = (" x y z\n"
1296+
"11 33 AAA\n"
1297+
"22 -44 ")
12981298
assert df_s == expected
12991299

13001300
df_s = df[['y', 'x', 'z']].to_string(index=False)
1301-
expected = (" y x z\n"
1302-
" 33 11 AAA\n"
1303-
"-44 22 ")
1301+
expected = (" y x z\n"
1302+
" 33 11 AAA\n"
1303+
"-44 22 ")
13041304
assert df_s == expected
13051305

13061306
def test_to_string_line_width_no_index(self):
@@ -1315,7 +1315,7 @@ def test_to_string_line_width_no_index(self):
13151315
df = DataFrame({'x': [11, 22, 33], 'y': [4, 5, 6]})
13161316

13171317
df_s = df.to_string(line_width=1, index=False)
1318-
expected = " x \\\n 11 \n 22 \n 33 \n\n y \n 4 \n 5 \n 6 "
1318+
expected = " x \\\n11 \n22 \n33 \n\n y \n 4 \n 5 \n 6 "
13191319

13201320
assert df_s == expected
13211321

@@ -1888,7 +1888,7 @@ def test_to_string_without_index(self):
18881888
# GH 11729 Test index=False option
18891889
s = Series([1, 2, 3, 4])
18901890
result = s.to_string(index=False)
1891-
expected = (u(' 1\n') + ' 2\n' + ' 3\n' + ' 4')
1891+
expected = (u('1\n') + '2\n' + '3\n' + '4')
18921892
assert result == expected
18931893

18941894
def test_unicode_name_in_footer(self):
@@ -2380,6 +2380,15 @@ def test_to_string_header(self):
23802380
exp = '0 0\n ..\n9 9'
23812381
assert res == exp
23822382

2383+
@pytest.mark.parametrize("inputs, expected", [
2384+
([' a', ' b'], ' a\n b'),
2385+
(['.1', '1'], '.1\n 1'),
2386+
(['10', '-10'], ' 10\n-10')
2387+
])
2388+
def test_to_string_index_false_corner_case(self, inputs, expected):
2389+
s = pd.Series(inputs).to_string(index=False)
2390+
assert s == expected
2391+
23832392

23842393
def _three_digit_exp():
23852394
return '{x:.4g}'.format(x=1.7e8) == '1.7e+008'
@@ -2780,6 +2789,31 @@ def test_format_percentiles():
27802789
fmt.format_percentiles([0.1, 0.5, 'a'])
27812790

27822791

2792+
@pytest.mark.parametrize("input_array, expected", [
2793+
("a", "a"),
2794+
(["a", "b"], "a\nb"),
2795+
([1, "a"], "1\na"),
2796+
(1, "1"),
2797+
([0, -1], " 0\n-1"),
2798+
(1.0, '1.0')
2799+
])
2800+
def test_format_remove_leading_space_series(input_array, expected):
2801+
# GH: 24980
2802+
s = pd.Series(input_array).to_string(index=False)
2803+
assert s == expected
2804+
2805+
2806+
@pytest.mark.parametrize("input_array, expected", [
2807+
({"A": ["a"]}, "A\na"),
2808+
({"A": ["a", "b"], "B": ["c", "dd"]}, "A B\na c\nb dd"),
2809+
({"A": ["a", 1], "B": ["aa", 1]}, "A B\na aa\n1 1")
2810+
])
2811+
def test_format_remove_leading_space_dataframe(input_array, expected):
2812+
# GH: 24980
2813+
df = pd.DataFrame(input_array).to_string(index=False)
2814+
assert df == expected
2815+
2816+
27832817
def test_repr_html_ipython_config(ip):
27842818
code = textwrap.dedent("""\
27852819
import pandas as pd

pandas/tests/io/formats/test_to_latex.py

+11-11
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,10 @@ def test_to_latex(self, frame):
6464
withoutindex_result = df.to_latex(index=False)
6565
withoutindex_expected = r"""\begin{tabular}{rl}
6666
\toprule
67-
a & b \\
67+
a & b \\
6868
\midrule
69-
1 & b1 \\
70-
2 & b2 \\
69+
1 & b1 \\
70+
2 & b2 \\
7171
\bottomrule
7272
\end{tabular}
7373
"""
@@ -423,7 +423,7 @@ def test_to_latex_longtable(self, frame):
423423
withoutindex_result = df.to_latex(index=False, longtable=True)
424424
withoutindex_expected = r"""\begin{longtable}{rl}
425425
\toprule
426-
a & b \\
426+
a & b \\
427427
\midrule
428428
\endhead
429429
\midrule
@@ -433,8 +433,8 @@ def test_to_latex_longtable(self, frame):
433433
434434
\bottomrule
435435
\endlastfoot
436-
1 & b1 \\
437-
2 & b2 \\
436+
1 & b1 \\
437+
2 & b2 \\
438438
\end{longtable}
439439
"""
440440

@@ -490,8 +490,8 @@ def test_to_latex_no_header(self):
490490
withoutindex_result = df.to_latex(index=False, header=False)
491491
withoutindex_expected = r"""\begin{tabular}{rl}
492492
\toprule
493-
1 & b1 \\
494-
2 & b2 \\
493+
1 & b1 \\
494+
2 & b2 \\
495495
\bottomrule
496496
\end{tabular}
497497
"""
@@ -517,10 +517,10 @@ def test_to_latex_specified_header(self):
517517
withoutindex_result = df.to_latex(header=['AA', 'BB'], index=False)
518518
withoutindex_expected = r"""\begin{tabular}{rl}
519519
\toprule
520-
AA & BB \\
520+
AA & BB \\
521521
\midrule
522-
1 & b1 \\
523-
2 & b2 \\
522+
1 & b1 \\
523+
2 & b2 \\
524524
\bottomrule
525525
\end{tabular}
526526
"""

0 commit comments

Comments
 (0)