Markers+text mode : is it possible to have different text and hover text?


#1

Hello,

I’m building a network with plotly, using the ‘markers+text’ mode and I’d like to do the following :

  • Draw each marker with a short text (for instance a species name)
  • make supplemental informations appear in the hover section, for instance : the species genus, the number of connections in the network.

i’m currently struggling to separate these two. My trace is built like this :

node_trace = go.Scatter(
        x=[],
        y=[],
        text=[],
        mode='markers+text',
        hoverinfo='text',
        textposition='bottom center',
        marker=dict(
            showscale=False,               
            colorscale='Rainbow',
            reversescale=True,
            color=[],
            size=10,                
            line=dict(width=2))            
    ) 

I got then several loops to fill the node_trace['x'], node_trace['y'], and node_trace['text'] parameters. As you can see, my issue is on the hoverinfo='text' line : how can I separate the hover info from the text ?

Thanks a lot.


#2

i’ve figured it out : I have to use annotations with ‘markers’ mode :slight_smile:


#3

Could you give an example of how you did this? Also, do you know if it is also possible with Scattermapbox?

Thanks,
Troy


#4

Hello,

To make it simpler t explain, I’ve isolated the code dedicated to this in my function ; thus, the following code will not work because everything else is missing, but you’ll have an overview of how to do that. I added a few comments to make it clear (I hope)

"""
Important : previously set variables :
- network (netWorkX v 2.1 graph) : the network !
- positions (dict) : a dictionary built by a layout function of networkX :
                     positions = nx.spring_layout(network)
"""

# this is the object for nodes coordinates and properties
node_trace = go.Scatter(
    x=[],
    y=[],
    text=[],
    mode='markers', # only markers mode needed
    hoverinfo='text',
    textposition='bottom center',
    marker=dict(            
        colorscale='Rainbow',
        reversescale=True,
        color=[],
        size=10,            
        line=dict(width=2)
        ),
    textfont=dict(family='sans serif',
                  size=10,
                  color='#888'
                 )
)

# Some code to fill x and y nodes coordinates x and y ...
# ...

# Some code to the display of edges between nodes (another scatter object)  
# ...

# NOW : creating the annotations, that will display the node name on the figure
annotations = []

# hover text and color group
for node, adjacencies in enumerate(network.adjacency()):
    # adjacencies[1] : tuple
    # adjacencies[1][0] : origin node
    # adjacencies[1][1] : targets nodes     

    # setting the text that will be display on hover
    # (I have originally more informations involved but I made it shorter here)
    node_info = '{} - {} connections'.format(
        adjacencies[0],
        str(len(adjacencies[1]))
        )

    node_trace['text'] += tuple([node_info])

    # THERE : Annotations is a list of dictionaries with every needed parameter for each node annotation
    annotations.append(
        dict(x=positions[adjacencies[0]][0],
             y=positions[adjacencies[0]][1],
             text=adjacencies[0], # node name that will be displayed
             xanchor='left',
             xshift=10,
             font=dict(color='black', size=10),
             showarrow=False, arrowhead=1, ax=-10, ay=-10)
        )

# originally, I concatenated my nodes Scatter and my edges Scatter in a single list
# here it's just displaying the nodes
fig = go.Figure(data=node_trace,
                layout=go.Layout(
                    title='<br>Your Beautiful Network',
                    titlefont=dict(size=16),
                    showlegend=False,
                    hovermode='closest',
                    margin=dict(b=20, l=5, r=5, t=40),
                    # THERE !
                    annotations=annotations, 
                    xaxis=dict(showgrid=False, zeroline=False,
                               showticklabels=False),
                    yaxis=dict(showgrid=False, zeroline=False,
                               showticklabels=False)
                )
                )

Hope it helps.


#5

Thanks for the elaboration, good information. I didn’t realize that would be under the layout.

Unfortunately I don’t think this works with scattermapbox though since we have to use lat and long instead of x and y. Or at least I couldn’t get it to work yet with annotations.

Thanks!
Troy


#6

Hi, thanks for the nice description. While trying that out I got an error in the annotations.append( line, saying that annotations are not defined.
NameError: name ‘annotations’ is not defined
How did you define it before the append?
Thanks,
Jochen


#7

Hello,

Maybe you forgot the

annotations = []

statement ? (after the go.Scatter object declaration and some comments).


#8

Hi Micawber, yes, that was it. Sometimes the obvious is missing. Thanks a lot for the code sample. It works very nicely for me.
+1