13

I have a bar-graph like the following: http://matplotlib.org/examples/api/barchart_demo.html

In that case, let's assume each of the groups G1- G5 represent the average score that men in each group got on some exam and women in each group got on the same exam.

Now let's say I have some other feature associated with each group (avg. likability (float between 1-5)).

Ex: Avg Likability of men in G1 - 1.33
                   Avg Likability of women in G1 - 4.6
                   Avg Likability of men in G2- 5.0
                   .... etc...

Lets assume 1 - not likable and 5 - very likable

I want to know how I can incorporate this feature of likability into each bar by changing the shade of the color example: since men of group 1 in the above example have 1.33, their graph would be shaded a lighter shade of red than the men of G2, since men of G2 have 5.0 likability, their bar would be the darkest shade of red in the graph, and the same thing for the women.

I hope I have made myself clear. I would really appreciate if someone could point me to a resource in matplotlib that could achieve this, as I am very new to this package.

Thanks in advance.

tacaswell
  • 84,579
  • 22
  • 210
  • 199
anonuser0428
  • 11,789
  • 22
  • 63
  • 86

3 Answers3

13

bar takes a list of colors as an argument (docs). Simply pass in the colors you want.

import matplotlib.pyplot as plt
import matplotlib.cm as cm
from matplotlib.colors import Normalize
from numpy.random import rand

fig, ax = plt.subplots(1, 1)
# get a color map
my_cmap = cm.get_cmap('jet')
# get normalize function (takes data in range [vmin, vmax] -> [0, 1])
my_norm = Normalize(vmin=0, vmax=5)
# some boring fake data
my_data = 5*rand(5)
ax.bar(range(5), rand(5), color=my_cmap(my_norm(my_data)))

plt.show()

enter image description here

tacaswell
  • 84,579
  • 22
  • 210
  • 199
  • 1
    right but over here the color of the bar is dependent on its value from the y-axis, which is passed to the bar as a list. I want to add an additional feature to each bar wherein the color of the bar indicates the rating (example if we talk about the number of restaurant reviews per week, the color of a bar would be how positive or negative the reviews were in a given week (positive would be pink, negative would be red or something) Is there any way to achieve this? – anonuser0428 Sep 20 '13 at 15:44
  • Please re-read the answer (and see the edit to make it clearer). This does _exactly_ what you want. – tacaswell Sep 20 '13 at 15:54
  • 1
    _This does exactly what you want._ That graph sure doesn't look like anything the op asked for. – 7stud Sep 24 '13 at 22:40
  • 1
    @7stud I assume the OP is clever enough to understand color maps. – tacaswell Sep 24 '13 at 22:44
  • @tacaswell will you please help me with how to show colormap also. – harsh poddar Jul 27 '20 at 07:53
6
import pandas as pd
import matplotlib.pyplot as plt  

df = pd.DataFrame([1,2,3,4], [1,2,3,4])   
color = ['red','blue','green','orange']
df.plot(kind='bar', y=0, color=color, legend=False, rot=0)

enter image description here

Georgy
  • 12,464
  • 7
  • 65
  • 73
Bisi Afolalu
  • 59
  • 1
  • 4
3
import matplotlib.pyplot as plt
import matplotlib as mp
import numpy as np


xs = "ABCDEFGHI"
ys = [5, 6, 7, 8, 9, 10, 11, 12, 13]


#Colorize the graph based on likeability:

likeability_scores = np.array([
    5, 4.5, 3.5,
    2.5, 1.5, .5,
    2, 3, 4,
])

data_normalizer = mp.colors.Normalize()
color_map = mp.colors.LinearSegmentedColormap(
    "my_map",
    { 
        "red": [(0, 1.0, 1.0),
                (1.0, .5, .5)],

        "green": [(0, 0, 0),
                  (1.0, 0, 0)],

        "blue": [(0, 0, 0),
                 (1.0, 0, 0)]
    }

)

#Map xs to numbers:
N = len(xs)
x_nums = np.arange(1, N+1)

#Plot a bar graph:
plt.bar(
    x_nums,
    ys,
    align="center",
    color=color_map(data_normalizer(likeability_scores))
)

#Change x numbers back to strings:
plt.xticks(x_nums, xs)

plt.show()

--output:--

enter image description here

r,g,b values run from 0-1. Here is the red mapping:

       "red": [(0, 1.0, 1.0),
               (1.0, .5, .5)],

The first element in each tuple specifies the normalized likeability score. The second element in each tuple specifies the shade of red (0-1). The third element in each tuple is for more complicated stuff, so here it is always the same as the second element.

The red mapping specifies that the normalized likeability scores between 0-1.0 (the first elements of each tuple) will be mapped to the range 100% red to 50% red (the second elements in each tuple). A normalized likeability score of 0 will be mapped to 100% red, and a normalized likeability score of 1.0 will be mapped to 50% red. Setting the darkest red to 50% keeps the red from getting so dark that it looks brown or black.

You can specify as many tuples as you want--you just have to make sure you assign red values for the whole range (0-1) of normalized likeability scores, e.g.:

       "red": [(0, .5, .5),
               (.8, .6, .6),
               (1.0, .9, .9)],

You can't do this:

       "red": [(0, .5, .5),
               (.8, 1.0, 1.0)],
7stud
  • 46,922
  • 14
  • 101
  • 127