@@ -1492,6 +1492,35 @@ def format_with_na_rep(values: ArrayLike, formatter: Callable, na_rep: str):
1492
1492
).reshape (values .shape )
1493
1493
return formatted
1494
1494
1495
+ def format_complex_with_na_rep (
1496
+ values : ArrayLike , formatter : Callable , na_rep : str
1497
+ ):
1498
+ real_values = np .real (values ).ravel () # type: ignore[arg-type]
1499
+ imag_values = np .imag (values ).ravel () # type: ignore[arg-type]
1500
+ real_mask , imag_mask = isna (real_values ), isna (imag_values )
1501
+ formatted_lst = []
1502
+ for val , real_val , imag_val , re_isna , im_isna in zip (
1503
+ values .ravel (),
1504
+ real_values ,
1505
+ imag_values ,
1506
+ real_mask ,
1507
+ imag_mask ,
1508
+ ):
1509
+ if not re_isna and not im_isna :
1510
+ formatted_lst .append (formatter (val ))
1511
+ elif not re_isna : # xxx+nanj
1512
+ formatted_lst .append (f"{ formatter (real_val )} +{ na_rep } j" )
1513
+ elif not im_isna : # nan[+/-]xxxj
1514
+ # The imaginary part may either start with a "-" or a space
1515
+ imag_formatted = formatter (imag_val ).strip ()
1516
+ if imag_formatted .startswith ("-" ):
1517
+ formatted_lst .append (f"{ na_rep } { imag_formatted } j" )
1518
+ else :
1519
+ formatted_lst .append (f"{ na_rep } +{ imag_formatted } j" )
1520
+ else : # nan+nanj
1521
+ formatted_lst .append (f"{ na_rep } +{ na_rep } j" )
1522
+ return np .array (formatted_lst ).reshape (values .shape )
1523
+
1495
1524
if self .formatter is not None :
1496
1525
return format_with_na_rep (self .values , self .formatter , self .na_rep )
1497
1526
@@ -1512,11 +1541,12 @@ def format_values_with(float_format):
1512
1541
# need to distinguish complex and float NaNs (GH #53762)
1513
1542
values = self .values
1514
1543
is_complex = is_complex_dtype (values )
1515
- if is_complex :
1516
- na_rep = f"{ na_rep } +{ 0 :.{self .digits }f} j"
1517
1544
1518
1545
# separate the wheat from the chaff
1519
- values = format_with_na_rep (values , formatter , na_rep )
1546
+ if is_complex :
1547
+ values = format_complex_with_na_rep (values , formatter , na_rep )
1548
+ else :
1549
+ values = format_with_na_rep (values , formatter , na_rep )
1520
1550
1521
1551
if self .fixed_width :
1522
1552
if is_complex :
@@ -1917,7 +1947,7 @@ def _trim_zeros_complex(str_complexes: np.ndarray, decimal: str = ".") -> list[s
1917
1947
real_part , imag_part = [], []
1918
1948
for x in str_complexes :
1919
1949
# Complex numbers are represented as "(-)xxx(+/-)xxxj"
1920
- # The split will give [maybe "-", "xxx", "+/-", "xxx", "j", ""]
1950
+ # The split will give [{"", "-"} , "xxx", "+/-", "xxx", "j", ""]
1921
1951
# Therefore, the imaginary part is the 4th and 3rd last elements,
1922
1952
# and the real part is everything before the imaginary part
1923
1953
trimmed = re .split (r"([j+-])" , x )
@@ -1929,11 +1959,13 @@ def _trim_zeros_complex(str_complexes: np.ndarray, decimal: str = ".") -> list[s
1929
1959
# in the array
1930
1960
n = len (str_complexes )
1931
1961
padded_parts = _trim_zeros_float (real_part + imag_part , decimal )
1962
+ padded_length = max (len (part ) for part in padded_parts ) - 1
1932
1963
padded = [
1933
- padded_parts [i ] # real part (including - or space, possibly "NaN")
1934
- + padded_parts [i + n ] # imaginary part (including + or -)
1964
+ real_pt # real part, possibly NaN
1965
+ + imag_pt [0 ] # +/-
1966
+ + f"{ imag_pt [1 :]:>{padded_length }} " # complex part (no sign), possibly nan
1935
1967
+ "j"
1936
- for i in range ( n )
1968
+ for real_pt , imag_pt in zip ( padded_parts [: n ], padded_parts [ n :] )
1937
1969
]
1938
1970
return padded
1939
1971
0 commit comments