Skip to content

Commit f34d4e7

Browse files
add fixes
1 parent 6e0f9a9 commit f34d4e7

File tree

5 files changed

+94
-32
lines changed

5 files changed

+94
-32
lines changed

doc/source/whatsnew/v0.25.0.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,7 @@ I/O
276276

277277
- Bug in :func:`DataFrame.to_html()` where values were truncated using display options instead of outputting the full content (:issue:`17004`)
278278
- Fixed bug in missing text when using :meth:`to_clipboard` if copying utf-16 characters in Python 3 on Windows (:issue:`25040`)
279+
- Bug in :meth:`Series.to_string` adding a leading space when ``index=False`` (:issue:`24980`)
279280
- Bug in :func:`read_json` for ``orient='table'`` when it tries to infer dtypes by default, which is not applicable as dtypes are already defined in the JSON schema (:issue:`21345`)
280281
- Bug in :func:`read_json` for ``orient='table'`` and float index, as it infers index dtype by default, which is not applicable because index dtype is already defined in the JSON schema (:issue:`25433`)
281282
- Bug in :func:`read_json` for ``orient='table'`` and string of float column names, as it makes a column name type conversion to Timestamp, which is not applicable because column names are already defined in the JSON schema (:issue:`25435`)
@@ -286,6 +287,7 @@ I/O
286287
- Improved performance in :meth:`pandas.read_stata` and :class:`pandas.io.stata.StataReader` when converting columns that have missing values (:issue:`25772`)
287288

288289

290+
289291
Plotting
290292
^^^^^^^^
291293

pandas/core/generic.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2879,9 +2879,9 @@ def to_latex(self, buf=None, columns=None, col_space=None, header=True,
28792879
... 'mask': ['red', 'purple'],
28802880
... 'weapon': ['sai', 'bo staff']})
28812881
>>> df.to_latex(index=False) # doctest: +NORMALIZE_WHITESPACE
2882-
'\\begin{tabular}{lll}\n\\toprule\n name & mask & weapon
2883-
\\\\\n\\midrule\n Raphael & red & sai \\\\\n Donatello &
2884-
purple & bo staff \\\\\n\\bottomrule\n\\end{tabular}\n'
2882+
'\\begin{tabular}{lll}\n\\toprule\n name & mask & weapon
2883+
\\\\\n\\midrule\n Raphael & red & sai \\\\\nDonatello &
2884+
purple & bo staff \\\\\n\\bottomrule\n\\end{tabular}\n'
28852885
"""
28862886
# Get defaults from the pandas config
28872887
if self.ndim == 1:

pandas/io/formats/format.py

Lines changed: 36 additions & 10 deletions
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 = 'compat'
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
@@ -706,9 +713,15 @@ def _format_col(self, i):
706713
frame = self.tr_frame
707714
formatter = self._get_formatter(i)
708715
values_to_format = frame.iloc[:, i]._formatting_values()
716+
717+
if self.index:
718+
leading_space = 'compat'
719+
else:
720+
leading_space = False
709721
return format_array(values_to_format, formatter,
710722
float_format=self.float_format, na_rep=self.na_rep,
711-
space=self.col_space, decimal=self.decimal)
723+
space=self.col_space, decimal=self.decimal,
724+
leading_space=leading_space)
712725

713726
def to_html(self, classes=None, notebook=False, border=None):
714727
"""
@@ -845,7 +858,7 @@ def _get_column_name_list(self):
845858

846859
def format_array(values, formatter, float_format=None, na_rep='NaN',
847860
digits=None, space=None, justify='right', decimal='.',
848-
leading_space=None):
861+
leading_space='compat'):
849862
"""
850863
Format an array for printing.
851864
@@ -859,7 +872,7 @@ def format_array(values, formatter, float_format=None, na_rep='NaN',
859872
space
860873
justify
861874
decimal
862-
leading_space : bool, optional
875+
leading_space : bool, default is 'compat'
863876
Whether the array should be formatted with a leading space.
864877
When an array as a column of a Series or DataFrame, we do want
865878
the leading space to pad between columns.
@@ -909,7 +922,7 @@ class GenericArrayFormatter(object):
909922

910923
def __init__(self, values, digits=7, formatter=None, na_rep='NaN',
911924
space=12, float_format=None, justify='right', decimal='.',
912-
quoting=None, fixed_width=True, leading_space=None):
925+
quoting=None, fixed_width=True, leading_space='compat'):
913926
self.values = values
914927
self.digits = digits
915928
self.na_rep = na_rep
@@ -961,12 +974,12 @@ def _format(x):
961974

962975
is_float_type = lib.map_infer(vals, is_float) & notna(vals)
963976
leading_space = self.leading_space
964-
if leading_space is None:
977+
if leading_space == 'compat':
965978
leading_space = is_float_type.any()
966979

967980
fmt_values = []
968981
for i, v in enumerate(vals):
969-
if not is_float_type[i] and leading_space:
982+
if not is_float_type[i] and leading_space is True:
970983
fmt_values.append(u' {v}'.format(v=_format(v)))
971984
elif is_float_type[i]:
972985
fmt_values.append(float_format(v))
@@ -1085,7 +1098,11 @@ def format_values_with(float_format):
10851098
# The default is otherwise to use str instead of a formatting string
10861099
if self.float_format is None:
10871100
if self.fixed_width:
1088-
float_format = partial('{value: .{digits:d}f}'.format,
1101+
if self.leading_space is not False:
1102+
fmt_str = '{value: .{digits:d}f}'
1103+
else:
1104+
fmt_str = '{value:.{digits:d}f}'
1105+
float_format = partial(fmt_str.format,
10891106
digits=self.digits)
10901107
else:
10911108
float_format = self.float_format
@@ -1117,7 +1134,11 @@ def format_values_with(float_format):
11171134
(abs_vals > 0)).any()
11181135

11191136
if has_small_values or (too_long and has_large_values):
1120-
float_format = partial('{value: .{digits:d}e}'.format,
1137+
if self.leading_space is not False:
1138+
fmt_str = '{value: .{digits:d}e}'
1139+
else:
1140+
fmt_str = '{value:.{digits:d}e}'
1141+
float_format = partial(fmt_str.format,
11211142
digits=self.digits)
11221143
formatted_values = format_values_with(float_format)
11231144

@@ -1134,7 +1155,12 @@ def _format_strings(self):
11341155
class IntArrayFormatter(GenericArrayFormatter):
11351156

11361157
def _format_strings(self):
1137-
formatter = self.formatter or (lambda x: '{x: d}'.format(x=x))
1158+
if self.leading_space is False:
1159+
fmt_str = '{x:d}'
1160+
else:
1161+
fmt_str = '{x: d}'
1162+
formatter = self.formatter or (lambda x: fmt_str.format(x=x))
1163+
# formatter = self.formatter or (lambda x: '{x: d}'.format(x=x))
11381164
fmt_values = [formatter(x) for x in self.values]
11391165
return fmt_values
11401166

pandas/tests/io/formats/test_format.py

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1258,15 +1258,15 @@ def test_to_string_no_index(self):
12581258

12591259
df_s = df.to_string(index=False)
12601260
# Leading space is expected for positive numbers.
1261-
expected = (" x y z\n"
1262-
" 11 33 AAA\n"
1263-
" 22 -44 ")
1261+
expected = (" x y z\n"
1262+
"11 33 AAA\n"
1263+
"22 -44 ")
12641264
assert df_s == expected
12651265

12661266
df_s = df[['y', 'x', 'z']].to_string(index=False)
1267-
expected = (" y x z\n"
1268-
" 33 11 AAA\n"
1269-
"-44 22 ")
1267+
expected = (" y x z\n"
1268+
" 33 11 AAA\n"
1269+
"-44 22 ")
12701270
assert df_s == expected
12711271

12721272
def test_to_string_line_width_no_index(self):
@@ -1281,7 +1281,7 @@ def test_to_string_line_width_no_index(self):
12811281
df = DataFrame({'x': [11, 22, 33], 'y': [4, 5, 6]})
12821282

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

12861286
assert df_s == expected
12871287

@@ -1854,7 +1854,7 @@ def test_to_string_without_index(self):
18541854
# GH 11729 Test index=False option
18551855
s = Series([1, 2, 3, 4])
18561856
result = s.to_string(index=False)
1857-
expected = (u(' 1\n') + ' 2\n' + ' 3\n' + ' 4')
1857+
expected = (u('1\n') + '2\n' + '3\n' + '4')
18581858
assert result == expected
18591859

18601860
def test_unicode_name_in_footer(self):
@@ -2342,6 +2342,15 @@ def test_to_string_header(self):
23422342
exp = '0 0\n ..\n9 9'
23432343
assert res == exp
23442344

2345+
@pytest.mark.parametrize("inputs, expected", [
2346+
([' a', ' b'], ' a\n b'),
2347+
(['.1', '1'], '.1\n 1'),
2348+
(['10', '-10'], ' 10\n-10')
2349+
])
2350+
def test_to_string_index_false_corner_case(self, inputs, expected):
2351+
s = pd.Series(inputs).to_string(index=False)
2352+
assert s == expected
2353+
23452354
def test_to_string_multindex_header(self):
23462355
# GH 16718
23472356
df = (pd.DataFrame({'a': [0], 'b': [1], 'c': [2], 'd': [3]})
@@ -2750,6 +2759,31 @@ def test_format_percentiles():
27502759
fmt.format_percentiles([0.1, 0.5, 'a'])
27512760

27522761

2762+
@pytest.mark.parametrize("input_array, expected", [
2763+
("a", "a"),
2764+
(["a", "b"], "a\nb"),
2765+
([1, "a"], "1\na"),
2766+
(1, "1"),
2767+
([0, -1], " 0\n-1"),
2768+
(1.0, '1.0')
2769+
])
2770+
def test_format_remove_leading_space_series(input_array, expected):
2771+
# GH: 24980
2772+
s = pd.Series(input_array).to_string(index=False)
2773+
assert s == expected
2774+
2775+
2776+
@pytest.mark.parametrize("input_array, expected", [
2777+
({"A": ["a"]}, "A\na"),
2778+
({"A": ["a", "b"], "B": ["c", "dd"]}, "A B\na c\nb dd"),
2779+
({"A": ["a", 1], "B": ["aa", 1]}, "A B\na aa\n1 1")
2780+
])
2781+
def test_format_remove_leading_space_dataframe(input_array, expected):
2782+
# GH: 24980
2783+
df = pd.DataFrame(input_array).to_string(index=False)
2784+
assert df == expected
2785+
2786+
27532787
def test_repr_html_ipython_config(ip):
27542788
code = textwrap.dedent("""\
27552789
import pandas as pd

pandas/tests/io/formats/test_to_latex.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,10 @@ def test_to_latex(self, frame):
5858
withoutindex_result = df.to_latex(index=False)
5959
withoutindex_expected = r"""\begin{tabular}{rl}
6060
\toprule
61-
a & b \\
61+
a & b \\
6262
\midrule
63-
1 & b1 \\
64-
2 & b2 \\
63+
1 & b1 \\
64+
2 & b2 \\
6565
\bottomrule
6666
\end{tabular}
6767
"""
@@ -417,7 +417,7 @@ def test_to_latex_longtable(self, frame):
417417
withoutindex_result = df.to_latex(index=False, longtable=True)
418418
withoutindex_expected = r"""\begin{longtable}{rl}
419419
\toprule
420-
a & b \\
420+
a & b \\
421421
\midrule
422422
\endhead
423423
\midrule
@@ -427,8 +427,8 @@ def test_to_latex_longtable(self, frame):
427427
428428
\bottomrule
429429
\endlastfoot
430-
1 & b1 \\
431-
2 & b2 \\
430+
1 & b1 \\
431+
2 & b2 \\
432432
\end{longtable}
433433
"""
434434

@@ -484,8 +484,8 @@ def test_to_latex_no_header(self):
484484
withoutindex_result = df.to_latex(index=False, header=False)
485485
withoutindex_expected = r"""\begin{tabular}{rl}
486486
\toprule
487-
1 & b1 \\
488-
2 & b2 \\
487+
1 & b1 \\
488+
2 & b2 \\
489489
\bottomrule
490490
\end{tabular}
491491
"""
@@ -511,10 +511,10 @@ def test_to_latex_specified_header(self):
511511
withoutindex_result = df.to_latex(header=['AA', 'BB'], index=False)
512512
withoutindex_expected = r"""\begin{tabular}{rl}
513513
\toprule
514-
AA & BB \\
514+
AA & BB \\
515515
\midrule
516-
1 & b1 \\
517-
2 & b2 \\
516+
1 & b1 \\
517+
2 & b2 \\
518518
\bottomrule
519519
\end{tabular}
520520
"""

0 commit comments

Comments
 (0)