2013-08-13 8 views
6

Voglio riempire il colore dell'arcobaleno sotto una curva. In realtà la funzione matplotlib.pyplot.fill_between può riempire l'area sotto una curva con un singolo colore.Come riempire il colore dell'arcobaleno sotto una curva in Python matplotlib

import matplotlib.pyplot as plt 
import numpy as np 
x = np.linspace(0, 100, 50) 
y = -(x-50)**2 + 2500 
plt.plot(x,y) 
plt.fill_between(x,y, color='green') 
plt.show() 

C'è una manopola che posso modificare il colore per essere arcobaleno? Grazie.

+0

http://stackoverflow.com/questions/11564273/matplotlib-continuous-colormap-fill-between-two-lines – tacaswell

risposta

9

Questo è abbastanza facile da hackerare se si vuole "riempire" con una serie di rettangoli:

import numpy as np 
import pylab as plt 

def rect(x,y,w,h,c): 
    ax = plt.gca() 
    polygon = plt.Rectangle((x,y),w,h,color=c) 
    ax.add_patch(polygon) 

def rainbow_fill(X,Y, cmap=plt.get_cmap("jet")): 
    plt.plot(X,Y,lw=0) # Plot so the axes scale correctly 

    dx = X[1]-X[0] 
    N = float(X.size) 

    for n, (x,y) in enumerate(zip(X,Y)): 
     color = cmap(n/N) 
     rect(x,0,dx,y,color) 

# Test data  
X = np.linspace(0,10,100) 
Y = .25*X**2 - X 
rainbow_fill(X,Y) 
plt.show() 

enter image description here

è possibile appianare i bordi frastagliati, rendendo i rettangoli più piccoli (cioè usare più punti). Inoltre puoi usare un trapezio (o anche un polinomio interpolato) per rifinire i "rettangoli".

+0

ho allegare al di sotto della soluzione che utilizza le forme trapezoidali, invece di rettangoli: http: // StackOverflow. COM/a/30470859/213683. (Ho provato ad allegarlo come modifica, ma sono stato rifiutato.) – pms

+0

@pms È una bella aggiunta, ma è troppo drastica per una modifica (da qui il rifiuto). Sono contento che tu l'abbia postato tu stesso - sono sicuro che tornerà utile! – Hooked

4

Se intendi dare qualche arguto argomento a "color =" temo che questo non esista al meglio delle mie conoscenze. Puoi farlo manualmente impostando una linea quadratica per ogni colore e variando l'offset. Riempimento tra di loro con i colori corretti darà un rainbowish Questo rende un progetto di divertimento per imparare un po 'di Python, ma se non avete voglia di provare ecco un esempio:

import matplotlib.pyplot as plt 
import numpy as np 

x = np.linspace(0, 100, 50) 

y_old = -(x-50)**2 + 2500 
for delta, color in zip([2250, 2000, 1750, 1500, 1250, 1000], ["r", "orange", "g", "b", "indigo", "violet"]): 
    y_new = -(x-50)**2 + delta 
    plt.plot(x, y, "-k") 
    plt.fill_between(x, y_old, y_new, color=color) 
    y_old = y_new 

plt.ylim(0, 2500) 
plt.show() 

Example

Come si noterà questo non sembra un arcobaleno. Questo perché la funzione che stiamo usando è una quadratica, in realtà un arcobaleno è fatto di cerchi con raggi diversi (c'è anche un divertente progetto di matematica qui!). Anche questo è tracciabile da matplotlib, vorrei provarlo e farlo in modo che tu possa tracciare più di 7 colori nell'arcobaleno, ad esempio, trama 1000 colori che coprono l'intero spettro per farlo sembrare davvero un arcobaleno!

1

Ecco una soluzione modificata della risposta accettata che utilizza i trapezi anziché i rettangoli.

import numpy as np 
import pylab as plt 

# a solution that uses rectangles 
def rect(x,y,w,h,c): 
    ax = plt.gca() 
    polygon = plt.Rectangle((x,y),w,h,color=c) 
    ax.add_patch(polygon) 

# a solution that uses trapezoids 
def polygon(x1,y1,x2,y2,c): 
    polygon = mplpl.Polygon([ (x1,y1), (x2,y2), (x2,0), (x1,0) ], color=c) 
    ax.add_patch(polygon) 

def rainbow_fill(X,Y, cmap=plt.get_cmap("jet")): 
    plt.plot(X,Y,lw=0) # Plot so the axes scale correctly 

    dx = X[1]-X[0] 
    N = float(X.size) 

    for n, (x,y) in enumerate(zip(X,Y)): 
     color = cmap(n/N) 
     # uncomment to use rectangles 
     # rect(x,0,dx,y,color) 
     # uncomment to use trapezoids 
     if n+1 == N: continue 
     polygon(x,y,X[n+1],Y[n+1],color) 

# Test data  
X = np.linspace(0,10,100) 
Y = .25*X**2 - X 
rainbow_fill(X,Y) 
plt.show() 
Problemi correlati