So I have a dataframe with 3 columns: date, price, text
import pandas as pd
from datetime import datetime
import random
columns = ('dates','prices','text')
datelist = pd.date_range(datetime.today(), periods=5).tolist()
prices = []
for i in range(0, 5):
prices.append(random.randint(50, 60))
text =['AAA','BBB','CCC','DDD','EEE']
df = pd.DataFrame({'dates': datelist, 'price':prices, 'text':text})
dates price text
0 2022-11-23 14:11:51.142574 51 AAA
1 2022-11-24 14:11:51.142574 57 BBB
2 2022-11-25 14:11:51.142574 52 CCC
3 2022-11-26 14:11:51.142574 51 DDD
4 2022-11-27 14:11:51.142574 59 EEE
I want to plot date and price on a line chart, but when I hover over the line I want it to show the text from the row corresponding to that date.
eg when I hover over the point corresponding to 2022-11-27 I want the text to show 'EEE'
ive tried a few things in matplotlib etc but can only get data from the x and y axis to show but I cant figure out how to show data from a different column.
Any help would be greatly appreciated.
Thanks
CodePudding user response:
You could use Plotly.
import plotly.graph_objects as go
fig = go.Figure(data=go.Scatter(x=df['dates'], y=df['price'], mode='lines markers', text=df['text']))
fig.show()
CodePudding user response:
You should be aware that cursor & dataframe indexing will probably work well with points on a scatter plot, but it is a little bit trickier to handle a lineplot.
With a lineplot, matplotlib draws the line between 2 data points (basically, it's linear interpolation), so a specific logic must be taken care of to:
- specify the intended behavior
- implement the corresponding mouseover behavior when the cursor lands "between" 2 data points.
The lib/links below may provide tools to handle scatter plots and lineplots, but I am not expert enough to point you to this specific part in either the SO link nor the mplcursors link.
(besides, the exact intended behavioor was not clearly stated in your initial question; consider editing/clarifying)
So, alternatively to DankyKang's answer, have a look at this SO question and answers that cover a large panel of possibilities for mouseover: How to add hovering annotations to a plot
A library worth noting is this one: https://mplcursors.readthedocs.io/en/stable/
Quoting:
mplcursors provides interactive data selection cursors for Matplotlib. It is inspired from mpldatacursor, with a much simplified API. mplcursors requires Python 3, and Matplotlib≥3.1.
Specifically this example based on dataframes: https://mplcursors.readthedocs.io/en/stable/examples/dataframe.html
Quoting:
DataFrames can be used similarly to any other kind of input. Here, we generate a scatter plot using two columns and label the points using all columns. This example also applies a shadow effect to the hover panel.
copy-pasta of code example, should this answer be considered not complete enough :
from matplotlib import pyplot as plt
from matplotlib.patheffects import withSimplePatchShadow
import mplcursors
from pandas import DataFrame
df = DataFrame(
dict(
Suburb=["Ames", "Somerset", "Sawyer"],
Area=[1023, 2093, 723],
SalePrice=[507500, 647000, 546999],
)
)
df.plot.scatter(x="Area", y="SalePrice", s=100)
def show_hover_panel(get_text_func=None):
cursor = mplcursors.cursor(
hover=2, # Transient
annotation_kwargs=dict(
bbox=dict(
boxstyle="square,pad=0.5",
facecolor="white",
edgecolor="#ddd",
linewidth=0.5,
path_effects=[withSimplePatchShadow(offset=(1.5, -1.5))],
),
linespacing=1.5,
arrowprops=None,
),
highlight=True,
highlight_kwargs=dict(linewidth=2),
)
if get_text_func:
cursor.connect(
event="add",
func=lambda sel: sel.annotation.set_text(get_text_func(sel.index)),
)
return cursor
def on_add(index):
item = df.iloc[index]
parts = [
f"Suburb: {item.Suburb}",
f"Area: {item.Area:,.0f}m²",
f"Sale price: ${item.SalePrice:,.0f}",
]
return "\n".join(parts)
show_hover_panel(on_add)
plt.show()