creating a matplotlib scatter legend size related

前端 未结 6 2063
野性不改
野性不改 2020-12-04 20:46

I am looking for a way to include a (matplotlib) legend that describe the size of points in a scatter plot, as this could be related to another variable, like in this basic

相关标签:
6条回答
  • 2020-12-04 20:50

    This'll also work, and I think it's a bit simpler:

    msizes = np.array([3, 4, 5, 6, 7, 8])
    
    l1, = plt.plot([],[], 'or', markersize=msizes[0])
    l2, = plt.plot([],[], 'or', markersize=msizes[1])
    l3, = plt.plot([],[], 'or', markersize=msizes[2])
    l4, = plt.plot([],[], 'or', markersize=msizes[3])
    
    labels = ['M3', 'M4', 'M5', 'M6']
    
    leg = plt.legend([l1, l2, l3, l4], labels, ncol=1, frameon=True, fontsize=12,
    handlelength=2, loc = 8, borderpad = 1.8,
    handletextpad=1, title='My Title', scatterpoints = 1)
    

    Taken from: Point size legends in matplotlib and basemap plots

    0 讨论(0)
  • 2020-12-04 21:07

    The solution below used pandas to group the sizes together into set bins (with groupby). It plots each group and assigns it a label and a size for the markers. I have used the binning recipe from this question.

    Note this is slightly different to your stated problem as the marker sizes are binned, this means that two elements in a2, say 36 and 38, will have the same size as they are within the same binning. You can always increase the number of bins to make it finer as suits you.

    Using this method you could vary other parameters for each bin, such as the marker shape or colour.

    import numpy as np
    import matplotlib.pyplot as plt
    import pandas as pd
    
    N = 50
    M = 5 # Number of bins
    
    x = np.random.rand(N)
    y = np.random.rand(N)
    a2 = 400*np.random.rand(N)
    
    # Create the DataFrame from your randomised data and bin it using groupby.
    df = pd.DataFrame(data=dict(x=x, y=y, a2=a2))
    bins = np.linspace(df.a2.min(), df.a2.max(), M)
    grouped = df.groupby(np.digitize(df.a2, bins))
    
    # Create some sizes and some labels.
    sizes = [50*(i+1.) for i in range(M)]
    labels = ['Tiny', 'Small', 'Medium', 'Large', 'Huge']
    
    for i, (name, group) in enumerate(grouped):
        plt.scatter(group.x, group.y, s=sizes[i], alpha=0.5, label=labels[i])
    
    plt.legend()
    plt.show()
    

    Plot

    0 讨论(0)
  • 2020-12-04 21:08

    Use .legend_elements("sizes"):

    import numpy as np
    import matplotlib.pyplot as plt
    
    N = 50
    x = np.random.rand(N)
    y = np.random.rand(N)
    a2 = 400*np.random.rand(N)
    
    sc = plt.scatter(x, y, s=a2, alpha=0.5)
    plt.legend(*sc.legend_elements("sizes", num=6))
    plt.show()
    

    0 讨论(0)
  • 2020-12-04 21:10

    I found this here, it is so easy and concise. Hope it helps

    import matplotlib.pyplot as plt
    import numpy as np
    
    import plotly.plotly as py
    import plotly.tools as tls
    
    fig = plt.figure()
    ax = fig.add_subplot(111)
    
    x = [0,2,4,6,8,10]
    y = [0]*len(x)
    s = [100,  400, 490, 600, 240, 160] # Specifies marker size
    
    ax.scatter(x,y,s=s)
    ax.set_title('Plot with Different Marker size, matplotlib and plotly')
    
    plotly_fig = tls.mpl_to_plotly( fig )
    plotly_fig['layout']['showlegend'] = True
    plotly_url = py.plot(plotly_fig, filename='mpl-marker-size')
    
    0 讨论(0)
  • 2020-12-04 21:11

    I almost like mjp's answer, but it doesn't quite work because plt.plot's 'markersize' argument doesn't mean the same thing as plt.scatter's 's' argument. Your sizes will be wrong using plt.plot.

    Instead use:

        marker1 = plt.scatter([],[], s=a2.min())
        marker2 = plt.scatter([],[], s=a2.max())
        legend_markers = [marker1, marker2]
    
        labels = [
            str(round(a2.min(),2)),
            str(round(a2.max(),2))
            ]
    
        fig.legend(handles=legend_markers, labels=labels, loc='upper_right',
            scatterpoints=1)
    
    0 讨论(0)
  • 2020-12-04 21:11

    Building on mjp's and jpobst's answers, if you have more than two discrete sizes you can make a loop and include the labels in the call to plt.scatter():

    msizes = [3, 4, 5, 6, 7]
    markers = []
    for size in msizes:
       markers.append(plt.scatter([],[], s=size, label=size))
    
    plt.legend(handles=markers)
    

    Note that you can format the label using standard string formatting, such as label = ('M%d' %size) for the labels in mjp's answer.

    0 讨论(0)
提交回复
热议问题