How to avoid overlapping text in a plotly scatter plot?
Question:
I am looking for a solution to avoid overlapping text in the text-labels. I create the image with plotly scatter. Maybe there is an automation here.
from pandas import util
import plotly.express as px
import plotly.graph_objects as go
df = util.testing.makeDataFrame()
df_keyfigures_all = df[['A','B']]
fig = px.scatter(df_keyfigures_all, x="A", y="B",size_max=60,
text=df_keyfigures_all.index)
fig.update_traces(textposition='top center')
fig.layout = go.Layout(yaxis=dict(tickformat=".0%"), xaxis=dict(tickformat=".0%"),
yaxis_title="A", xaxis_title="B")
fig.update_layout(showlegend=False)
plotly.io.write_image(fig, file='keyfigures.png', format='png')
Answers:
Unfortunately, there does not seem to be a direct way to do this. A little digging on the plotly community forum will show you that it has already been requested and that the developers are aware of the issue.
It is not the perfect solution, but one way is to hide the text in the hover text.
fig = px.scatter(df_keyfigures_all, x="A", y="B",size_max=60,
hover_name = df_keyfigures_all.index)
One solution is to alternate the text position like in this live demo:
import pandas as pd
from plotly import express as px, graph_objects as go
df = pd.DataFrame()
df['x'] = [0, 1, 1, 2, 3, 6, 7, 7, 8, 8, 9, 9, 10, 11, 11, 12]
df['y'] = [57, 55, 75, 23, 80, 66, 66, 23, 79, 79, 20, 71, 59, 74, 82, 77]
df['explainer_name'] = ['tree_shap_approximation', 'saabas', 'tree_shap', 'baseline_random', 'archipelago',
'shapley_taylor_interaction', 'partition', 'anova', 'permutation_partition', 'permutation',
'shap_interaction', 'sage', 'maple', 'lime', 'kernel_shap', 'exact_shapley_values']
fig = px.scatter(df,
x='x',
y='y',
# size='dot_size',
text='explainer_name',
# log_x=True,
labels={
"x": "Time",
"y": "Score",
# 'dot_size': 'Portability',
'explainer_name': 'Explainer '
},
title='No overlapping annotations', # take some vertical space
)
def improve_text_position(x):
""" it is more efficient if the x values are sorted """
# fix indentation
positions = ['top center', 'bottom center'] # you can add more: left center ...
return [positions[i % len(positions)] for i in range(len(x))]
fig.update_traces(textposition=improve_text_position(df['x']))
fig.show()
I am looking for a solution to avoid overlapping text in the text-labels. I create the image with plotly scatter. Maybe there is an automation here.
from pandas import util
import plotly.express as px
import plotly.graph_objects as go
df = util.testing.makeDataFrame()
df_keyfigures_all = df[['A','B']]
fig = px.scatter(df_keyfigures_all, x="A", y="B",size_max=60,
text=df_keyfigures_all.index)
fig.update_traces(textposition='top center')
fig.layout = go.Layout(yaxis=dict(tickformat=".0%"), xaxis=dict(tickformat=".0%"),
yaxis_title="A", xaxis_title="B")
fig.update_layout(showlegend=False)
plotly.io.write_image(fig, file='keyfigures.png', format='png')
Unfortunately, there does not seem to be a direct way to do this. A little digging on the plotly community forum will show you that it has already been requested and that the developers are aware of the issue.
It is not the perfect solution, but one way is to hide the text in the hover text.
fig = px.scatter(df_keyfigures_all, x="A", y="B",size_max=60,
hover_name = df_keyfigures_all.index)
One solution is to alternate the text position like in this live demo:
import pandas as pd
from plotly import express as px, graph_objects as go
df = pd.DataFrame()
df['x'] = [0, 1, 1, 2, 3, 6, 7, 7, 8, 8, 9, 9, 10, 11, 11, 12]
df['y'] = [57, 55, 75, 23, 80, 66, 66, 23, 79, 79, 20, 71, 59, 74, 82, 77]
df['explainer_name'] = ['tree_shap_approximation', 'saabas', 'tree_shap', 'baseline_random', 'archipelago',
'shapley_taylor_interaction', 'partition', 'anova', 'permutation_partition', 'permutation',
'shap_interaction', 'sage', 'maple', 'lime', 'kernel_shap', 'exact_shapley_values']
fig = px.scatter(df,
x='x',
y='y',
# size='dot_size',
text='explainer_name',
# log_x=True,
labels={
"x": "Time",
"y": "Score",
# 'dot_size': 'Portability',
'explainer_name': 'Explainer '
},
title='No overlapping annotations', # take some vertical space
)
def improve_text_position(x):
""" it is more efficient if the x values are sorted """
# fix indentation
positions = ['top center', 'bottom center'] # you can add more: left center ...
return [positions[i % len(positions)] for i in range(len(x))]
fig.update_traces(textposition=improve_text_position(df['x']))
fig.show()