Skip to content

Commit fbdeaa8

Browse files
committed
BUG: plotting with non-nano TimedeltaIndex
1 parent aa5726a commit fbdeaa8

File tree

4 files changed

+15
-9
lines changed

4 files changed

+15
-9
lines changed

pandas/plotting/_matplotlib/converter.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
from matplotlib.axis import Axis
6262

6363
from pandas._libs.tslibs.offsets import BaseOffset
64+
from pandas._typing import TimeUnit
6465

6566

6667
_mpl_units: dict = {} # Cache for units overwritten by us
@@ -1099,18 +1100,22 @@ class TimeSeries_TimedeltaFormatter(mpl.ticker.Formatter): # pyright: ignore[re
10991100
Formats the ticks along an axis controlled by a :class:`TimedeltaIndex`.
11001101
"""
11011102

1103+
def __init__(self, unit: TimeUnit = "ns"):
1104+
self.unit = unit
1105+
super().__init__()
1106+
11021107
axis: Axis
11031108

11041109
@staticmethod
1105-
def format_timedelta_ticks(x, pos, n_decimals: int) -> str:
1110+
def format_timedelta_ticks(x, pos, n_decimals: int, exp: int) -> str:
11061111
"""
11071112
Convert seconds to 'D days HH:MM:SS.F'
11081113
"""
1109-
s, ns = divmod(x, 10**9) # TODO(non-nano): this looks like it assumes ns
1114+
s, ns = divmod(x, 10**exp)
11101115
m, s = divmod(s, 60)
11111116
h, m = divmod(m, 60)
11121117
d, h = divmod(h, 24)
1113-
decimals = int(ns * 10 ** (n_decimals - 9))
1118+
decimals = int(ns * 10 ** (n_decimals - exp))
11141119
s = f"{int(h):02d}:{int(m):02d}:{int(s):02d}"
11151120
if n_decimals > 0:
11161121
s += f".{decimals:0{n_decimals}d}"
@@ -1119,6 +1124,7 @@ def format_timedelta_ticks(x, pos, n_decimals: int) -> str:
11191124
return s
11201125

11211126
def __call__(self, x, pos: int | None = 0) -> str:
1127+
exp = {"ns": 9, "us": 6, "ms": 3, "s": 0}[self.unit]
11221128
(vmin, vmax) = tuple(self.axis.get_view_interval())
1123-
n_decimals = min(int(np.ceil(np.log10(100 * 10**9 / abs(vmax - vmin)))), 9)
1124-
return self.format_timedelta_ticks(x, pos, n_decimals)
1129+
n_decimals = min(int(np.ceil(np.log10(100 * 10**exp / abs(vmax - vmin)))), exp)
1130+
return self.format_timedelta_ticks(x, pos, n_decimals, exp)

pandas/plotting/_matplotlib/timeseries.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,7 @@ def format_dateaxis(
341341
subplot.format_coord = functools.partial(_format_coord, freq)
342342

343343
elif isinstance(index, ABCTimedeltaIndex):
344-
subplot.xaxis.set_major_formatter(TimeSeries_TimedeltaFormatter())
344+
subplot.xaxis.set_major_formatter(TimeSeries_TimedeltaFormatter(index.unit))
345345
else:
346346
raise TypeError("index type not supported")
347347

pandas/tests/plotting/test_converter.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,7 @@ class TestTimeDeltaConverter:
347347
)
348348
def test_format_timedelta_ticks(self, x, decimal, format_expected):
349349
tdc = converter.TimeSeries_TimedeltaFormatter
350-
result = tdc.format_timedelta_ticks(x, pos=None, n_decimals=decimal)
350+
result = tdc.format_timedelta_ticks(x, pos=None, n_decimals=decimal, exp=9)
351351
assert result == format_expected
352352

353353
@pytest.mark.parametrize("view_interval", [(1, 2), (2, 1)])

pandas/tests/plotting/test_datetimelike.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1531,7 +1531,7 @@ def test_format_timedelta_ticks_narrow(self):
15311531
assert len(result_labels) == len(expected_labels)
15321532
assert result_labels == expected_labels
15331533

1534-
def test_format_timedelta_ticks_wide(self):
1534+
def test_format_timedelta_ticks_wide(self, unit):
15351535
expected_labels = [
15361536
"00:00:00",
15371537
"1 days 03:46:40",
@@ -1544,7 +1544,7 @@ def test_format_timedelta_ticks_wide(self):
15441544
"9 days 06:13:20",
15451545
]
15461546

1547-
rng = timedelta_range("0", periods=10, freq="1 D")
1547+
rng = timedelta_range("0", periods=10, freq="1 D", unit=unit)
15481548
df = DataFrame(np.random.default_rng(2).standard_normal((len(rng), 3)), rng)
15491549
_, ax = mpl.pyplot.subplots()
15501550
ax = df.plot(fontsize=2, ax=ax)

0 commit comments

Comments
 (0)