I managed to set a fixed label for each bubble in my chart. Here’s the code:
import plotly.graph_objects as go
import plotly.express as px
import pandas as pd
margin_factor = 1.6
data = {'x': [1.5, 1.6, -1.2],
'y': [21, -16, 46],
'circle-size': [10, 5, 6],
'circle-color': ["red","red","green"],
'tttt': ["the last xt for MO","the last xt for MO pom","the last xt for MO %"]
}
# Create DataFrame
df = pd.DataFrame(data)
fig = px.scatter(
df,
x="x",
y="y",
color="circle-color",
size='circle-size'
)
fig.update_layout(
{
'xaxis': {
"range": [-100, 100],
'zerolinewidth': 3,
"zerolinecolor": "blue",
"tick0": -100,
"dtick": 25,
'scaleanchor': 'y'
},
'yaxis': {
"range": [-100, 100],
'zerolinewidth': 3,
"zerolinecolor": "green",
"tick0": -100,
"dtick": 25
},
"width": 500,
"height": 500
}
)
x_pad = (max(df.x) - min(df.x)) / 8
y_pad = (max(df.y) - min(df.y)) / 30
for x0, y0 in zip(data['x'], data['y']):
fig.add_shape(type="rect",
x0=x0 + (x_pad)/5,
y0=y0 - y_pad,
x1=x0 + x_pad,
y1=y0 + y_pad,
xref='x', yref='y',
line=dict(
color="black",
width=2,
),
fillcolor="#1CBE4F",
layer="below"
)
fig.add_trace(
go.Scatter(
x=df["x"].values + (x_pad)/2,
y=df["y"],
text=df["tttt"],
mode="text",
showlegend=False
)
)
fig.show()
Now what I’m trying to do is to put some css to these labels some this like this :
I know there is something called annotation, I tried it, but I did not successfully create annotations for each element.
You can add the rectangles using plotly shapes. I have adjusted the size and coordinates of the rectangle to scale to the range = max - min
of your x and y values in your data since this is how plotly determines the scale of the figures (rather than hardcoding the size of the rectangles which won't work if your data changes). The length of the box in the x-direction is then scaled to the length of the text to be placed inside the box.
import plotly.graph_objects as go
import plotly.express as px
import pandas as pd
data = {'x': [1.5, 1.6, -1.2],
'y': [21, -16, 46],
'circle-size': [10, 5, 6],
'circle-color': ["red","red","green"],
'tttt': ["ggg","vvvv","really really long string"],
}
# Create DataFrame
df = pd.DataFrame(data)
df['length'] = df['tttt'].str.len()
fig = px.scatter(
df,
x="x",
y="y",
color="circle-color",
size='circle-size',
# text="tttt",
# hover_name="tttt",
color_discrete_map={"red": "red", "green": "green"}
)
fig.update_traces(textposition='middle right', textfont_size=14, textfont_color='black', textfont_family="Inter", hoverinfo="skip")
xrange_min = -100
xrange_max = 100
yrange_min = -100
yrange_max = 100
fig.update_layout(
{
'xaxis': {
"range": [xrange_min, xrange_max],
'zerolinewidth': 3,
"zerolinecolor": "blue",
"tick0": -100,
"dtick": 25,
'scaleanchor': 'y'
},
'yaxis': {
"range": [yrange_min, yrange_max],
'zerolinewidth': 3,
"zerolinecolor": "green",
"tick0": -100,
"dtick": 25
},
"width": 500,
"height": 500
}
)
x_pad = (xrange_max - xrange_min) / 25
y_pad = (yrange_max - yrange_min) / 30
for (x0, y0, text, length) in zip(df['x'], df['y'], df['tttt'], df['length']):
fig.add_shape(type="rect",
x0=x0 + 1.2*x_pad,
y0=y0 - y_pad,
x1=x0 + (length)*x_pad,
y1=y0 + y_pad,
xref='x', yref='y',
line=dict(
color="black",
width=2,
),
fillcolor="#1CBE4F",
layer="below"
)
fig.add_trace(
go.Scatter(
x=[x0 + 1.2*x_pad + (length*x_pad/4)],
y=[y0 + (y_pad / 2)],
text=[text],
mode="text",
showlegend=False
)
)
fig.show()