ZAK
ZAK

Reputation: 105

Show all colors in histogram bars on top of each other without adding weights in python

I am using following code to make 5 bars on 3 different data sets a, b and c. How can I show all colors in each bar. I don't want their value to add up. For example, in first bar if the value of Green is 1, Yellow is 3 and Red is 6 I don't want the final value to be 10 rather it should be 6 but all colors should appear till their final value. I don't want to use transparent colors or only bar outlines.

import matplotlib.pyplot as plt
import numpy as np

a = [1, 2, 3, 4, 5]
b = [3, 4, 1, 10, 9]
c = [6, 7, 2, 4, 6]
ind = np.arange(len(a))

fig = plt.figure()
ax = fig.add_subplot(111)
ax.bar(x=ind, height=a, width=0.35, align='center', label='Green',
       facecolor='g')
ax.bar(x=ind, height=b, width=0.35,  align='center', label='Yellow',
       facecolor='y')
ax.bar(x=ind, height=c, width=0.35,  align='center', label='Red', facecolor='r')

plt.xticks(ind, a)
plt.xlabel('Coordination Number')
plt.ylabel('Frequency')
plt.legend()
plt.show()

enter image description here

Upvotes: 0

Views: 722

Answers (2)

gherka
gherka

Reputation: 1446

If I understand your question correctly, you want to show all colour bars starting from the same zero baseline and grouped together under their corresponding Number?

I'll use bokeh for plotting, since it provides an easy way to "offset" each bar in the group. To vary the amount of visual offset for each bar, change the second parameter of the dodge function. For this combination of widths, 0.05 seemed like a nice value.

from bokeh.io import output_notebook, output_file, show
from bokeh.models import ColumnDataSource
from bokeh.plotting import figure
from bokeh.transform import dodge

output_notebook() # or output_file("chart.html") if not using Jupyter

x_axis_values = [str(x) for x in range(1, 6)]

data = {
    "Coordination Number" : x_axis_values,
    "Green"               : [1, 2, 3, 4, 5],
    "Yellow"              : [3, 4, 1, 10, 9],
    "Red"                 : [6, 7, 2, 4, 6]
}

src = ColumnDataSource(data=data)

p = figure(
    x_range=x_axis_values, y_range=(0, 10), plot_height=275,
    title="Offset Group Bar Chart", toolbar_location=None, tools="")

p.vbar(
    x=dodge('Coordination Number', -0.05, range=p.x_range),
    top='Green', width=0.2, source=src, color="#8DD3C7", legend_label="Green")

p.vbar(
    x=dodge('Coordination Number',  0.0,  range=p.x_range),
    top='Yellow', width=0.2, source=src, color="#FFD92F", legend_label="Yellow")

p.vbar(
    x=dodge('Coordination Number',  0.05, range=p.x_range),
    top='Red', width=0.2, source=src, color="#E15759", legend_label="Red")

p.x_range.range_padding = 0.1
p.xgrid.grid_line_color = None
p.legend.location = "top_left"
p.legend.orientation = "horizontal"
p.xaxis.axis_label = "Coordination Number"
p.yaxis.axis_label = "Frequency"

show(p)

enter image description here

Upvotes: 0

r-beginners
r-beginners

Reputation: 35205

The reference value for the 'a' column is 6, but it was unclear if it is the maximum value. I understood it to be the maximum value and calculated the composition ratio. I created a stacked graph based on the results.

import numpy as np
import pandas as pd
a = [1, 2, 3, 4, 5]
b = [3, 4, 1, 10, 9]
c = [6, 7, 2, 4, 6]
ind = np.arange(len(a))
df = pd.DataFrame({'a':a,'b':b,'c':c}, index=ind)
df['total'] = df.sum(axis=1)
df['max'] = df[['a','b','c']].max(axis=1)
df['aa'] = df['max']*(df['a']/df['total'])
df['bb'] = df['max']*(df['b']/df['total'])
df['cc'] = df['max']*(df['c']/df['total'])
df
    a   b   c   total   max aa  bb  cc
0   1   3   6   10  6   0.600000    1.800000    3.600000
1   2   4   7   13  7   1.076923    2.153846    3.769231
2   3   1   2   6   3   1.500000    0.500000    1.000000
3   4   10  4   18  10  2.222222    5.555556    2.222222
4   5   9   6   20  9   2.250000    4.050000    2.700000

import matplotlib.pyplot as plt

fig = plt.figure()
ax = fig.add_subplot(111)
ax.bar(x=ind, height=df.loc[:,'aa'], bottom=0, width=0.35, align='center', label='Green',
       facecolor='g')
ax.bar(x=ind, height=df.loc[:,'bb'], bottom=df.loc[:,'aa'], width=0.35, align='center', label='Yellow',
       facecolor='y')
ax.bar(x=ind, height=df.loc[:,'cc'], bottom=df.loc[:,'aa']+df.loc[:,'bb'], width=0.35, align='center', label='Red', facecolor='r')

plt.xticks(ind, a)
plt.xlabel('Coordination Number')
plt.ylabel('Frequency')
plt.legend()
plt.show()

enter image description here

Upvotes: 1

Related Questions