Skip to content

Commit

Permalink
BUG: Display precision doesn't affect complex float numbers #25514 (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
sakarpanta authored and jreback committed Apr 12, 2019
1 parent 22c2b73 commit 90a85e0
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 12 deletions.
1 change: 1 addition & 0 deletions doc/source/whatsnew/v0.25.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,7 @@ Numeric

- Bug in :meth:`to_numeric` in which large negative numbers were being improperly handled (:issue:`24910`)
- Bug in :meth:`to_numeric` in which numbers were being coerced to float, even though ``errors`` was not ``coerce`` (:issue:`24910`)
- Bug in :class:`format` in which floating point complex numbers were not being formatted to proper display precision and trimming (:issue:`25514`)
- Bug in error messages in :meth:`DataFrame.corr` and :meth:`Series.corr`. Added the possibility of using a callable. (:issue:`25729`)
- Bug in :meth:`Series.divmod` and :meth:`Series.rdivmod` which would raise an (incorrect) ``ValueError`` rather than return a pair of :class:`Series` objects as result (:issue:`25557`)
- Raises a helpful exception when a non-numeric index is sent to :meth:`interpolate` with methods which require numeric index. (:issue:`21662`)
Expand Down
12 changes: 6 additions & 6 deletions pandas/core/frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -2497,12 +2497,12 @@ def memory_usage(self, index=True, deep=False):
... for t in dtypes])
>>> df = pd.DataFrame(data)
>>> df.head()
int64 float64 complex128 object bool
0 1 1.0 (1+0j) 1 True
1 1 1.0 (1+0j) 1 True
2 1 1.0 (1+0j) 1 True
3 1 1.0 (1+0j) 1 True
4 1 1.0 (1+0j) 1 True
int64 float64 complex128 object bool
0 1 1.0 1.0+0.0j 1 True
1 1 1.0 1.0+0.0j 1 True
2 1 1.0 1.0+0.0j 1 True
3 1 1.0 1.0+0.0j 1 True
4 1 1.0 1.0+0.0j 1 True
>>> df.memory_usage()
Index 80
Expand Down
31 changes: 25 additions & 6 deletions pandas/io/formats/format.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@
from pandas.compat import lzip

from pandas.core.dtypes.common import (
is_categorical_dtype, is_datetime64_dtype, is_datetime64tz_dtype,
is_extension_array_dtype, is_float, is_float_dtype, is_integer,
is_integer_dtype, is_list_like, is_numeric_dtype, is_scalar,
is_categorical_dtype, is_complex_dtype, is_datetime64_dtype,
is_datetime64tz_dtype, is_extension_array_dtype, is_float, is_float_dtype,
is_integer, is_integer_dtype, is_list_like, is_numeric_dtype, is_scalar,
is_timedelta64_dtype)
from pandas.core.dtypes.generic import (
ABCIndexClass, ABCMultiIndex, ABCSeries, ABCSparseArray)
Expand Down Expand Up @@ -892,7 +892,7 @@ def format_array(values, formatter, float_format=None, na_rep='NaN',
fmt_klass = Timedelta64Formatter
elif is_extension_array_dtype(values.dtype):
fmt_klass = ExtensionArrayFormatter
elif is_float_dtype(values.dtype):
elif is_float_dtype(values.dtype) or is_complex_dtype(values.dtype):
fmt_klass = FloatArrayFormatter
elif is_integer_dtype(values.dtype):
fmt_klass = IntArrayFormatter
Expand Down Expand Up @@ -1084,6 +1084,7 @@ def format_values_with(float_format):

# separate the wheat from the chaff
values = self.values
is_complex = is_complex_dtype(values)
mask = isna(values)
if hasattr(values, 'to_dense'): # sparse numpy ndarray
values = values.to_dense()
Expand All @@ -1094,7 +1095,10 @@ def format_values_with(float_format):
for val in values.ravel()[imask]])

if self.fixed_width:
return _trim_zeros(values, na_rep)
if is_complex:
return _trim_zeros_complex(values, na_rep)
else:
return _trim_zeros_float(values, na_rep)

return values

Expand Down Expand Up @@ -1424,7 +1428,22 @@ def just(x):
return result


def _trim_zeros(str_floats, na_rep='NaN'):
def _trim_zeros_complex(str_complexes, na_rep='NaN'):
"""
Separates the real and imaginary parts from the complex number, and
executes the _trim_zeros_float method on each of those.
"""
def separate_and_trim(str_complex, na_rep):
num_arr = str_complex.split('+')
return (_trim_zeros_float([num_arr[0]], na_rep) +
['+'] +
_trim_zeros_float([num_arr[1][:-1]], na_rep) +
['j'])

return [''.join(separate_and_trim(x, na_rep)) for x in str_complexes]


def _trim_zeros_float(str_floats, na_rep='NaN'):
"""
Trims zeros, leaving just one before the decimal points if need be.
"""
Expand Down
13 changes: 13 additions & 0 deletions pandas/tests/io/formats/test_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -1370,6 +1370,19 @@ def test_to_string_float_index(self):
'5.0 4')
assert result == expected

def test_to_string_complex_float_formatting(self):
# GH #25514
with pd.option_context('display.precision', 5):
df = DataFrame({'x': [
(0.4467846931321966 + 0.0715185102060818j),
(0.2739442392974528 + 0.23515228785438969j),
(0.26974928742135185 + 0.3250604054898979j)]})
result = df.to_string()
expected = (' x\n0 0.44678+0.07152j\n'
'1 0.27394+0.23515j\n'
'2 0.26975+0.32506j')
assert result == expected

def test_to_string_ascii_error(self):
data = [('0 ', ' .gitignore ', ' 5 ',
' \xe2\x80\xa2\xe2\x80\xa2\xe2\x80'
Expand Down

0 comments on commit 90a85e0

Please sign in to comment.