Search code examples
pythonmatplotlibplotscatter-plot

Is there a way to indicate on a plot what different colors for each point and markers represent?


Is there a way I could add a box (like how I drew in the image below) to indicate what different colors for points and the different markers represent?

Or if there is any other way than adding the boxes, since I want to make it clear for the viewer what the plot exactly means.

Scatter plot with different markers and colors


Solution

  • Yes, check out the documentation for matplotlib.pyplot's scatter plot. The marker argument is where you place the shape of the marker, the label argument is what you label the data of that plot in the legend, color is obviously the color of the markers, and s is their size.

    To put custom colors for custom conditions, you can use list comprehension to set the color for that specific condition. Then, the easiest way to show all of this in a legend is to create a custom legend:

    ######################### Mock Data ########################
    import numpy as np
    import matplotlib.pyplot as plt
    time = np.arange(0,10)
    y1 = np.random.randint(0, 100, 10)
    y2 = np.random.randint(0, 100, 10)
    y3 = np.random.randint(0, 100, 10)
    df = pd.DataFrame({"time":time, "Star":y1, "Circle":y2, "Square":y3})
    #############################################################
    
    # Create custom colors based on conditions
    y1Color = ["darkgreen" if x > 75 else "red" if x > 25 else "orange" for x in y1]
    y2Color = ["darkgreen" if x > 75 else "red" if x > 25 else "orange" for x in y2]
    y3Color = ["darkgreen" if x > 75 else "red" if x > 25 else "orange" for x in y3]
    
    # Create custom legend based on above conditions
    legend_elements = [Line2D([0], [0], marker='*', color='w', label='Star > 75', 
                              markerfacecolor='g', markersize=15),
                       Line2D([0], [0], marker='*', color='w', label='Star > 25', 
                              markerfacecolor='r', markersize=15),
                       Line2D([0], [0], marker='*', color='w', label='Star < 25', 
                              markerfacecolor='orange', markersize=15),
                       Line2D([0], [0], marker='o', color='w', label='Circle > 75', 
                              markerfacecolor='g', markersize=15),
                       Line2D([0], [0], marker='o', color='w', label='Circle > 25', 
                              markerfacecolor='r', markersize=15),
                       Line2D([0], [0], marker='o', color='w', label='Circle < 25', 
                              markerfacecolor='orange', markersize=15),
                       Line2D([0], [0], marker='s', color='w', label='Square > 75', 
                              markerfacecolor='g', markersize=15),
                       Line2D([0], [0], marker='s', color='w', label='Square > 25', 
                              markerfacecolor='r', markersize=15),
                       Line2D([0], [0], marker='s', color='w', label='Square < 25', 
                              markerfacecolor='orange', markersize=15),]
    
    # Plot all the points with custom colors and custom legends
    plt.scatter(data=df, x="time", y="Star", marker="*", color=y1Color, s=200)
    plt.scatter(data=df, x="time", y="Circle", marker="o", color=y2Color, s=200)
    plt.scatter(data=df, x="time", y="Square", marker="s", color=y3Color, s=200)
    plt.legend(handles=legend_elements)
    plt.show()
    

    Output graph: enter image description here

    Slightly shorter/more compact legend:

    ######################### Mock Data ########################
    import numpy as np
    import matplotlib.pyplot as plt
    time = np.arange(0,10)
    y1 = np.random.randint(0, 100, 10)
    y2 = np.random.randint(0, 100, 10)
    y3 = np.random.randint(0, 100, 10)
    df = pd.DataFrame({"time":time, "Star":y1, "Circle":y2, "Square":y3})
    #############################################################
    
    # Create custom colors based on conditions
    y1Color = ["darkgreen" if x > 75 else "red" if x > 25 else "orange" for x in y1]
    y2Color = ["darkgreen" if x > 75 else "red" if x > 25 else "orange" for x in y2]
    y3Color = ["darkgreen" if x > 75 else "red" if x > 25 else "orange" for x in y3]
    
    # Create custom legend based on above conditions
    legend_elements = [Line2D([0], [0], marker='', color='g', label='> 75', markersize=15),
                       Line2D([0], [0], marker='', color='r', label='> 25', markersize=15),
                       Line2D([0], [0], marker='', color='orange', label='< 25', markersize=15),
                       Line2D([0], [0], marker='*', color='w', label='Star', 
                              markerfacecolor='black', markersize=15),
                       Line2D([0], [0], marker='o', color='w', label='Circle', 
                              markerfacecolor='black', markersize=15),
                       Line2D([0], [0], marker='s', color='w', label='Square',
                              markerfacecolor='black', markersize=15),]
    
    # Plot all the points with custom colors and custom legends
    plt.scatter(data=df, x="time", y="Star", marker="*", color=y1Color, s=200)
    plt.scatter(data=df, x="time", y="Circle", marker="o", color=y2Color, s=200)
    plt.scatter(data=df, x="time", y="Square", marker="s", color=y3Color, s=200)
    plt.legend(handles=legend_elements)
    plt.show()
    

    Output enter image description here