From 406ed4d41e65ad408c0d0ca357751adaa5b16437 Mon Sep 17 00:00:00 2001 From: Daniel Saxton Date: Thu, 1 Oct 2020 19:56:19 -0500 Subject: [PATCH 01/17] CLN: Clean float / complex string formatting --- pandas/io/formats/format.py | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/pandas/io/formats/format.py b/pandas/io/formats/format.py index b9d41f142c2b5..52c3acf4d52e2 100644 --- a/pandas/io/formats/format.py +++ b/pandas/io/formats/format.py @@ -1473,9 +1473,9 @@ def format_values_with(float_format): if self.fixed_width: if is_complex: - result = _trim_zeros_complex(values, self.decimal, na_rep) + result = values else: - result = _trim_zeros_float(values, self.decimal, na_rep) + result = _trim_zeros_float(values, self.decimal) return np.asarray(result, dtype="object") return values @@ -1855,21 +1855,8 @@ def just(x): return result -def _trim_zeros_complex( - str_complexes: np.ndarray, decimal: str = ".", na_rep: str = "NaN" -) -> List[str]: - """ - Separates the real and imaginary parts from the complex number, and - executes the _trim_zeros_float method on each of those. - """ - return [ - "".join(_trim_zeros_float(re.split(r"([j+-])", x), decimal, na_rep)) - for x in str_complexes - ] - - def _trim_zeros_float( - str_floats: Union[np.ndarray, List[str]], decimal: str = ".", na_rep: str = "NaN" + str_floats: Union[np.ndarray, List[str]], decimal: str = "." ) -> List[str]: """ Trims zeros, leaving just one before the decimal points if need be. @@ -1877,7 +1864,7 @@ def _trim_zeros_float( trimmed = str_floats def _is_number(x): - return x != na_rep and not x.endswith("inf") + return re.match(r"\s*-?[0-9]+(\.[0-9]+)?", x) is not None def _cond(values): finite = [x for x in values if _is_number(x)] From a1228c9f9d50d05dce435da2f27cd55903b547ef Mon Sep 17 00:00:00 2001 From: Daniel Saxton Date: Thu, 1 Oct 2020 20:22:05 -0500 Subject: [PATCH 02/17] Fix --- pandas/io/formats/format.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/io/formats/format.py b/pandas/io/formats/format.py index 52c3acf4d52e2..653aec2f2925d 100644 --- a/pandas/io/formats/format.py +++ b/pandas/io/formats/format.py @@ -1864,7 +1864,7 @@ def _trim_zeros_float( trimmed = str_floats def _is_number(x): - return re.match(r"\s*-?[0-9]+(\.[0-9]+)?", x) is not None + return re.match(r"\s*-?[0-9]+(\.[0-9]*)?", x) is not None def _cond(values): finite = [x for x in values if _is_number(x)] From 72be97fac7db649caeb65275782496d9d154472d Mon Sep 17 00:00:00 2001 From: Daniel Saxton Date: Fri, 2 Oct 2020 12:16:04 -0500 Subject: [PATCH 03/17] Fix and test --- pandas/io/formats/format.py | 38 ++++++++++++++++++++++++-- pandas/tests/io/formats/test_format.py | 7 +++++ 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/pandas/io/formats/format.py b/pandas/io/formats/format.py index 653aec2f2925d..8243648e16f4f 100644 --- a/pandas/io/formats/format.py +++ b/pandas/io/formats/format.py @@ -1473,7 +1473,8 @@ def format_values_with(float_format): if self.fixed_width: if is_complex: - result = values + result = _trim_zeros_complex(values, self.decimal) + result = _post_process_complex(result) else: result = _trim_zeros_float(values, self.decimal) return np.asarray(result, dtype="object") @@ -1855,6 +1856,39 @@ def just(x): return result +def _trim_zeros_complex(str_complexes: np.ndarray, decimal: str = ".") -> List[str]: + """ + Separates the real and imaginary parts from the complex number, and + executes the _trim_zeros_float method on each of those. + """ + return [ + "".join(_trim_zeros_float(re.split(r"([j+-])", x), decimal)) + for x in str_complexes + ] + + +def _post_process_complex(complex_strings: List[str]) -> List[str]: + """ + Zero pad complex number strings to equal length. + + This helper is needed because _trim_zeros_complex handles each complex + number independently and therefore can't pad to equal length. The input + strings here are assumed to be of the form " 1.000+1.000j", where the + real and imaginary parts have equal length. + """ + max_length = max(len(x) for x in complex_strings) + length_deltas = [max_length - len(x) for x in complex_strings] + result = [ + x[: -(d // 2 + 1)] + + (max_length - len(x)) // 2 * "0" + + x[-(d // 2 + 1) : -1] + + (max_length - len(x)) // 2 * "0" + + x[-1] + for x, d in zip(complex_strings, length_deltas) + ] + return result + + def _trim_zeros_float( str_floats: Union[np.ndarray, List[str]], decimal: str = "." ) -> List[str]: @@ -1864,7 +1898,7 @@ def _trim_zeros_float( trimmed = str_floats def _is_number(x): - return re.match(r"\s*-?[0-9]+(\.[0-9]*)?", x) is not None + return re.match(fr"\s*-?[0-9]+({decimal}[0-9]*)?", x) is not None def _cond(values): finite = [x for x in values if _is_number(x)] diff --git a/pandas/tests/io/formats/test_format.py b/pandas/tests/io/formats/test_format.py index 68f5386fff7be..8fc0411835dd7 100644 --- a/pandas/tests/io/formats/test_format.py +++ b/pandas/tests/io/formats/test_format.py @@ -3432,3 +3432,10 @@ def test_format_remove_leading_space_dataframe(input_array, expected): # GH: 24980 df = pd.DataFrame(input_array).to_string(index=False) assert df == expected + + +def test_to_string_complex_number_trims_zeros(): + s = pd.Series([1.0000 + 1.0000j, 1.0 + 1.0j]) + result = s.to_string() + expected = "0 1.0+1.0j\n1 1.0+1.0j" + assert result == expected From e1d1ba3b124af9b9c3469aebff71e2b0910c7082 Mon Sep 17 00:00:00 2001 From: Daniel Saxton Date: Fri, 2 Oct 2020 12:19:48 -0500 Subject: [PATCH 04/17] Fix --- pandas/io/formats/format.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/pandas/io/formats/format.py b/pandas/io/formats/format.py index 8243648e16f4f..c3832c886878a 100644 --- a/pandas/io/formats/format.py +++ b/pandas/io/formats/format.py @@ -1879,11 +1879,7 @@ def _post_process_complex(complex_strings: List[str]) -> List[str]: max_length = max(len(x) for x in complex_strings) length_deltas = [max_length - len(x) for x in complex_strings] result = [ - x[: -(d // 2 + 1)] - + (max_length - len(x)) // 2 * "0" - + x[-(d // 2 + 1) : -1] - + (max_length - len(x)) // 2 * "0" - + x[-1] + x[: -(d // 2 + 1)] + d // 2 * "0" + x[-(d // 2 + 1) : -1] + d // 2 * "0" + x[-1] for x, d in zip(complex_strings, length_deltas) ] return result From d38839ca85faca7e70539c8fe7f05b29d8831cce Mon Sep 17 00:00:00 2001 From: Daniel Saxton Date: Fri, 2 Oct 2020 12:21:30 -0500 Subject: [PATCH 05/17] Fix --- pandas/io/formats/format.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pandas/io/formats/format.py b/pandas/io/formats/format.py index c3832c886878a..18bb0272e7d54 100644 --- a/pandas/io/formats/format.py +++ b/pandas/io/formats/format.py @@ -1877,10 +1877,10 @@ def _post_process_complex(complex_strings: List[str]) -> List[str]: real and imaginary parts have equal length. """ max_length = max(len(x) for x in complex_strings) - length_deltas = [max_length - len(x) for x in complex_strings] + half_deltas = [(max_length - len(x)) // 2 for x in complex_strings] result = [ - x[: -(d // 2 + 1)] + d // 2 * "0" + x[-(d // 2 + 1) : -1] + d // 2 * "0" + x[-1] - for x, d in zip(complex_strings, length_deltas) + x[: -(d + 1)] + d * "0" + x[-(d + 1) : -1] + d * "0" + x[-1] + for x, d in zip(complex_strings, half_deltas) ] return result From 0da1c465810e4112be3d3996156a62ade90170e0 Mon Sep 17 00:00:00 2001 From: Daniel Saxton Date: Fri, 2 Oct 2020 12:22:58 -0500 Subject: [PATCH 06/17] Nit --- pandas/io/formats/format.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pandas/io/formats/format.py b/pandas/io/formats/format.py index 18bb0272e7d54..ff7ec2398a92e 100644 --- a/pandas/io/formats/format.py +++ b/pandas/io/formats/format.py @@ -1878,11 +1878,11 @@ def _post_process_complex(complex_strings: List[str]) -> List[str]: """ max_length = max(len(x) for x in complex_strings) half_deltas = [(max_length - len(x)) // 2 for x in complex_strings] - result = [ + padded = [ x[: -(d + 1)] + d * "0" + x[-(d + 1) : -1] + d * "0" + x[-1] for x, d in zip(complex_strings, half_deltas) ] - return result + return padded def _trim_zeros_float( From 4ea7dcf715c95bef3607e2448e7c00728033fe88 Mon Sep 17 00:00:00 2001 From: Daniel Saxton Date: Fri, 2 Oct 2020 12:24:52 -0500 Subject: [PATCH 07/17] Nit --- pandas/io/formats/format.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pandas/io/formats/format.py b/pandas/io/formats/format.py index ff7ec2398a92e..646dc58a45445 100644 --- a/pandas/io/formats/format.py +++ b/pandas/io/formats/format.py @@ -1879,8 +1879,8 @@ def _post_process_complex(complex_strings: List[str]) -> List[str]: max_length = max(len(x) for x in complex_strings) half_deltas = [(max_length - len(x)) // 2 for x in complex_strings] padded = [ - x[: -(d + 1)] + d * "0" + x[-(d + 1) : -1] + d * "0" + x[-1] - for x, d in zip(complex_strings, half_deltas) + s[: -(d + 1)] + d * "0" + s[-(d + 1) : -1] + d * "0" + s[-1] + for s, d in zip(complex_strings, half_deltas) ] return padded From 376b06edecd293b6870f9790a55ed55aff51f2c2 Mon Sep 17 00:00:00 2001 From: Daniel Saxton Date: Fri, 2 Oct 2020 13:10:02 -0500 Subject: [PATCH 08/17] Change doc --- pandas/core/frame.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pandas/core/frame.py b/pandas/core/frame.py index 9b2540a1ce043..a88b0bd7d2332 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -2650,11 +2650,11 @@ def memory_usage(self, index=True, deep=False) -> Series: >>> df = pd.DataFrame(data) >>> df.head() int64 float64 complex128 object bool - 0 1 1.0 1.000000+0.000000j 1 True - 1 1 1.0 1.000000+0.000000j 1 True - 2 1 1.0 1.000000+0.000000j 1 True - 3 1 1.0 1.000000+0.000000j 1 True - 4 1 1.0 1.000000+0.000000j 1 True + 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 128 From e564fee77f6f05325fb8ec7536bfa65198c16ac6 Mon Sep 17 00:00:00 2001 From: Daniel Saxton Date: Fri, 2 Oct 2020 13:12:49 -0500 Subject: [PATCH 09/17] Escape --- pandas/io/formats/format.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/io/formats/format.py b/pandas/io/formats/format.py index 646dc58a45445..bdf75b859dd84 100644 --- a/pandas/io/formats/format.py +++ b/pandas/io/formats/format.py @@ -1894,7 +1894,7 @@ def _trim_zeros_float( trimmed = str_floats def _is_number(x): - return re.match(fr"\s*-?[0-9]+({decimal}[0-9]*)?", x) is not None + return re.match(fr"\s*-?[0-9]+(\{decimal}[0-9]*)?", x) is not None def _cond(values): finite = [x for x in values if _is_number(x)] From 6cec3171a306b40288a66ba70dab1107105f3999 Mon Sep 17 00:00:00 2001 From: Daniel Saxton Date: Fri, 2 Oct 2020 15:17:24 -0500 Subject: [PATCH 10/17] Add failing test --- pandas/tests/io/formats/test_format.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pandas/tests/io/formats/test_format.py b/pandas/tests/io/formats/test_format.py index 8fc0411835dd7..a4070f73eadee 100644 --- a/pandas/tests/io/formats/test_format.py +++ b/pandas/tests/io/formats/test_format.py @@ -3435,7 +3435,7 @@ def test_format_remove_leading_space_dataframe(input_array, expected): def test_to_string_complex_number_trims_zeros(): - s = pd.Series([1.0000 + 1.0000j, 1.0 + 1.0j]) + s = pd.Series([1.000000 + 1.000000j, 1.0 + 1.0j, 1.0005 + 1.0j]) result = s.to_string() - expected = "0 1.0+1.0j\n1 1.0+1.0j" + expected = "0 1.0000+1.0j\n1 1.0000+1.0j\n2 1.0005+1.0j" assert result == expected From 50ccbc0c73ea8b7a54aa3afede4158e9996dacb2 Mon Sep 17 00:00:00 2001 From: Daniel Saxton Date: Fri, 2 Oct 2020 15:19:58 -0500 Subject: [PATCH 11/17] Edit --- pandas/io/formats/format.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/pandas/io/formats/format.py b/pandas/io/formats/format.py index bdf75b859dd84..02d5409265959 100644 --- a/pandas/io/formats/format.py +++ b/pandas/io/formats/format.py @@ -1869,12 +1869,7 @@ def _trim_zeros_complex(str_complexes: np.ndarray, decimal: str = ".") -> List[s def _post_process_complex(complex_strings: List[str]) -> List[str]: """ - Zero pad complex number strings to equal length. - - This helper is needed because _trim_zeros_complex handles each complex - number independently and therefore can't pad to equal length. The input - strings here are assumed to be of the form " 1.000+1.000j", where the - real and imaginary parts have equal length. + Zero pad complex number strings produced by _trim_zeros_complex. """ max_length = max(len(x) for x in complex_strings) half_deltas = [(max_length - len(x)) // 2 for x in complex_strings] From e725cb203508ebbdb1a4d810d85fed80508526fd Mon Sep 17 00:00:00 2001 From: Daniel Saxton Date: Fri, 2 Oct 2020 15:56:19 -0500 Subject: [PATCH 12/17] Maybe --- pandas/io/formats/format.py | 14 ++++++++++---- pandas/tests/io/formats/test_format.py | 4 ++-- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/pandas/io/formats/format.py b/pandas/io/formats/format.py index 02d5409265959..b8026c26cf68e 100644 --- a/pandas/io/formats/format.py +++ b/pandas/io/formats/format.py @@ -1871,11 +1871,17 @@ def _post_process_complex(complex_strings: List[str]) -> List[str]: """ Zero pad complex number strings produced by _trim_zeros_complex. """ - max_length = max(len(x) for x in complex_strings) - half_deltas = [(max_length - len(x)) // 2 for x in complex_strings] + lengths = [len(s) for s in complex_strings] + max_length = max(lengths) + half_deltas = [(max_length - k) // 2 for k in lengths] padded = [ - s[: -(d + 1)] + d * "0" + s[-(d + 1) : -1] + d * "0" + s[-1] - for s, d in zip(complex_strings, half_deltas) + s[: -((k - 1) // 2 + 1)] + + d * "0" + + s[-((k - 1) // 2 + 1) : -((k - 1) // 2)] + + s[-((k - 1) // 2) : -1] + + d * "0" + + s[-1] + for s, k, d in zip(complex_strings, lengths, half_deltas) ] return padded diff --git a/pandas/tests/io/formats/test_format.py b/pandas/tests/io/formats/test_format.py index a4070f73eadee..b30ceed23b02e 100644 --- a/pandas/tests/io/formats/test_format.py +++ b/pandas/tests/io/formats/test_format.py @@ -3435,7 +3435,7 @@ def test_format_remove_leading_space_dataframe(input_array, expected): def test_to_string_complex_number_trims_zeros(): - s = pd.Series([1.000000 + 1.000000j, 1.0 + 1.0j, 1.0005 + 1.0j]) + s = pd.Series([1.000000 + 1.000000j, 1.0 + 1.0j, 1.05 + 1.0j]) result = s.to_string() - expected = "0 1.0000+1.0j\n1 1.0000+1.0j\n2 1.0005+1.0j" + expected = "0 1.00+1.00j\n1 1.00+1.00j\n2 1.05+1.00j" assert result == expected From 03e8cab57400ce30b35a82c64aead13fba014e69 Mon Sep 17 00:00:00 2001 From: Daniel Saxton Date: Fri, 2 Oct 2020 16:09:44 -0500 Subject: [PATCH 13/17] Comment --- pandas/io/formats/format.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pandas/io/formats/format.py b/pandas/io/formats/format.py index b8026c26cf68e..c95ee1e008ba5 100644 --- a/pandas/io/formats/format.py +++ b/pandas/io/formats/format.py @@ -1875,10 +1875,10 @@ def _post_process_complex(complex_strings: List[str]) -> List[str]: max_length = max(lengths) half_deltas = [(max_length - k) // 2 for k in lengths] padded = [ - s[: -((k - 1) // 2 + 1)] + s[: -((k - 1) // 2 + 1)] # real part + d * "0" - + s[-((k - 1) // 2 + 1) : -((k - 1) // 2)] - + s[-((k - 1) // 2) : -1] + + s[-((k - 1) // 2 + 1) : -((k - 1) // 2)] # + / - + + s[-((k - 1) // 2) : -1] # imaginary part + d * "0" + s[-1] for s, k, d in zip(complex_strings, lengths, half_deltas) From 46949fd873b4e11923f79bcabd56436a0ece62eb Mon Sep 17 00:00:00 2001 From: Daniel Saxton Date: Fri, 2 Oct 2020 16:15:43 -0500 Subject: [PATCH 14/17] Remove --- pandas/io/formats/format.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/pandas/io/formats/format.py b/pandas/io/formats/format.py index c95ee1e008ba5..022d15bad88d0 100644 --- a/pandas/io/formats/format.py +++ b/pandas/io/formats/format.py @@ -1873,15 +1873,14 @@ def _post_process_complex(complex_strings: List[str]) -> List[str]: """ lengths = [len(s) for s in complex_strings] max_length = max(lengths) - half_deltas = [(max_length - k) // 2 for k in lengths] padded = [ s[: -((k - 1) // 2 + 1)] # real part - + d * "0" + + (max_length - k) // 2 * "0" + s[-((k - 1) // 2 + 1) : -((k - 1) // 2)] # + / - + s[-((k - 1) // 2) : -1] # imaginary part - + d * "0" + + (max_length - k) // 2 * "0" + s[-1] - for s, k, d in zip(complex_strings, lengths, half_deltas) + for s, k in zip(complex_strings, lengths) ] return padded From 11f20d01c570baa9c0592b738ae6a7aa83d29be9 Mon Sep 17 00:00:00 2001 From: Daniel Saxton Date: Sat, 3 Oct 2020 01:05:37 -0500 Subject: [PATCH 15/17] Compile and comment --- pandas/io/formats/format.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/pandas/io/formats/format.py b/pandas/io/formats/format.py index 022d15bad88d0..1b24220846f87 100644 --- a/pandas/io/formats/format.py +++ b/pandas/io/formats/format.py @@ -1870,6 +1870,11 @@ def _trim_zeros_complex(str_complexes: np.ndarray, decimal: str = ".") -> List[s def _post_process_complex(complex_strings: List[str]) -> List[str]: """ Zero pad complex number strings produced by _trim_zeros_complex. + + Input strings are assumed to be of the form " 1.000+1.000j" with a + leading space and the real and imaginary parts having equal precision. + The output strings will all have length equal to that of the longest + input string. """ lengths = [len(s) for s in complex_strings] max_length = max(lengths) @@ -1892,9 +1897,10 @@ def _trim_zeros_float( Trims zeros, leaving just one before the decimal points if need be. """ trimmed = str_floats + number_regex = re.compile(fr"\s*[\+-]?[0-9]+(\{decimal}[0-9]*)?") def _is_number(x): - return re.match(fr"\s*-?[0-9]+(\{decimal}[0-9]*)?", x) is not None + return re.match(number_regex, x) is not None def _cond(values): finite = [x for x in values if _is_number(x)] From 0e0dd926903fc70765967080fc9817f868919b97 Mon Sep 17 00:00:00 2001 From: Daniel Saxton Date: Thu, 8 Oct 2020 16:11:15 -0500 Subject: [PATCH 16/17] Move into other function --- pandas/io/formats/format.py | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/pandas/io/formats/format.py b/pandas/io/formats/format.py index 98cf70247ef09..bdddd319531dc 100644 --- a/pandas/io/formats/format.py +++ b/pandas/io/formats/format.py @@ -1474,7 +1474,6 @@ def format_values_with(float_format): if self.fixed_width: if is_complex: result = _trim_zeros_complex(values, self.decimal) - result = _post_process_complex(result) else: result = _trim_zeros_float(values, self.decimal) return np.asarray(result, dtype="object") @@ -1862,22 +1861,13 @@ def _trim_zeros_complex(str_complexes: np.ndarray, decimal: str = ".") -> List[s Separates the real and imaginary parts from the complex number, and executes the _trim_zeros_float method on each of those. """ - return [ + trimmed = [ "".join(_trim_zeros_float(re.split(r"([j+-])", x), decimal)) for x in str_complexes ] - -def _post_process_complex(complex_strings: List[str]) -> List[str]: - """ - Zero pad complex number strings produced by _trim_zeros_complex. - - Input strings are assumed to be of the form " 1.000+1.000j" with a - leading space and the real and imaginary parts having equal precision. - The output strings will all have length equal to that of the longest - input string. - """ - lengths = [len(s) for s in complex_strings] + # pad strings to the length of the longest trimmed string for alignment + lengths = [len(s) for s in trimmed] max_length = max(lengths) padded = [ s[: -((k - 1) // 2 + 1)] # real part @@ -1886,7 +1876,7 @@ def _post_process_complex(complex_strings: List[str]) -> List[str]: + s[-((k - 1) // 2) : -1] # imaginary part + (max_length - k) // 2 * "0" + s[-1] - for s, k in zip(complex_strings, lengths) + for s, k in zip(trimmed, lengths) ] return padded From eca0413161343fe5dd7e088d49eec5795f78fdba Mon Sep 17 00:00:00 2001 From: Daniel Saxton Date: Sat, 10 Oct 2020 20:10:29 -0500 Subject: [PATCH 17/17] Note --- doc/source/whatsnew/v1.2.0.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/source/whatsnew/v1.2.0.rst b/doc/source/whatsnew/v1.2.0.rst index 883697efeab7f..8ea5a5c587c3f 100644 --- a/doc/source/whatsnew/v1.2.0.rst +++ b/doc/source/whatsnew/v1.2.0.rst @@ -423,6 +423,7 @@ I/O - Bug in :func:`read_table` and :func:`read_csv` when ``delim_whitespace=True`` and ``sep=default`` (:issue:`36583`) - Bug in :meth:`to_json` with ``lines=True`` and ``orient='records'`` the last line of the record is not appended with 'new line character' (:issue:`36888`) - Bug in :meth:`read_parquet` with fixed offset timezones. String representation of timezones was not recognized (:issue:`35997`, :issue:`36004`) +- Bug in output rendering of complex numbers showing too many trailing zeros (:issue:`36799`) Plotting ^^^^^^^^