Search code examples
pythonmatplotlibseaborndata-sciencevisualization

Python / Seaborn - How to plot the names of each value in a scatterplot


first of all, in case I comment on any mistakes while writing this, sorry, English is not my first language.

I'm a begginer with Data vizualiation with python, I have a dataframe with 115 rows, and I want to do a scatterplot with 4 quadrants and show the values in R1 (image below for reference)

enter image description here

At moment this is my scatterplot. It's a football player dataset so I want to plot the name of the players name in the 'R1'. Is that possible?

enter image description here


Solution

  • You can annotate each point by making a sub-dataframe of just the players in a quadrant that you care about based on their x/y values using plt.annotate. So something like this:

    
    import pandas as pd
    import matplotlib.pyplot as plt
    import seaborn as sns
    
    ##### Making a mock dataset #################################################
    names = ['one', 'two', 'three', 'four', 'five', 'six']
    value_1 = [1, 2, 3, 4, 5, 6]
    value_2 = [1, 2, 3, 4, 5, 6]
    
    df = pd.DataFrame(zip(names, value_1, value_2), columns = ['name', 'v_1', 'v_2'])
    #############################################################################
    
    plt.rcParams['figure.figsize'] = (10, 5) # sizing parameter to make the graph bigger
    ax1 = sns.scatterplot(x = value_1, y = value_2, s = 100) # graph code
    
    # Code to make a subset of data that fits the specific conditions that I want to annotate
    quadrant = df[(df.v_1 > 3) & (df.v_2 > 3)].reset_index(drop = True)
    
    # Code to annotate the above "quadrant" on the graph
    for x in range(len(quadrant)):
        plt.annotate('Player: {}\nValue 1: {}\nValue 2: {}'.format(quadrant.name[x], quadrant.v_1[x], quadrant.v_2[x]),
                     (quadrant.v_1[x], quadrant.v_2[x])
    

    Output graph:

    enter image description here

    If you're just working in the notebook and don't need to save the image with all the player's names, then using a "hover" feature might be a better idea. Annotating every player's name might become too busy for the graph, so just hovering over the point might work out better for you.

    %matplotlib widget # place this or "%matplotlib notebook" at the top of your notebook
                       # This allows you to work with matplotlib graphs in line
    
    import mplcursors # this is the module that allows hovering features on your graph
    
    # using the same dataframe from above
    ax1 = sns.scatterplot(x = value_1, y = value_2, s = 100)
    @mplcursors.cursor(ax1, hover=2).connect("add") # add the plot to the hover feature of mplcursors
    def _(sel):
        sel.annotation.set_text('Player: {}\nValue 1: {}\nValue 2: {}'.format(df.name[sel.index], sel.target[0], sel.target[0])) # set the text
    
    
        # you don't need any of the below but I like to customize
        sel.annotation.get_bbox_patch().set(fc="lightcoral", alpha=1) # set the box color
        sel.annotation.arrow_patch.set(arrowstyle='-|>', connectionstyle='angle3', fc='black', alpha=.5) # set the arrow style
    
    

    Example outputs from hovering: enter image description here enter image description here