From c1cded3580419c6ce0fd277559e0c4ba4e5591ba Mon Sep 17 00:00:00 2001 From: Isaiah Akorita Date: Thu, 6 Feb 2025 14:57:15 +0100 Subject: [PATCH 1/5] added bokeh datetime formatting for x-axis tooltip --- hvplot/converter.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/hvplot/converter.py b/hvplot/converter.py index 155efad2e..521dfd26c 100644 --- a/hvplot/converter.py +++ b/hvplot/converter.py @@ -2631,14 +2631,15 @@ def ohlc(self, x=None, y=None, data=None): tools = seg_cur_opts.pop('tools', []) if 'hover' in tools: tools[tools.index('hover')] = HoverTool( + formatters={f'@{x}': 'datetime'}, tooltips=[ - (x, f'@{x}'), + (x, f'@{x}{{%F}}'), ('Open', f'@{o}'), ('High', f'@{h}'), ('Low', f'@{l}'), ('Close', f'@{c}'), ] - + [(hc, f'@{hc}') for hc in vdims[4:]] + + [(hc, f'@{hc}') for hc in vdims[4:]], ) seg_cur_opts['tools'] = tools seg_cur_opts['color'] = self.kwds.get('line_color', 'black') From 48d3ff42324b2c31ee6761bf524b1f98b2197887 Mon Sep 17 00:00:00 2001 From: Isaiah Akorita Date: Thu, 6 Feb 2025 14:58:13 +0100 Subject: [PATCH 2/5] added tests --- hvplot/tests/plotting/testohlc.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/hvplot/tests/plotting/testohlc.py b/hvplot/tests/plotting/testohlc.py index 5cdb9a570..7e83f8407 100644 --- a/hvplot/tests/plotting/testohlc.py +++ b/hvplot/tests/plotting/testohlc.py @@ -32,3 +32,15 @@ def test_ohlc_hover_cols_all(): tooltips = segments.opts.get('plot').kwargs['tools'][0].tooltips assert len(tooltips) == len(df.columns) + 1 assert tooltips[-1] == ('Volume', '@Volume') + + +def test_ohlc_date_tooltip_format(): + plot = df.hvplot.ohlc(y=ohlc_cols) + segments = plot.Segments.I + hover_tool = segments.opts.get('plot').kwargs['tools'][0] + tooltips = hover_tool.tooltips + x_label, x_tooltip = tooltips[0] + assert '{%F}' in x_tooltip + formatter_key = '@' + x_label + formatter = hover_tool.formatters + assert formatter.get(formatter_key) == 'datetime' From fc10a837c28b44c4d5830dba0f09839567971ade Mon Sep 17 00:00:00 2001 From: Isaiah Akorita Date: Thu, 6 Feb 2025 16:27:38 +0100 Subject: [PATCH 3/5] added check for datetime x-axis --- hvplot/converter.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/hvplot/converter.py b/hvplot/converter.py index 521dfd26c..319a8804d 100644 --- a/hvplot/converter.py +++ b/hvplot/converter.py @@ -2630,10 +2630,17 @@ def ohlc(self, x=None, y=None, data=None): seg_cur_opts, seg_compat_opts = self._get_compat_opts('Segments') tools = seg_cur_opts.pop('tools', []) if 'hover' in tools: + x_data = data[x] if x in data.columns else data.index + if np.issubdtype(x_data.dtype, np.datetime64): + x_tooltip = f'@{x}{{%F}}' + formatter = {f'@{x}': 'datetime'} + else: + x_tooltip = f'@{x}' + formatter = {} tools[tools.index('hover')] = HoverTool( - formatters={f'@{x}': 'datetime'}, + formatters=formatter, tooltips=[ - (x, f'@{x}{{%F}}'), + (x, x_tooltip), ('Open', f'@{o}'), ('High', f'@{h}'), ('Low', f'@{l}'), From 46e53d0e0c521aa3e3a1ef1610db47967c9b46b2 Mon Sep 17 00:00:00 2001 From: Isaiah Akorita Date: Thu, 6 Feb 2025 16:28:47 +0100 Subject: [PATCH 4/5] added tests for non-datetime x-axis --- hvplot/tests/plotting/testohlc.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/hvplot/tests/plotting/testohlc.py b/hvplot/tests/plotting/testohlc.py index 7e83f8407..011a74454 100644 --- a/hvplot/tests/plotting/testohlc.py +++ b/hvplot/tests/plotting/testohlc.py @@ -44,3 +44,27 @@ def test_ohlc_date_tooltip_format(): formatter_key = '@' + x_label formatter = hover_tool.formatters assert formatter.get(formatter_key) == 'datetime' + + +def test_ohlc_non_datetime_x_axis(): + df = pd.DataFrame( + { + 'Open': [100.00, 101.25, 102.75], + 'High': [104.10, 105.50, 110.00], + 'Low': [94.00, 97.10, 99.20], + 'Close': [101.15, 99.70, 109.50], + 'Volume': [10012, 5000, 18000], + }, + index=[1, 2, 3], + ) + + ohlc_cols = ['Open', 'High', 'Low', 'Close'] + + plot = df.hvplot.ohlc(y=ohlc_cols) + segments = plot.Segments.I + hover_tool = segments.opts.get('plot').kwargs['tools'][0] + tooltips = hover_tool.tooltips + x_label, x_tooltip = tooltips[0] + assert '{%F}' not in x_tooltip + formatter_key = '@' + x_label + assert formatter_key not in hover_tool.formatters From 6102f5fa0c5d67f34c7b4a2b076bb9fe16c5074a Mon Sep 17 00:00:00 2001 From: Isaiah Akorita Date: Thu, 6 Feb 2025 16:56:28 +0100 Subject: [PATCH 5/5] modify type checking to use pandas --- hvplot/converter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hvplot/converter.py b/hvplot/converter.py index 319a8804d..3ed9f49b8 100644 --- a/hvplot/converter.py +++ b/hvplot/converter.py @@ -2631,7 +2631,7 @@ def ohlc(self, x=None, y=None, data=None): tools = seg_cur_opts.pop('tools', []) if 'hover' in tools: x_data = data[x] if x in data.columns else data.index - if np.issubdtype(x_data.dtype, np.datetime64): + if pd.api.types.is_datetime64_any_dtype(x_data): x_tooltip = f'@{x}{{%F}}' formatter = {f'@{x}': 'datetime'} else: