Reputation: 25
This is a follow-up to How to combine groups of columns as a bar plot in pandas
Is it possible to alter the way bar plots are displayed. To display a player, a bar with solid color fill and the next bar with just a colored border. This is a sample plot.
Upvotes: 0
Views: 74
Reputation: 35686
This is a slight change to the styling of the columns in the previous question:
fig, ax = plt.subplots()
plot_df.plot(kind='bar', rot=0, ax=ax, legend=False, xlabel='', ylabel='Score')
players = plot_df.columns.get_level_values(0).unique()
score_types = plot_df.columns.get_level_values(1).unique()
hatches = ['/', None]
colours = ['red', 'green', 'blue']
iter_hatches = np.tile(np.repeat(hatches, plot_df.shape[0]),
len(players))
iter_colours = np.tile(np.repeat([v for c in colours
for v in [None, c]], plot_df.shape[0]),
len(players))
iter_edges = np.roll(iter_colours, -plot_df.shape[0])
for patch, colour, hatch, edge in zip(ax.patches, iter_colours,
iter_hatches, iter_edges):
if colour is None:
patch.set_fill(False)
patch.set_edgecolor(edge)
else:
patch.set_facecolor(colour)
patch.set_hatch(hatch)
ax.legend(loc=1)
plt.tight_layout()
plt.show()
Logic is to intersperse None
with the colours:
[v for c in colours for v in [None, c]]
[None, 'red', None, 'green', None, 'blue']
Create Edges based on the color column using np.roll
this will shift the colours back so that there are None
s are inverse:
iter_colours
array([None, None, None, 'red', 'red', 'red', None, None, None, 'green',
'green', 'green', None, None, None, 'blue', 'blue', 'blue', None,
None, None, 'red', 'red', 'red', None, None, None, 'green',
'green', 'green', None, None, None, 'blue', 'blue', 'blue', None,
None, None, 'red', 'red', 'red', None, None, None, 'green',
'green', 'green', None, None, None, 'blue', 'blue', 'blue'],
dtype=object)
iter_edges = np.roll(iter_colours, -plot_df.shape[0])
array(['red', 'red', 'red', None, None, None, 'green', 'green', 'green',
None, None, None, 'blue', 'blue', 'blue', None, None, None, 'red',
'red', 'red', None, None, None, 'green', 'green', 'green', None,
None, None, 'blue', 'blue', 'blue', None, None, None, 'red', 'red',
'red', None, None, None, 'green', 'green', 'green', None, None,
None, 'blue', 'blue', 'blue', None, None, None], dtype=object)
Then perform separate logic based on None
colours and not None
colours:
for patch, colour, hatch, edge in zip(ax.patches, iter_colours,
iter_hatches, iter_edges):
if colour is None: # If colour is None
patch.set_fill(False) # Set the fill to False
patch.set_edgecolor(edge) # Add an Edge Colour
else:
patch.set_facecolor(colour) # Otherwise use face colour
patch.set_hatch(hatch) # Set Hatch
Upvotes: 1