2

I have this histogram computed from a pandas dataframe.

enter image description here

I want to change the colors based on the x-axis values.
For example:

If the value is = 0 the color should be green
If the value is > 0 the color should be red
If the value is < 0 the color should be yellow  

I'm only concerned with the x-axis. The height of the bar doesn't matter much to me. All other solutions are for the y-axis.

tdy
  • 36,675
  • 19
  • 86
  • 83

2 Answers2

2

For each bar patch in ax.containers[0], use set_color based on the x position:

  • get_x returns the left edge, so get the midpoint by adding half of get_width
  • x probably won't be exactly 0, so test with some buffer (0.2 in this example)

Since you asked for pandas in the comments, this example uses DataFrame.plot.hist, but you can do this with any matplotlib-based histogram/bar plot:

df = pd.DataFrame({'A': np.random.default_rng(222).uniform(-1, 1, 40)})
ax = df.plot.hist()

for bar in ax.containers[0]:
    # get x midpoint of bar
    x = bar.get_x() + 0.5 * bar.get_width()

    # set bar color based on x
    if x < -0.2:
        bar.set_color('orange')
    elif x > 0.2:
        bar.set_color('red')
    else:
        bar.set_color('green')

tdy
  • 36,675
  • 19
  • 86
  • 83
0

Just plot them one by one:

import matplotlib as mpl
import matplotlib.pyplot as plt

x = np.linspace(-1,1,10)
y = np.random.uniform(0,1,10)
width = 0.2
plt.figure(figsize = (12, 6))
cmap = mpl.cm.RdYlGn.reversed()
norm = mpl.colors.Normalize(vmin=0, vmax=10)
for x0, y0 in zip(x,y):
    plt.bar(x0, y0, width = width, color = cmap(norm(np.abs(x0*10))))

enter image description here

Z Li
  • 4,133
  • 1
  • 4
  • 19
  • I want to change the colors based on the value on the x axis. –  Dec 02 '21 at 16:10
  • @roger this is changed based on x axis `color = cmap(norm(np.abs(x0*10)))` – Z Li Dec 02 '21 at 16:31
  • @Z li Could you explain what's happening in the code? When I plug my data in the whole thing turns green? Like a green square. –  Dec 02 '21 at 16:52
  • the color is determined by a color map `cmap ` and it is normalized to a range of `[0, 10]`. In the color part I set the color accordingly given by `x0`. Since the value of `x0` here is small (-1 to 1) I multiply it by 10. If you getting all green it is probably because your x values are too small (small value gets green and larger ones get red) – Z Li Dec 02 '21 at 17:09
  • Also if you are getting a huge square it is probably because you set the `width` of the bars to be too large – Z Li Dec 02 '21 at 17:10
  • I've played with it for a while. What would be the best way to add a pandas df to your solution? Your solution works as is but I can't get it to work with my solution. Sometimes it's all green, sometimes it's all yellow. I changed the x variable to be my actual data and I changed the y to be just a count to 20 because it really doesn't matter to me. But that didn't give me similar results to what you have. –  Dec 02 '21 at 17:30
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/239787/discussion-between-roger-and-z-li). –  Dec 02 '21 at 17:33