Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Auto place annotation bubble

I have the following snippit of code:

data.plot(y='Close', ax = ax)
newdates = exceptthursday.loc[start:end]
for anotate in (newdates.index + BDay()).strftime('%Y-%m-%d'):
    ax.annotate('holliday', xy=(anotate, data['Close'].loc[anotate]),  xycoords='data',
                xytext=(-30, 40), textcoords='offset points',
                size=13, ha='center', va="baseline",
                bbox=dict(boxstyle="round", alpha=0.1),
                arrowprops=dict(arrowstyle="wedge,tail_width=0.5", alpha=0.1)); 

This produces a plot which looks like this: enter image description here

As you can see i have explicitly mentioned the xytext, this makes the "bubbles" messy as at some locations they overlap which makes it hard to read. Is there any way it can be "auto - placed" so that they are not overlapping. Such as some of the "bubbles" are above and below the plot line in such a way that they do not overlap.

like image 255
Slartibartfast Avatar asked Jul 04 '20 21:07

Slartibartfast


People also ask

How do I create a bubble in AutoCAD?

In the Create Grid Bubble dialog box, you can either choose to confirm the tool settings for label prefix, extension line length, and one- or two-sided labelling, or you can overwrite them. Click OK when the settings are according to your wishes.

How do I enable auto-binding in bubble?

To use auto-binding, we need to grant permissions to our users to auto-update their data. When you enable auto-binding, Bubble will alert you that you need to define the Privacy rules to allow your users to auto-update this field. Choose the relevant data type and click on define a new role.

How do I place an annotation at a specific page location?

To place an annotation at a specific page location relative to the user’s view, we need to use the coordinate system that represents the user’s view, i.e. Rotated User Space. Since the doc.getPageBox () function returns the coordinates in Rotated User Space, this is a fairly easy task.

Does annoreset remove the position of the annotative attributes?

Annoreset removes the position of the attributes , but it has no effect of the position of the block. maybe somebody could help. Solved by chriscowgill7373 . Go to Solution. 09-21-2018 01:59 AM "I have some blocks with annotative attributes.


2 Answers

Auto-Placing according to me is such that you zoom in zoom out and automatically data and UI is adjusted because you can't avoid overlapping even though you place the bubbles above and below the plot line due to lots of data points which can't be ignored. I have used plotly library as matplotlib has limitations. I have chosen UK holidays. You can change it accordingly.

import plotly.graph_objects as go
import plotly.express as px
from pandas_datareader import data as web
import holidays

data = web.DataReader('fb', 'yahoo')
uk_holidays = holidays.UnitedKingdom()
data["is_holiday"] = [True if i in uk_holidays else False for i in data.index]
data["Date"] = data.index
data.reset_index(drop=True, inplace=True)

fig = px.line(data, x='Date', y='Close')

fig.update_xaxes(
    rangeslider_visible=True,
    rangeselector=dict(
        buttons=list([
            dict(count=1, label="1m", step="month", stepmode="backward"),
            dict(count=6, label="6m", step="month", stepmode="backward"),
            dict(count=1, label="YTD", step="year", stepmode="todate"),
            dict(count=1, label="1y", step="year", stepmode="backward"),
            dict(step="all")
        ])
    )
)


for close, date in data[data["is_holiday"] == True][["Close","Date"]].itertuples(index=False):
    fig.add_annotation(
        x=date.date(),
        y=close,
        xref="x",
        yref="y",
        text="Holiday",
        showarrow=True,
        font=dict(
            family="Courier New, monospace",
            size=16,
            color="#ffffff"
            ),
        align="center",
        arrowhead=2,
        arrowsize=1,
        arrowwidth=2,
        arrowcolor="#636363",
        ax=20,
        ay=-30,
        bordercolor="#c7c7c7",
        borderwidth=2,
        borderpad=4,
        bgcolor="#ff7f0e",
        opacity=0.8
        )
fig.update_layout(title_text='Trend Analysis with Holiday', title_x=0.5,showlegend=False)
fig.show()

Working of the above code:

enter image description here

like image 89
bigbounty Avatar answered Oct 17 '22 00:10

bigbounty


Because of the small amount of holiday data used, the degree of overlap in the annotations will seem less effective because of the small amount of overlap in the annotations, but the gist of the answer is that the issue could be improved slightly by varying the position of the annotations according to the index.

import matplotlib.pyplot as plt
import matplotlib.dates as mdates
from pandas_datareader import data as web
from pandas.tseries.holiday import USFederalHolidayCalendar as calendar

data = web.DataReader('fb', 'yahoo')
cal = calendar()
holidays = cal.holidays(start=data.index.min(), end=data.index.max())
data['Holiday'] = data.index.isin(holidays)
holiday = data[data['Holiday'] == True]

fig = plt.figure(figsize=(16,6))
ax = fig.add_subplot(111)

ax.plot(data.index, data.Close)

for i,x,y in zip(range(len(holiday)),holiday.index, holiday.Close):
    if i % 2 == 0: 
        ax.annotate('holliday', xy=(x,y),  xycoords='data',
                    xytext=(-30, 40), textcoords='offset points',
                    size=13, ha='center', va="baseline",
                    bbox=dict(boxstyle="round", alpha=0.1),
                    arrowprops=dict(arrowstyle="wedge,tail_width=0.5", alpha=0.1))
    else:
        ax.annotate('holliday', xy=(x,y),  xycoords='data',
                xytext=(30, -40), textcoords='offset points',
                size=13, ha='center', va="baseline",
                bbox=dict(boxstyle="round", alpha=0.1),
                arrowprops=dict(arrowstyle="wedge,tail_width=0.5", alpha=0.1))


ax.xaxis.set_major_locator(mdates.MonthLocator(bymonth=None, interval=3, tz=None))
ax.xaxis.set_major_formatter(mdates.DateFormatter("%Y-%m-%d"))
ax.tick_params(axis='x', labelrotation=45)

enter image description here

like image 31
r-beginners Avatar answered Oct 17 '22 01:10

r-beginners