pythonpandasplt

Scatter plots in Pandas: Plot by category with different color and shape combinations


I would like to plot a data-set by its categories, using geometric shapes such as circle, triangle and square to represent category 1 and colors to represent category 2. The output would have varying combination of the geometric shapes and colors and the legend would list the attributes of the categories separately i.e.:

circle = a
triangle = b
square = c

red = I
green = II
blue = III

Looking for solutions I found following posts which would only give solutions for one specific geometric shape having one specific color.

I tried to work something out with the code from one of the posts but without success.

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

np.random.seed(1983)
num = 10
x, y = np.random.random((2, num))
cat1 = np.random.choice(['a', 'b', 'c'], num)
cat2 = np.random.choice(['I', 'II', 'III'], num)
df = pd.DataFrame(dict(x=x, y=y, cat1=cat1, cat2=cat2))

groups = df.groupby(['cat1', 'cat2'])

fig, ax = plt.subplots()
for name, group in groups:
ax.plot(group.x, group.y, marker='o', linestyle='', ms=12, label=name)
ax.legend()

plt.show()

Solution

  • you can try this code block

    import matplotlib.pyplot as plt
    import numpy as np
    import pandas as pd
    
    #Create mapping dictionary that you want
    marker_dict = {'a':'o','b':'^','c':'s'}
    color_dict = {'I':'red', 'II':'green', 'III':'blue'}
    
    np.random.seed(1983)
    num = 10
    x, y = np.random.random((2, num))
    cat1 = np.random.choice(['a', 'b', 'c'], num)
    cat2 = np.random.choice(['I', 'II', 'III'], num)
    df = pd.DataFrame(dict(x=x, y=y, cat1=cat1, cat2=cat2))
    
    groups = df.groupby(['cat1', 'cat2'])
    
    fig, ax = plt.subplots()
    ax.margins(0.05)
    for name, group in groups:
        marker = marker_dict[name[0]]
        color = color_dict[name[1]]
        ax.plot(group.x, group.y, marker=marker, linestyle='', ms=12, label=name,color=color)
    ax.legend()
    
    plt.show()
    

    Hope it helps.