I'm trying to display a custom legend for a bar graph, but it is only displaying the first legend in the legend list. How can I display all the values in the legend?
df.time_to_travel_grouping.value_counts().plot(kind="bar",
color = ["b","tab:green","tab:red","c","m","y","tab:blue","tab:orange"],
xlabel="TTT", ylabel="Total Counts",
title="Fig4: Total Counts by Time to Travel Category (TTT)", figsize=(20,15))
plt.legend(["a","b","c","d","e","f","g","h"])
plt.subplots_adjust(bottom=0.15)
plt.subplots_adjust(left=0.15)
CodePudding user response:
Let's get the patches handles from the axes using ax.get_legend_handles_labels
:
s = pd.Series(np.arange(100,50,-5), index=[*'abcdefghij'])
ax = s.plot(kind="bar",
color = ["b","tab:green","tab:red","c","m","y","tab:blue","tab:orange"],
xlabel="TTT", ylabel="Total Counts",
title="Fig4: Total Counts by Time to Travel Category (TTT)", figsize=(20,15))
patches, _ = ax.get_legend_handles_labels()
labels = [*'abcdefghij']
ax.legend(*patches, labels, loc='best')
plt.subplots_adjust(bottom=0.15)
plt.subplots_adjust(left=0.15)
Output:
CodePudding user response:
To create an automatic legend, matplotlib stores labels for graphical elements. In the case of this bar plot, the complete 'container' pandas assigns one label to the complete 'container'.
You could remove the label of the container (assigning a label starting with _
), and assign individual labels to the bars. The xtick labels can be used, as they are already in the desired order.
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
df = pd.DataFrame({'time_to_travel_grouping': np.random.choice([*'abcdefgh'], 200)})
ax = df.time_to_travel_grouping.value_counts().plot(kind="bar",
color=["b", "tab:green", "tab:red", "c", "m", "y", "tab:blue", "tab:orange"],
xlabel="TTT", ylabel="Total Counts",
title="Fig4: Total Counts by Time to Travel Category (TTT)",
figsize=(20, 15))
ax.containers[0].set_label('_nolegend')
for bar, tick_label in zip(ax.containers[0], ax.get_xticklabels()):
bar.set_label(tick_label.get_text())
ax.legend()
plt.tight_layout()
plt.show()
With a little bit less internal manipulation, something similar can be obtained via seaborn:
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
import seaborn as sns
df = pd.DataFrame({'time_to_travel_grouping': np.random.choice([*'abcdefgh'], 200)})
plt.figure(figsize=(20, 15))
ax = sns.countplot(data=df, x='time_to_travel_grouping', hue='time_to_travel_grouping',
palette=["b", "tab:green", "tab:red", "c", "m", "y", "tab:blue", "tab:orange"],
order=df.time_to_travel_grouping.value_counts().index,
dodge=False)
plt.setp(ax, xlabel="TTT", ylabel="Total Counts", title="Fig4: Total Counts by Time to Travel Category (TTT)")
plt.tight_layout()
plt.show()