1

I have the following dataframe

import pandas as pd
import matplotlib.pyplot as plt

df = pd.DataFrame({'var': ['bid', 'on', 'off', 'bid', 'on', 'off'],
                   'aud': ['H', 'H', 'H', 'L', 'L', 'L'],
                   'eff': [0.1, 0.2, 0.3, 0.01, 0.02, 0.03],
                   'spend': [10, 20, 30, 1, 2, 3],
                   'marg': [0.001, 0.002, 0.003, 0.0001, 0.0002, 0.0003]})

My end goal is to create a bubble plot, with specific colors for every var, the marg on the y_axis, the eff on the x_axis of the plot and the size of the bubbles to be equal to spend with respective legends for the color and the size

I am using the following code

x = df.loc[df.aud == 'H']['eff']
y = df.loc[df.aud == 'H']['marg']
z = df.loc[df.aud == 'H']['spend']
colours_dict = dict(zip(['bid', 'on', 'off'], ['#185177', '#FAA22C', '#8FC5E8']))

g, ax = plt.subplots()

scatter = ax.scatter(x, y, c=[ colours_dict[i] for i in df.loc[df.aud == 'H']['var'] ], s=z*10)

# produce a legend with the unique colors from the scatter
legend1 = ax.legend(*scatter.legend_elements(),
                    loc="center", title="var")
ax.add_artist(legend1)

# produce a legend with a cross section of sizes from the scatter
handles, labels = scatter.legend_elements(prop="sizes", alpha=0.6)
legend2 = ax.legend(handles, labels, loc="upper right", title="Spend")

plt.savefig('bubbles.png')

The problem is that the legend with the colors does not show the labels.

Any help ?

1 Answer 1

1

You have two options:

Create the handles manually

import pandas as pd
import matplotlib.pyplot as plt

df = pd.DataFrame({'var': ['bid', 'on', 'off', 'bid', 'on', 'off'],
                   'aud': ['H', 'H', 'H', 'L', 'L', 'L'],
                   'eff': [0.1, 0.2, 0.3, 0.01, 0.02, 0.03],
                   'spend': [10, 20, 30, 1, 2, 3],
                   'marg': [0.001, 0.002, 0.003, 0.0001, 0.0002, 0.0003]})

x = df.loc[df.aud == 'H']['eff']
y = df.loc[df.aud == 'H']['marg']
z = df.loc[df.aud == 'H']['spend']
labels = ['bid', 'on', 'off']
colors = ['#185177', '#FAA22C', '#8FC5E8']
colours_dict = dict(zip(labels, colors))

fig, ax = plt.subplots()

c = [colours_dict[i] for i in df.loc[df.aud == 'H']['var']]
scatter = ax.scatter(x, y, c=c, s=z*10)

# produce a legend with the unique colors from the scatter
handles = [plt.Line2D([],[], ls="", marker="o", color=c) for c in colors] 
legend1 = ax.legend(handles, labels, loc="lower right", title="var")

plt.show()

Use a color mapping

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap, BoundaryNorm

df = pd.DataFrame({'var': ['bid', 'on', 'off', 'bid', 'on', 'off'],
                   'aud': ['H', 'H', 'H', 'L', 'L', 'L'],
                   'eff': [0.1, 0.2, 0.3, 0.01, 0.02, 0.03],
                   'spend': [10, 20, 30, 1, 2, 3],
                   'marg': [0.001, 0.002, 0.003, 0.0001, 0.0002, 0.0003]})

x = df.loc[df.aud == 'H']['eff']
y = df.loc[df.aud == 'H']['marg']
z = df.loc[df.aud == 'H']['spend']

labels = ['bid', 'on', 'off',]
colors = ['#185177', '#FAA22C', '#8FC5E8']
inv = [labels.index(i) for i  in df.loc[df.aud == 'H']['var']]

cmap = ListedColormap(colors)
norm = BoundaryNorm(np.arange(len(colors)+1)-0.5, len(colors))

fig, ax = plt.subplots()

scatter = ax.scatter(x, y, c=inv, s=z*10, cmap=cmap, norm=norm)

legend1 = ax.legend(scatter.legend_elements(num=len(labels))[0], labels, 
                    loc="lower right", title="var")

plt.show()
Sign up to request clarification or add additional context in comments.

2 Comments

this plots only one legend for the colors, not for the size though
I left out the size because you already know how to get that legend. See minimal reproducible example.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.