diff --git a/doc/source/whatsnew/v0.18.0.txt b/doc/source/whatsnew/v0.18.0.txt index ffba681565f48..5acda44c63161 100644 --- a/doc/source/whatsnew/v0.18.0.txt +++ b/doc/source/whatsnew/v0.18.0.txt @@ -185,6 +185,48 @@ In addition, ``.round()``, ``.floor()`` and ``.ceil()`` will be available thru t s s.dt.round('D') + +Formatting of integer in FloatIndex +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Integers in ``FloatIndex``, e.g. 1., are now formatted with a decimal point +and a ``0`` digit, e.g. ``1.0`` (:issue:`11713`) + +This change affects the display in jupyter, but also the output of IO methods +like ``.to_csv`` or ``.to_html`` + +Previous Behavior: + +.. code-block:: python + + In [2]: s = Series([1,2,3], index=np.arange(3.)) + + In [3]: s + Out[3]: + 0 1 + 1 2 + 2 3 + dtype: int64 + + In [4]: s.index + Out[4]: Float64Index([0.0, 1.0, 2.0], dtype='float64') + + In [5]: print(s.to_csv(path=None)) + 0,1 + 1,2 + 2,3 + + +New Behavior: + +.. ipython:: python + + s = Series([1,2,3], index=np.arange(3.)) + s + s.index + print(s.to_csv(path=None)) + + .. _whatsnew_0180.enhancements.other: Other enhancements diff --git a/pandas/core/format.py b/pandas/core/format.py index 10b67d6229234..d7f3a669de9f4 100644 --- a/pandas/core/format.py +++ b/pandas/core/format.py @@ -2115,7 +2115,9 @@ def _format_strings(self): abs_vals = np.abs(self.values) # this is pretty arbitrary for now - has_large_values = (abs_vals > 1e8).any() + # large values: more that 8 characters including decimal symbol + # and first digit, hence > 1e6 + has_large_values = (abs_vals > 1e6).any() has_small_values = ((abs_vals < 10**(-self.digits)) & (abs_vals > 0)).any() @@ -2367,7 +2369,7 @@ def just(x): def _trim_zeros(str_floats, na_rep='NaN'): """ - Trims zeros and decimal points. + Trims zeros, leaving just one before the decimal points if need be. """ trimmed = str_floats @@ -2379,8 +2381,8 @@ def _cond(values): while _cond(trimmed): trimmed = [x[:-1] if x != na_rep else x for x in trimmed] - # trim decimal points - return [x[:-1] if x.endswith('.') and x != na_rep else x for x in trimmed] + # leave one 0 after the decimal points if need be. + return [x + "0" if x.endswith('.') and x != na_rep else x for x in trimmed] def single_column_table(column, align=None, style=None): diff --git a/pandas/tests/test_format.py b/pandas/tests/test_format.py index b7691033dfc83..2ad25ad738649 100644 --- a/pandas/tests/test_format.py +++ b/pandas/tests/test_format.py @@ -204,7 +204,7 @@ def test_repr_chop_threshold(self): self.assertEqual(repr(df), ' 0 1\n0 0.0 0.5\n1 0.5 0.0') with option_context("display.chop_threshold", 0.6): - self.assertEqual(repr(df), ' 0 1\n0 0 0\n1 0 0') + self.assertEqual(repr(df), ' 0 1\n0 0.0 0.0\n1 0.0 0.0') with option_context("display.chop_threshold", None): self.assertEqual(repr(df), ' 0 1\n0 0.1 0.5\n1 0.5 -0.1') @@ -753,7 +753,7 @@ def test_to_html_with_empty_string_label(self): def test_to_html_unicode(self): df = DataFrame({u('\u03c3'): np.arange(10.)}) - expected = u'\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
\u03c3
00
11
22
33
44
55
66
77
88
99
' + expected = u'\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
\u03c3
00.0
11.0
22.0
33.0
44.0
55.0
66.0
77.0
88.0
99.0
' self.assertEqual(df.to_html(), expected) df = DataFrame({'A': [u('\u03c3')]}) expected = u'\n \n \n \n \n \n \n \n \n \n \n \n \n
A
0\u03c3
' @@ -1916,12 +1916,12 @@ def test_to_string_format_na(self): 'B': [np.nan, 'foo', 'foooo', 'fooooo', 'bar']}) result = df.to_string() - expected = (' A B\n' - '0 NaN NaN\n' - '1 -1 foo\n' - '2 -2 foooo\n' - '3 3 fooooo\n' - '4 4 bar') + expected = (' A B\n' + '0 NaN NaN\n' + '1 -1.0 foo\n' + '2 -2.0 foooo\n' + '3 3.0 fooooo\n' + '4 4.0 bar') self.assertEqual(result, expected) def test_to_string_line_width(self): @@ -3760,8 +3760,8 @@ def test_misc(self): def test_format(self): obj = fmt.FloatArrayFormatter(np.array([12, 0], dtype=np.float64)) result = obj.get_result() - self.assertEqual(result[0], " 12") - self.assertEqual(result[1], " 0") + self.assertEqual(result[0], " 12.0") + self.assertEqual(result[1], " 0.0") def test_output_significant_digits(self): # Issue #9764 @@ -3793,15 +3793,15 @@ def test_output_significant_digits(self): def test_too_long(self): # GH 10451 with pd.option_context('display.precision', 4): - # need both a number > 1e8 and something that normally formats to + # need both a number > 1e6 and something that normally formats to # having length > display.precision + 6 df = pd.DataFrame(dict(x=[12345.6789])) self.assertEqual(str(df), ' x\n0 12345.6789') - df = pd.DataFrame(dict(x=[2e8])) - self.assertEqual(str(df), ' x\n0 200000000') - df = pd.DataFrame(dict(x=[12345.6789, 2e8])) + df = pd.DataFrame(dict(x=[2e6])) + self.assertEqual(str(df), ' x\n0 2000000.0') + df = pd.DataFrame(dict(x=[12345.6789, 2e6])) self.assertEqual( - str(df), ' x\n0 1.2346e+04\n1 2.0000e+08') + str(df), ' x\n0 1.2346e+04\n1 2.0000e+06') class TestRepr_timedelta64(tm.TestCase):