So, the script below requests data from postgres database and draws a diagram.
The requested data is a table with 4 columns (ID, Object, Percentage, Color)
.
The data:
result = [
(1, 'Apple', 10, 'Red'),
(2, 'Blueberry', 40, 'Blue'),
(3, 'Cherry', 94, 'Red'),
(4, 'Orange', 68, 'Orange')
]
import pandas as pd
from matplotlib import pyplot as plt
import psycopg2
conn = psycopg2.connect(
host="localhost",
port="5432",
database="db",
user="user",
password="123")
cur = conn.cursor()
cur.callproc("test_stored_procedure")
result = cur.fetchall()
cur.close()
conn.close()
print(result)
result = pd.DataFrame(result, columns=['ID', 'Object', 'Percentage', 'Color'])
fruits = result.Object
counts = result.Percentage
labels = result.Color
s = 'tab:'
bar_colors = [s + x for x in result.Color]
fig, ax = plt.subplots()
for x, y, c, lb in zip(fruits, counts, bar_colors, labels):
ax.bar(x, y, color=c, label=lb)
ax.set_ylabel('fruit supply')
ax.set_title('Fruit supply by kind and color')
ax.legend(title='Fruit color', loc='upper left')
plt.show()
Result:
As you can see in the legend "Red"
label is shown twice.
I tried several different examples of how to fix this, but unfortunately no one worked out. F.e.:
handles, labels = ax.get_legend_handles_labels()
ax.legend(handles, labels)
Either make a dictionnary of the handles/labels
to make unique combinations:
hls = {l:h for h,l in zip(*ax.get_legend_handles_labels())}
ax.legend(hls.values(), hls.keys(), loc='upper left', title='Fruit color')
Output :
Or avoid the duplicates upfront by using pandas plot
and manually draw the legend :
fig, ax = plt.subplots()
result.plot(x="Object", y="Percentage", kind="bar", rot=0,
title="Fruit supply by kind and color",
color=result["Color"].radd("tab:"), ax=ax)
labels = result["Color"].unique()
handles = [plt.Rectangle((0, 0), 0, 0, color=c) for c in labels]
ax.legend(
handles, labels, ncol=1,
handleheight=2, handlelength=3,
loc="upper left", title="Fruit color"
)
ax.set_xlabel(None)