Como obter linhas coloridas diferentes para gráficos diferentes em uma única figura?

202

Estou usando matplotlibpara criar os gráficos. Eu tenho que identificar cada plotagem com uma cor diferente que deve ser gerada automaticamente pelo Python.

Você pode me dar um método para colocar cores diferentes para diferentes parcelas na mesma figura?

pottigopi
fonte

Respostas:

424

O Matplotlib faz isso por padrão.

Por exemplo:

import matplotlib.pyplot as plt
import numpy as np

x = np.arange(10)

plt.plot(x, x)
plt.plot(x, 2 * x)
plt.plot(x, 3 * x)
plt.plot(x, 4 * x)
plt.show()

Gráfico básico demonstrando ciclismo em cores

E, como você já deve saber, você pode facilmente adicionar uma legenda:

import matplotlib.pyplot as plt
import numpy as np

x = np.arange(10)

plt.plot(x, x)
plt.plot(x, 2 * x)
plt.plot(x, 3 * x)
plt.plot(x, 4 * x)

plt.legend(['y = x', 'y = 2x', 'y = 3x', 'y = 4x'], loc='upper left')

plt.show()

Trama básica com legenda

Se você deseja controlar as cores que serão percorridas:

import matplotlib.pyplot as plt
import numpy as np

x = np.arange(10)

plt.gca().set_color_cycle(['red', 'green', 'blue', 'yellow'])

plt.plot(x, x)
plt.plot(x, 2 * x)
plt.plot(x, 3 * x)
plt.plot(x, 4 * x)

plt.legend(['y = x', 'y = 2x', 'y = 3x', 'y = 4x'], loc='upper left')

plt.show()

Gráfico mostrando controle sobre o ciclo de cores padrão

Se você não estiver familiarizado com o matplotlib, o tutorial é um bom lugar para começar .

Editar:

Primeiro, se você tiver muitas (> 5) coisas que deseja traçar em uma figura, também:

  1. Coloque-os em gráficos diferentes (considere usar algumas sub-gráficos em uma figura) ou
  2. Use algo diferente de cor (por exemplo, estilos de marcador ou espessura de linha) para distinguir entre eles.

Caso contrário, você vai acabar com uma trama muito confusa! Seja legal com quem vai ler o que estiver fazendo e não tente colocar 15 coisas diferentes em uma única figura !!

Além disso, muitas pessoas são daltônicas em graus variados, e é difícil distinguir entre várias cores sutilmente diferentes para mais pessoas do que você imagina.

Dito isto, se você realmente deseja colocar 20 linhas em um eixo com 20 cores relativamente distintas, aqui está uma maneira de fazê-lo:

import matplotlib.pyplot as plt
import numpy as np

num_plots = 20

# Have a look at the colormaps here and decide which one you'd like:
# http://matplotlib.org/1.2.1/examples/pylab_examples/show_colormaps.html
colormap = plt.cm.gist_ncar
plt.gca().set_prop_cycle(plt.cycler('color', plt.cm.jet(np.linspace(0, 1, num_plots))))

# Plot several different functions...
x = np.arange(10)
labels = []
for i in range(1, num_plots + 1):
    plt.plot(x, i * x + 5 * i)
    labels.append(r'$y = %ix + %i$' % (i, 5*i))

# I'm basically just demonstrating several different legend options here...
plt.legend(labels, ncol=4, loc='upper center', 
           bbox_to_anchor=[0.5, 1.1], 
           columnspacing=1.0, labelspacing=0.0,
           handletextpad=0.0, handlelength=1.5,
           fancybox=True, shadow=True)

plt.show()

Cores exclusivas para 20 linhas com base em um determinado mapa de cores

Joe Kington
fonte
17
Observe o último exemplo: nas versões mais recentes do matplotlib, o item set_color_cyclefoi descontinuado, de modo que a linha deve ser plt.gca().set_prop_cycle(plt.cycler('color', plt.cm.jet(np.linspace(0, 1, num_plots))))e apenas alterá-la plt.cm.YOUR_PREFERED_COLOR_MAPpara atender às suas necessidades.
Nate
1
@JoeKington: A explicação foi maravilhoso, obrigado muito muito
Rika
isso é ótimo. existe uma maneira de torná-los interativos? por exemplo em RI convertido ggplot para ggplotly (), e a trama se torna html interactiva
Krazzy R
Estou convencido de que o OP sabia que o Matplotlib colore curvas apropriadamente diferentes em uma única plotagem (em uma única axes) e perguntei sobre a variação da cor de uma única linha em diferentes plotagens (diferentes axes) ... Dito isto, excelente resposta a uma importante pergunta (possivelmente diferente do que OP perguntou, mas ninguém pode dizer porque eles pediram esta única pergunta e desapareceu!) - 1
gboffi
37

Configurando-os mais tarde

Se você não souber o número de plotagens que deseja plotar, poderá alterar as cores depois de plotá-las, recuperando o número diretamente da plotagem usando .lines, use esta solução:

Alguns dados aleatórios

import matplotlib.pyplot as plt
import numpy as np

fig1 = plt.figure()
ax1 = fig1.add_subplot(111)


for i in range(1,15):
    ax1.plot(np.array([1,5])*i,label=i)

O trecho de código que você precisa:

colormap = plt.cm.gist_ncar #nipy_spectral, Set1,Paired   
colors = [colormap(i) for i in np.linspace(0, 1,len(ax1.lines))]
for i,j in enumerate(ax1.lines):
    j.set_color(colors[i])
  

ax1.legend(loc=2)

O resultado é o seguinte:insira a descrição da imagem aqui

GM
fonte
8

TL; DR Não, isso não pode ser feito automaticamente . Sim, é possível.

import matplotlib.pyplot as plt
my_colors = plt.rcParams['axes.prop_cycle']() # <<< note that we CALL the prop_cycle
fig, axes = plt.subplots(2,3)
for ax in axes.flatten(): ax.plot((0,1), (0,1), **next(my_colors))

insira a descrição da imagem aqui Cada plotagem ( axes) em uma figura ( figure) tem seu próprio ciclo de cores - se você não forçar uma cor diferente para cada plotagem, todas as plotagens compartilham a mesma ordem de cores, mas, se esticarmos um pouco o que "automaticamente" significa , pode ser feito.


O OP escreveu

[...] eu tenho que identificar cada plotagem com uma cor diferente que deve ser gerada automaticamente pelo [Matplotlib].

Mas ... Matplotlib gera automaticamente cores diferentes para cada curva diferente

In [10]: import numpy as np
    ...: import matplotlib.pyplot as plt

In [11]: plt.plot((0,1), (0,1), (1,2), (1,0));
Out[11]:

insira a descrição da imagem aqui

Então, por que o pedido de OP? Se continuarmos a ler, temos

Você pode me dar um método para colocar cores diferentes para diferentes parcelas na mesma figura?

e faz sentido, porque cada trama (cada uma axesna linguagem de Matplotlib) tem a sua color_cycle(ou melhor, em 2018 prop_cycle) e cada trama ( axes) reutiliza as mesmas cores na mesma ordem.

In [12]: fig, axes = plt.subplots(2,3)

In [13]: for ax in axes.flatten():
    ...:     ax.plot((0,1), (0,1))

insira a descrição da imagem aqui

Se esse é o significado da pergunta original, uma possibilidade é nomear explicitamente uma cor diferente para cada gráfico.

Se as plotagens (como geralmente acontecem) forem geradas em um loop, precisamos ter uma variável de loop adicional para substituir a cor escolhida automaticamente pelo Matplotlib.

In [14]: fig, axes = plt.subplots(2,3)

In [15]: for ax, short_color_name in zip(axes.flatten(), 'brgkyc'):
    ...:     ax.plot((0,1), (0,1), short_color_name)

insira a descrição da imagem aqui

Outra possibilidade é instanciar um objeto cycler

from cycler import cycler
my_cycler = cycler('color', ['k', 'r']) * cycler('linewidth', [1., 1.5, 2.])
actual_cycler = my_cycler()

fig, axes = plt.subplots(2,3)
for ax in axes.flat:
    ax.plot((0,1), (0,1), **next(actual_cycler))

insira a descrição da imagem aqui

Note que type(my_cycler)é cycler.Cyclermas type(actual_cycler)é itertools.cycle.

gboffi
fonte
3

Eu gostaria de oferecer uma pequena melhoria na última resposta do loop fornecida no post anterior (esse post está correto e ainda deve ser aceito). A suposição implícita feita ao rotular o último exemplo é que plt.label(LIST)coloca o número da etiqueta X na LISTlinha correspondente à décima vez em que plotfoi chamado. Eu já tive problemas com essa abordagem antes. A maneira recomendada de criar legendas e personalizar seus rótulos de acordo com a documentação do matplotlibs ( http://matplotlib.org/users/legend_guide.html#adjusting-the-order-of-legend-item ) é ter uma sensação calorosa de que os rótulos juntamente com os gráficos exatos que você acha que eles fazem:

...
# Plot several different functions...
labels = []
plotHandles = []
for i in range(1, num_plots + 1):
    x, = plt.plot(some x vector, some y vector) #need the ',' per ** below
    plotHandles.append(x)
    labels.append(some label)
plt.legend(plotHandles, labels, 'upper left',ncol=1)

**: Matplotlib Legends não está funcionando

Tommy
fonte
3
Apenas fyi: você também pode usar o "label" kwarg para plotar e chamar a legenda sem argumentos.
quer