Reputation: 14641
Is there a way to color the bars of a barchart based on the bar's value. For example:
- values below -0.5: red
- values between -0.5 to 0: green
- values between 0 to 08: blue
- etc
I have found some basic examples of bar coloring but nothing which can cater for value ranges, such as the above examples.
UPDATE:
Thank you kikocorreoso for your suggestion. This works great when both axes are numbers as per your example. However in my case my original data structure is a pandas dataframe. I then use df.stack() and plot the result. This means that the dataframes rows/columns become the x axis of the plot and the dataframe cells are the Y axis (bars).
I have tried masking as per your example but it doesn't seem to work when the Y axis are numbers and the X axis are names. eg:
col1 col2 col3 col4
row1 1 2 3 4
row2 5 6 7 8
row3 9 10 11 12
row4 13 14 15 16
The above dataframe needs to be plotted as a barchart with the row/column combinations forming the x-axis. Each cell value will be a bar. And ultimately, coloring the bars as per the original question. Thanks
Upvotes: 22
Views: 88144
Reputation: 352
With list comprehension and conditional expressions:
profit_color = [('green' if p > 0 else 'red') for p in profit]
plt.bar(year, profit, color=profit_color)
Full example with value ranges:
import matplotlib.pyplot as plt
profit = [-4.56, -0.81, -0.47, 0.25, 1.05, 1.93, 2.91, 3.43]
year = [*range(len(profit))]
profit_color = [{p<0: 'red', 0<=p<=2: 'orange', p>2: 'green'}[True] for p in profit]
plt.bar(year, profit, color=profit_color)
plt.show()
Upvotes: 10
Reputation: 21
small improvement to the answer above
x = np.arange(4)
y = np.array([-2,3,-1,2])
cc=list(map(lambda x: 'red' if x <= 0 else 'blue', y))
plt.bar(x, y, color = cc)
plt.show()
Upvotes: 1
Reputation: 1850
import numpy as np
import matplotlib.pyplot as plt
x = np.arange(4)
y = np.array([-2,3,-1,2])
cc=['colors']*len(y)
for n,val in enumerate(y):
if val<0:
cc[n]='red'
elif val>=0
cc[n]='blue'
plt.bar(x, y, color = cc)
plt.show()
Upvotes: 1
Reputation: 121
I see this question has been asked a long time ago already, but just in case it could help someone, this is what worked for me:
Iterate over all values and append colors to a list depending on customized conditions, so you get a list with as many color specifications as you have values; then use the color list in plt.bar()
:
import numpy as np
import matplotlib.pyplot as plt
x = np.arange(10)
y = np.arange(10) * 0.1
col = []
for val in y:
if val < 0.4:
col.append('blue')
elif val >= 0.7:
col.append('green')
else:
col.append('red')
# col looks like this: ['blue', 'blue', 'blue', 'blue', 'red', 'red', 'red', 'green', 'green', 'green']
plt.bar(x, y, color = col)
Upvotes: 12
Reputation: 4219
You could use masks for your datasets. A basic example could be the following:
import numpy as np
import matplotlib.pyplot as plt
x = np.arange(10)
y = np.arange(10) * 0.1
mask1 = y < 0.5
mask2 = y >= 0.5
plt.bar(x[mask1], y[mask1], color = 'red')
plt.bar(x[mask2], y[mask2], color = 'blue')
plt.show()
UPDATE:
As you updated your question I update the code. For your simple case, and if I understood correctly, you could do the following (ugly) hack:
import pandas as pd
df = pd.DataFrame({'col1':[1,2,3], 'col2':[4,5,6]},
index = ['row1','row2','row3'])
dfstacked = df.stack()
mask = dfstacked <= 3
colors = np.array(['b']*len(dfstacked))
colors[mask.values] = 'r'
dfstacked.plot(kind = 'bar', rot = 45, color = colors)
plt.show()
Or use a more OO solution.
The code briefly explained:
dfstacked
dataframe has a MultiIndex
the ticks are not well printed so I use the rot
keyword to rotate them. If you want to automate it in order to get a nice plot you can use plt.tight_layout()
before plt.show()
.I hope it helps.
Upvotes: 39