简体   繁体   中英

Reflecting points in a bar graph using matplotlib

long time lurker for programming questions, first time poster.

I am writing some code where I am making a bar graph of a bunch of values, some of which are negative and some of which are positive- plot here

In short, what I want to do is take all the negative values for the green part and overlay them onto the positive side, so you can see the asymmetry in those values. I have tried a few methods to get this to work, and perhaps I'm not searching the correct things but can't seem to find a good answer on how to do this.

The relevant code I have so far (hopefully not leaving anything out that's important for the purposes of the plot...):

import glob
import pyrap.images as pim
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import norm
import matplotlib.mlab as mlab
from scipy.optimize import * 

less_than_expected_min = -500
more_than_expected_max = 1200
n_bins = 100

bin_edges = np.linspace(less_than_expected_min, more_than_expected_max, n_bins)
for i in range(total):
    all_clipped_values = np.zeros([total,n_bins-1])

clipped_levels= np.sum(all_clipped_values,axis=0)

reflect= np.concatenate([clipped_levels[0:30], clipped_levels[30:0]])


plt.bar(bin_edges[:-1],clipped_levels,width=(more_than_expected_max -less_than_expected_min)/float(n_bins), log=True,color='green')
plt.bar(bin_edges[:-1],reflect,width=(more_than_expected_max -less_than_expected_min)/float(n_bins), log=True,color='red')

The issue when I try this method, however, is I get "AssertionError: incompatible sizes: argument 'height' must be length 99 or scalar." It's not quite clear to me how to solve this, or in fact if there is a simpler way to do this reflection than what I'm thinking.

Any feedback appreciated- thanks!

As I mentioned in my comment, maybe this will clarify

>>> x = list(range(100))
>>> x[0:30]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29]
>>> x[30:0]
[]
>>> x[30:0:-1]
[30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1]

You have to specify the negative step.

Each time you call plt.bar , if your first argument is an array of length n (the set of abscissas), then your second argument must be an array of length n (the set of ordinates).

In your case, your set of abscissas is by construction an array of length 99, hence you must ensure your set of ordinates has the same shape.

For the first call, your second argument clipped_levels seems to have the right length, but for the second call, the second argument is reflect - which is far from 99 items long.

Fix that and it should work, hopefully !

EDIT :

Something like reverse = np.concatenate([clipped_levels[:n_bins/2], clipped_levels[n_bins/2-2::-1]]) should do the trick.

Also, I still think your for loop could be replaced by a single instruction (the initialization of all_clipped_values ), unless there is some other code inside that was not relevant here.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM