Skip to content

Commit 6693a72

Browse files
nbonnottejreback
authored andcommitted
ENH: formatting integers in FloatIndex as floats
xref #12164 closes #11719 closes #12207
1 parent 52c547a commit 6693a72

File tree

3 files changed

+63
-19
lines changed

3 files changed

+63
-19
lines changed

doc/source/whatsnew/v0.18.0.txt

+42
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,48 @@ In addition, ``.round()``, ``.floor()`` and ``.ceil()`` will be available thru t
185185
s
186186
s.dt.round('D')
187187

188+
189+
Formatting of integer in FloatIndex
190+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
191+
192+
Integers in ``FloatIndex``, e.g. 1., are now formatted with a decimal point
193+
and a ``0`` digit, e.g. ``1.0`` (:issue:`11713`)
194+
195+
This change affects the display in jupyter, but also the output of IO methods
196+
like ``.to_csv`` or ``.to_html``
197+
198+
Previous Behavior:
199+
200+
.. code-block:: python
201+
202+
In [2]: s = Series([1,2,3], index=np.arange(3.))
203+
204+
In [3]: s
205+
Out[3]:
206+
0 1
207+
1 2
208+
2 3
209+
dtype: int64
210+
211+
In [4]: s.index
212+
Out[4]: Float64Index([0.0, 1.0, 2.0], dtype='float64')
213+
214+
In [5]: print(s.to_csv(path=None))
215+
0,1
216+
1,2
217+
2,3
218+
219+
220+
New Behavior:
221+
222+
.. ipython:: python
223+
224+
s = Series([1,2,3], index=np.arange(3.))
225+
s
226+
s.index
227+
print(s.to_csv(path=None))
228+
229+
188230
.. _whatsnew_0180.enhancements.other:
189231

190232
Other enhancements

pandas/core/format.py

+6-4
Original file line numberDiff line numberDiff line change
@@ -2115,7 +2115,9 @@ def _format_strings(self):
21152115
abs_vals = np.abs(self.values)
21162116

21172117
# this is pretty arbitrary for now
2118-
has_large_values = (abs_vals > 1e8).any()
2118+
# large values: more that 8 characters including decimal symbol
2119+
# and first digit, hence > 1e6
2120+
has_large_values = (abs_vals > 1e6).any()
21192121
has_small_values = ((abs_vals < 10**(-self.digits)) &
21202122
(abs_vals > 0)).any()
21212123

@@ -2367,7 +2369,7 @@ def just(x):
23672369

23682370
def _trim_zeros(str_floats, na_rep='NaN'):
23692371
"""
2370-
Trims zeros and decimal points.
2372+
Trims zeros, leaving just one before the decimal points if need be.
23712373
"""
23722374
trimmed = str_floats
23732375

@@ -2379,8 +2381,8 @@ def _cond(values):
23792381
while _cond(trimmed):
23802382
trimmed = [x[:-1] if x != na_rep else x for x in trimmed]
23812383

2382-
# trim decimal points
2383-
return [x[:-1] if x.endswith('.') and x != na_rep else x for x in trimmed]
2384+
# leave one 0 after the decimal points if need be.
2385+
return [x + "0" if x.endswith('.') and x != na_rep else x for x in trimmed]
23842386

23852387

23862388
def single_column_table(column, align=None, style=None):

pandas/tests/test_format.py

+15-15
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ def test_repr_chop_threshold(self):
204204
self.assertEqual(repr(df), ' 0 1\n0 0.0 0.5\n1 0.5 0.0')
205205

206206
with option_context("display.chop_threshold", 0.6):
207-
self.assertEqual(repr(df), ' 0 1\n0 0 0\n1 0 0')
207+
self.assertEqual(repr(df), ' 0 1\n0 0.0 0.0\n1 0.0 0.0')
208208

209209
with option_context("display.chop_threshold", None):
210210
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):
753753

754754
def test_to_html_unicode(self):
755755
df = DataFrame({u('\u03c3'): np.arange(10.)})
756-
expected = u'<table border="1" class="dataframe">\n <thead>\n <tr style="text-align: right;">\n <th></th>\n <th>\u03c3</th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <th>0</th>\n <td>0</td>\n </tr>\n <tr>\n <th>1</th>\n <td>1</td>\n </tr>\n <tr>\n <th>2</th>\n <td>2</td>\n </tr>\n <tr>\n <th>3</th>\n <td>3</td>\n </tr>\n <tr>\n <th>4</th>\n <td>4</td>\n </tr>\n <tr>\n <th>5</th>\n <td>5</td>\n </tr>\n <tr>\n <th>6</th>\n <td>6</td>\n </tr>\n <tr>\n <th>7</th>\n <td>7</td>\n </tr>\n <tr>\n <th>8</th>\n <td>8</td>\n </tr>\n <tr>\n <th>9</th>\n <td>9</td>\n </tr>\n </tbody>\n</table>'
756+
expected = u'<table border="1" class="dataframe">\n <thead>\n <tr style="text-align: right;">\n <th></th>\n <th>\u03c3</th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <th>0</th>\n <td>0.0</td>\n </tr>\n <tr>\n <th>1</th>\n <td>1.0</td>\n </tr>\n <tr>\n <th>2</th>\n <td>2.0</td>\n </tr>\n <tr>\n <th>3</th>\n <td>3.0</td>\n </tr>\n <tr>\n <th>4</th>\n <td>4.0</td>\n </tr>\n <tr>\n <th>5</th>\n <td>5.0</td>\n </tr>\n <tr>\n <th>6</th>\n <td>6.0</td>\n </tr>\n <tr>\n <th>7</th>\n <td>7.0</td>\n </tr>\n <tr>\n <th>8</th>\n <td>8.0</td>\n </tr>\n <tr>\n <th>9</th>\n <td>9.0</td>\n </tr>\n </tbody>\n</table>'
757757
self.assertEqual(df.to_html(), expected)
758758
df = DataFrame({'A': [u('\u03c3')]})
759759
expected = u'<table border="1" class="dataframe">\n <thead>\n <tr style="text-align: right;">\n <th></th>\n <th>A</th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <th>0</th>\n <td>\u03c3</td>\n </tr>\n </tbody>\n</table>'
@@ -1916,12 +1916,12 @@ def test_to_string_format_na(self):
19161916
'B': [np.nan, 'foo', 'foooo', 'fooooo', 'bar']})
19171917
result = df.to_string()
19181918

1919-
expected = (' A B\n'
1920-
'0 NaN NaN\n'
1921-
'1 -1 foo\n'
1922-
'2 -2 foooo\n'
1923-
'3 3 fooooo\n'
1924-
'4 4 bar')
1919+
expected = (' A B\n'
1920+
'0 NaN NaN\n'
1921+
'1 -1.0 foo\n'
1922+
'2 -2.0 foooo\n'
1923+
'3 3.0 fooooo\n'
1924+
'4 4.0 bar')
19251925
self.assertEqual(result, expected)
19261926

19271927
def test_to_string_line_width(self):
@@ -3760,8 +3760,8 @@ def test_misc(self):
37603760
def test_format(self):
37613761
obj = fmt.FloatArrayFormatter(np.array([12, 0], dtype=np.float64))
37623762
result = obj.get_result()
3763-
self.assertEqual(result[0], " 12")
3764-
self.assertEqual(result[1], " 0")
3763+
self.assertEqual(result[0], " 12.0")
3764+
self.assertEqual(result[1], " 0.0")
37653765

37663766
def test_output_significant_digits(self):
37673767
# Issue #9764
@@ -3793,15 +3793,15 @@ def test_output_significant_digits(self):
37933793
def test_too_long(self):
37943794
# GH 10451
37953795
with pd.option_context('display.precision', 4):
3796-
# need both a number > 1e8 and something that normally formats to
3796+
# need both a number > 1e6 and something that normally formats to
37973797
# having length > display.precision + 6
37983798
df = pd.DataFrame(dict(x=[12345.6789]))
37993799
self.assertEqual(str(df), ' x\n0 12345.6789')
3800-
df = pd.DataFrame(dict(x=[2e8]))
3801-
self.assertEqual(str(df), ' x\n0 200000000')
3802-
df = pd.DataFrame(dict(x=[12345.6789, 2e8]))
3800+
df = pd.DataFrame(dict(x=[2e6]))
3801+
self.assertEqual(str(df), ' x\n0 2000000.0')
3802+
df = pd.DataFrame(dict(x=[12345.6789, 2e6]))
38033803
self.assertEqual(
3804-
str(df), ' x\n0 1.2346e+04\n1 2.0000e+08')
3804+
str(df), ' x\n0 1.2346e+04\n1 2.0000e+06')
38053805

38063806

38073807
class TestRepr_timedelta64(tm.TestCase):

0 commit comments

Comments
 (0)