简体   繁体   中英

Matplotlib Fill_between not working with two curves and 'where' condition

I have the following code:

import matplotlib.pyplot as plt

tildelist = [0.38878, 0.9275000000000001, 1.0493000000000001, 0.7799400000000001, 0.21630000000000005, 0.21630000000000005, 0.9074800000000002, 2.26002, 1.0837400000000001, 0.21630000000000005, 0.21630000000000005, 0.6433, 0.9429000000000001, 0.27622, 0.23996000000000003, 0.6216000000000002, 0.68894, 0.34230000000000005, 0.21630000000000005, 0.47656000000000004, 0.66556, 1.0437, 0.3661, 0.3346, 0.5712, 0.8986600000000002, 0.74746, 0.31094, 0.5712, 0.5661600000000001, 1.3006000000000002, 0.7340199999999999, 0.0, 0.0, 2.5052098332176604, 5.061356833449, 0.0, 0.0, 0.0, 0.0, 1.64234, 1.4148400000000003, 0.9455600000000002, 0.8230599999999999, 1.5153600000000003, 0.5336799999999999, 0.5082, 0.57232, 1.12322, 1.4065800000000002, 0.5368999999999999, 0.21630000000000005, 0.3465000000000001, 0.8829800000000001, 1.8379200000000002, 1.7056200000000001, 1.05252, 1.2306, 0.99176, 1.46076, 1.4128800000000001, 0.8652, 0.9966599999999999, 1.51438, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2.6159, 3.1127600000000006, 2.7106800000000004, 2.6951400000000003, 4.0, 3.157, 2.1578199999999996, 1.9651800000000001, 1.06834, 1.69694, 1.2080600000000004, 0.8575000000000002]
pvlist = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0024485703275, 0.014189322872999998, 0.017274831464, 0.032399218874, 0.0437174946395, 0.054832859515499995, 0.08097311923249999, 0.14823322805499997, 0.183033049771, 0.3825400623385, 0.40805960146049997, 0.406044572373, 0.4546157846779999, 0.62414554279, 0.8040121546764999, 0.8566804419469998, 0.6471686383579999, 0.8845809490925, 0.883082102771, 0.43601875181149996, 1.0613568334489998, 1.1202136575354997, 1.1654046590229998, 1.2553348183145, 1.1136954158, 1.2222314657959998, 0.9697016623525, 1.2105366156069997, 1.3544616657385002, 0.5278753574214999, 1.353652237894, 1.4534492240674999, 0.6305305066884999, 0.9014175082879999, 0.5823572566129999, 1.0245447414455, 0.7280179826699998, 1.3126664895629998, 1.4048295308685, 1.4523198122069998, 1.2656314751189999, 1.2292708477774998, 1.143669808523, 1.1794532539404998, 0.9664060134575, 0.5818133189604999, 0.4612700229225, 0.8277498967979998, 0.7675148025655, 0.748532423232, 0.7318194628745, 0.5013466543799999, 0.39813316088149997, 0.23136454722699998, 0.1346367369215, 0.17184841006849996, 0.2261439741605, 0.377514939593, 0.302599843469, 0.107099320042, 0.09699960205649999, 0.08806879891699998, 0.045631237310999995, 0.025037315616499998, 0.009905696702, 0.007973754937499999, 0.003431330859, 0.001140702563, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
fixed_time_list = range(96)

resultimg, result = plt.subplots(figsize=(20, 10))
images, = result.plot(tildelist, linestyle='-', color='red')
images, = result.plot(pvlist, linestyle='-', color='green')

result.fill_between(fixed_time_list, pvlist, 0, where=pvlist<tildelist, facecolor='green', alpha=0.5)

plt.ylabel('Energy value (kW)')
plt.xlabel('Time instant')
plt.locator_params(axis='x', nbins=96)
plt.grid(True)
resultimg = plt.savefig('stackoverflow_example.png', dpi=200) 

plt.close(resultimg)

That produces this output: 在此处输入图片说明

Now, what I actually want to obtain (see the where condition) is the area between the x axis and pvlist (the green line) filled, BUT ONLY in the areas where the curve is under tildelist (the red line). It seems like the where condition is not being considered. Moreover, if I invert the condition (pvlist>tildelist), it actually works! But that's not what I want to obtain.

I also tried to convert the lists into numpy arrays, as suggested to similar questions, but it did not work.

Any help is appreciated. Regards

From the doc for fill_between :

where array of bool (length N), optional, default: None

Define where to exclude some horizontal regions from being filled. The filled regions are defined by the coordinates x[where]

So two things are important here, first your comparison of the lists just returns a single boolean value:

print(pvlist < tildelist)
# True

As you suggested one option is to use numpy arrays:

tildelist = np.array(tildelist)
pvlist = np.array(pvlist)
print(pvlist < tildelist)
# [ True  ... True False False False  True ... True False False True ...]

For me this works and produces the following plots, left pvlist<tildelist and right pvlist>tildelist :

fillbetweenfillbetween

The second thing is that where defines where to exclude some horizontal regions from being filled .

If you want:

the area between the x axis and pvlist (the green line) filled, BUT ONLY in the areas where the curve is under tildelist (the red line)

You don't want some horizontal sub regions to be excluded but rather you want to exclude some vertical sub regions. In other words you want to fill the area between the x axis and a new array which is defined as the minimum of the two curves:

pvlist_min = np.min(np.vstack([tildelist, pvlist]), axis=0)
result.fill_between(fixed_time_list, pvlist_min, 0, facecolor='green', alpha=0.5)

fillbetween

EDIT

One could add interpolation, because fill_between works only point wise so the contours are not filled exactly. By first interpolating the two curves linearly and then calculating the minimum the result follows the curves more closely:

def get_x_substeps(x, n_substeps):
    x_steps = np.diff(x, axis=-1) / n_substeps
    delta = np.arange(n_substeps) * x_steps[..., np.newaxis]
    x_ss = (x[:-1, np.newaxis] + delta).flatten()
    x_ss = np.hstack([x_ss, x[-1]])
    return x_ss

n_substeps = 10
tildelist = get_x_substeps(x=tildelist, n_substeps=n_substeps)
pvlist = get_x_substeps(x=pvlist, n_substeps=n_substeps)
fixed_time_list = get_x_substeps(x=fixed_time_list, n_substeps=n_substeps)

pvlist_min = np.min(np.vstack([tildelist, pvlist]), axis=0)

result.fill_between(fixed_time_list, pvlist_min, 0, facecolor='green', alpha=0.5)

fillbetween

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