quarta-feira, 6 de maio de 2020

Crie seus próprios marcadores com Matplotlib

Crie seus próprios marcadores com Matplotlib


Na biblioteca matplotlib existem muitos marcadores que podem ser usados em diversas situações para representar um tipo de dado. Mas cada projeto tem suas necessidades e especificações. E não é raro você precisar de um marcador próprio para um projeto. Não sendo adequado os marcadores padrão da biblioteca. Como um projeto onde você precisa criar um marcador com a silhueta de um edifício, animal ou uma marca. Se esse é o seu caso não se preocupe pois a biblioteca matplotlib nos permite criar nossos próprios marcadores.

Como criar marcadores com a biblioteca matplotlib

A criação de um marcador segue a mesma logica da criação de um gráfico com pontos interligados. Para criar um gráfico precisamos das coordenadas de cada nó do gráfico. Quando existe mais de um nó no gráfico uma linha é traçada de um ponto ao outro, e assim sucessivamente até o último ponto, criando um figura. Na criação de um marcador seguimos a mesma lógica. Criamos os nós com as coordenadas e no final temos um conjunto de pontos conectados que formam uma imagem.
Exemplo
import numpy as np
import matplotlib.path as mpath
from matplotlib import pyplot as plt

forma = [
  (0., -2., mpath.Path.MOVETO),
  (2., 0., mpath.Path.LINETO),
  (0., 2., mpath.Path.LINETO),
  (-2., 0., mpath.Path.LINETO),
  (0., -2., mpath.Path.CLOSEPOLY)
]

u, v, codes = zip(*forma)
novo_marcador = mpath.Path(np.asarray((u, v)).T, codes)
dados = np.random.rand(8, 8)
plt.scatter(dados[:,0], dados[:, 1], color=(1., 0., .40), marker=novo_marcador, s=64)
plt.show()
Executando o código acima o seu gráfico deve parecer com esse:

Como funciona…

Nos exemplos anteriores passamos uma string para o parâmetro marker. Isso porque esses marcadores são marcadores predefinidos da biblioteca matplotlib. Assim só precisamos passar, como argumento do parâmetro, uma string correspondente a um marcador predefinido. Por isso só precisamos passar uma string. Mas o argumento do parâmetro marker também pode ser uma instância do Path.
O método path é o responsável por criar o nosso novo marcador. Esse método deve receber dois argumentos: as coordenadas de cada ponto da nossa figura e uma instrução. Para facilitar o entendimento criamos uma lista com as coordenadas e a instrução. Assim não precisamos ter duas listas separadas, uma com as coordenadas e outra com as instruções. Mais o método path não pode receber essa lista do jeito que está, as coordenadas e as instruções devem estar separadas. Por isso usamos a função zip, que faz esse trabalho para nos.
O nosso marcador toma forma com o movimento do curso entre os pontos. Para o cursor saber o que esta fazendo ele precisa de instruções. Esse curso pode receber essas três instruções:
  • MOVETO: Com essa instrução o cursor é posicionado na coordenada informada, mas nenhuma linha é desenhada.
  • LINETO: Com essa instrução o curso é posicionado em outra posição. E dessa vez uma linha é traçada.
  • CLOSEPOLY: Com essa instrução fechamos o nosso polígono/marcador.
Com isso podemos criar um marcador com qualquer forma que desejamos. É só ter paciência e descrever as coordenadas da figura que se deseja utilizar como marcador. Outra alternativa é converter de um desenho SVG.

Alterando tamanho do marcador com Matplotlib

Alterando tamanho do marcador com Matplotlib


Já vimos que podemos alterar a cor, a borda e a forma de um ponto usado num gráfico com a biblioteca matplotlib. Mas em alguns casos só essas alterações não serão suficientes para representar um dado de forma apropriada. Em alguns casos você precisa que o tamanho do ponto cresça de acordo com o valor do dado que o ponto está representando. Por isso a biblioteca matplotlib fornece formas de alterar o tamanho dos pontos.

Como alterar o tamanho dos marcadores

Assim como alteramos a cor, a barda e a forma de um marcador por um parâmetro especifico da função scatter, alterar o tamanho não é diferente. Fazemos essa alteração através de um parâmetro. O parâmetro em questão é o s.
Exemplo
import numpy as np
import matplotlib.pyplot as plt

a = np.random.randn(100, 2)
b = np.random.randn(100, 2)

plt.scatter(a[:,0], a[:, 1], color='.75', marker='x', s=80.)
plt.scatter(b[:,0], b[:, 1], color='.25', marker='^', s=20.)
plt.show()
Executando o exemplo acima o resultado deve ser parecido com esse gráfico:

Como funciona o para metro s

Nesse exemplo mostramos dois conjuntos de dados, cada um representado por um marcador de tamanho diferente. O tamanho é do marcador é definido pelo valor passado ao parâmetro s.
O valor passado ao parâmetro s define o tamanho da área do marcador e não o seu raio. Assim os tamanhos são as áreas reais da superfície e não os raios, eles seguem uma progressão quadrática (os marcadores quatro vezes maior terão raios duas vezes maior).

Marcadores com Matplotlib

Marcadores com Matplotlib


Nos exemplos anteriores, criamos gráficos com pontos sem muitas alterações, apenas alteramos as cores e, em alguns casos, adicionamos uma borda. Mas a biblioteca matplotlib fornece mais opções para alterar a aparência de um ponto, criando um gráfico com maior variedade visual. Assim podemos representar mais dados sem precisar recorrer a mudar a cor do ponto, utilizando outros marcadores além deste.

Mãos a obra…

A biblioteca matplotlib nos permiti especificar o marcador que será usado de várias formas. Veja algumas formas abaixo:
Marcadores predefinidos: Esses marcadores são definidos pela própria biblioteca. Podemos usar esses marcadores passando um número entre zero e oito ou passando uma string.
Lista de vértices: Com essa lista de valores par, passamos as coordenadas do caminho das formas que queremos utilizar.

Como usamos marcadores na função scatter

Para alterar o marcador utilizado pela função scatter podemos usar o parâmetro marker. O parâmetro marker pode receber marcadores predefinidos, lista de vértices ou um marcador definido por você. Vamos ver o funcionamento do parâmetro marker:
Exemplo
import numpy as np
import matplotlib.pyplot as plt

a = np.random.randn(100, 2)
b = np.random.randn(100, 2)

plt.scatter(a[:,0], a[:, 1], color=(0.0, .40, 1.0), marker='x')
plt.scatter(b[:,0], b[:, 1], color=(.40, 1.0, .21), marker='^')
plt.show()
Executando o exemplo acima você deve ver um gráfico parecido com esse:

Como funciona o parâmetro marker

Nesse exemplo, passamos para o parâmetro marker uma string com o marcador desejado. Note que chamamos a função scatter duas vezes, isso porque o parâmetro marker não aceita uma lista com marcadores, assim como faz o parâmetro color com as cores. Para cada marcador novo, precisamos chamar a função novamente. Por isso não podemos fazer uma única chamada da função.

Estilo de preenchimento com Matplotlib

Estilo de preenchimento com Matplotlib


Se por algum motivo você precisar criar um gráfico de barras com a mesma cor, você vai precisar usar algum artificio para conseguir distinguir de um dado do outro. E um bom modo de fazer isso é preencher a barra com um padrão. Assim, mesmo que as cores sejam idênticas, ainda será possível distinguir uma barra da outra.

Como preencher uma barra com um padrão

Para preencher uma barra com algum padrão, utilizamos o parâmetro hatch.
Exemplo
import numpy as np
import matplotlib.pyplot as plt

n_barras = 8
y1 = np.random.random(n_barras)
y2 = np.random.random(n_barras)
x = np.arange(n_barras)

plt.bar(x, y1, color = (.40, 1.0, .21), hatch = '.')
plt.bar(x, y1 + y2, bottom = y1, color = (.0, .40, 1.0), hatch = '*')
plt.show()
Executando o exemplo acima o resultado deve ser um gráfico parecido com este:

Como o parâmetro hatch funciona

O parâmetro hatch pode receber alguns valores. E de acordo com o valor passado ao parâmetro, a barra será preenchida com um padrão diferente. Veja alguns valores aceito pelo parâmetro hatch:
  • /
  • \
  • |
  • -
  • +
  • x
  • o
  • O
  • .
  • *
Para cada valor passado ao parâmetro hatch, existe um padrão de preenchimento. No nosso caso usamos o asterisco e o ponto. O que resultou no preenchimento com estrelas e pontos, respectivamente.
Se você precisar trocar a cor do padrão de preenchimento use o parâmetro edgecolor. O parâmetro edgecolor funciona como o parâmetro color, recebendo valores com três cores, quatro cores, nomes definidos e tons de cinza.

domingo, 3 de maio de 2020

Padrão e espessura da linha com Matplotlib

Padrão e espessura da linha com Matplotlib


Algumas gráficas só trabalham com cores em tons de cinza. E em muitos casos essas cores se resumem em três níveis de cinza. Nessa condições não é muito fácil criar um gráfico para representar mais de três dados distintos. E é ai que a biblioteca matplotlib entra. Ela fornece maneiras de tornar elementos com a mesma cor diferentes. Como por exemplo, diferenciando elementos pela espessura e padrão. Um elemento com a mesma cor, mas com padrão e espessura diferentes, podem ser facilmente reconhecidos como um novo grupo de dados, independente da cor.

Como alterar o padrão e espessura da linha

Para alterar as cores usadas no gráfico passamos valores para o parâmetro color e, em alguns casos, para o parâmetro colormaps. Para alterar o padrão ou estilo de uma linha, também passamos valores para um parâmetro. Nesse caso, o linestyle.
Exemplo
import matplotlib.pyplot as plt

x = [0, 1, 2, 3, 4]
y1 = [0, 1, 2, 3, 4]
y2 = [0, 2, 4, 6, 8]
y3 = [0, 3, 5, 7, 9]

plt.plot(x, y1, color = 'k', linestyle = 'solid')
plt.plot(x, y2, color = 'k', linestyle = 'dashed')
plt.plot(x, y3, color = 'k', linestyle = 'dashdot')
plt.show()
A execução do código acima resulta no gráfico abaixo:

Como funciona o parâmetro linestyle

O parâmetro linestyle pode receber quatro valores diferentes. Para cada valor a linha vai ser traçada com um padrão diferente. Esses são os quatro valores que o parametro linestyle pode receber:
  • solid
  • dashed
  • dotted
  • dashdot

Tem mais…

A largura da linha

Não é só o estilo do tracejado da linha que pode ser alterado. O parâmetro linewidth nos permite definir a largura da linha. Por padrão o valor desse parâmetro é um. Nos podemos alterar esse valor para chamar atenção para uma linha especifica com um dado ligeiramente mais relevante.
Exemplo
import matplotlib.pyplot as plt

x = [0, 1, 2, 3, 4]
y1 = [0, 1, 2, 3, 4]
y2 = [0, 2, 4, 6, 8]
y3 = [0, 3, 5, 7, 9]

plt.plot(x, y1, color = 'k', linestyle = 'solid', linewidth = 2)
plt.plot(x, y2, color = 'k', linestyle = 'dashed', linewidth = 3)
plt.plot(x, y3, color = 'k', linestyle = 'dashdot', linewidth = 1.7)
plt.show()
O código acima resulta no gráfico abaixo:


Nesse exemplo, podemos perceber que quanto maior for o valor passado para o parâmetro linewidth maior será a largura da linha.

Função bar com colormaps

Função bar com colormaps


Muitas funções da biblioteca matplotlib tem suporte ao uso de mapas de cores. Uma dessas funções e a função scatter (E outras que veremos nos próximos tutoriais). Infelizmente a função bar não possui suporte ao uso de colormaps. Mas isso não significa que não podemos usar um mapa de cores para definir as cores das barras da função bar.
A biblioteca matplotlid fornece funções para gerar uma lista de cores a partir de um colormap. E com essa lista de cores podemos passar para o parâmetro color da função. Assim, não é necessário que uma função tenha suporte ao uso de colormaps para podemos usar um colormap.

Como usar colormaps com a função bar

Assim como fizemos no exemplo anterior, vamos usar o módulo matplotlib.cm. Mas com uma diferença: vamos utilizar o objeto diretamente, em vez de permitir que uma função faça a renderização das cores automaticamente. Também vamos precisar importar o módulo matplotlib.colors. Esse módulo contêm funções para criação de cores e manipulação. Como veremos a seguir:
Exemplo
import numpy as np
import matplotlib.cm as cm
import matplotlib.colors as col
import matplotlib.pyplot as plt

dados = np.random.randint(99, size = 50)
mapa_cores = cm.ScalarMappable(col.Normalize(0, 99), cm.winter)
plt.bar(np.arange(len(dados)), dados, color = mapa_cores.to_rgba(dados))
plt.show()
Executando o código acima o resultado deve ser um gráfico com barras parecido com esse:

Como funciona…

Primeiro criamos uma matriz com cinquenta números aleatórios entre zero e noventa e nove. Depois criamos uma lista de cores escalar com as cores normalizadas do mapa de cores winter. Depois a função to_rgba converte a lista de valores para uma lista de cores. Desse jeito usamos um colormap na função bar, mesmo que a função não tenha suporte a colormaps.

Função scatter com colormaps

Função scatter com colormaps


Quando se trabalha com muitas cores num gráfico, um dos problemas é achar uma combinação de cores adequada. Outro problema é o trabalho que isso da. Escrever cada cor uma por uma é demorado. Para resolver esses dois problemas a biblioteca matplotlib colormaps (mapas de cores). Com um colormaps você não precisar se preocupar com a combinação de cores e nem de escrever uma por uma. Os mapas de cores fornecem cores de forma continua baseado numa cor ou em varias.

Como usar colormaps com a função scatter

O módulo matplotli.cm fornece muitos mapas de cores. Além disso esse módulo fornece funções para você criar o seu próprio mapa de core. Um coisa que não é muito usado,pelo menos por min. Já que os mapas de cores, que vem no módulo matplotlib.cm, são numerosos e servem para a maioria das necessidades.
Nos exemplos anteriores, com a função scatter, usamos o parâmetro color com uma lista de cores. Os colormaps funcionam como uma lista de cores, com a diferença que as cores seguem uma sequência lógica. E ao invés de usar o parâmetro color vamos usar o cmap.
Exemplo
import numpy as np
import matplotlib.cm as cm
import matplotlib.pyplot as plt

Numero_Cores = 50
angulo = np.linspace(0, 8 * 2 * np.pi, Numero_Cores)
raio = np.linspace(.5, 1., Numero_Cores)
x = raio * np.cos(angulo)
y = raio * np.sin(angulo)

plt.scatter(x, y, c = angulo, cmap = cm.viridis)
plt.show()
Executando o código acima o gráfico apresentado deve ser igual a esse:

Como funciona o parâmetro cmap

O parametro cmap recebe um mapa de cores. Isso define quais cores serão usadas. E o parâmetro c define o número de cores que será usado.
Nesse exemplo, usamos o mapa de cor viridis. Que é um mapa de cores que vai do roxo ao amarelo. Com o parâmetro c definimos que nosso gráfico vai ter cinquenta cores do mapa de cores viridis. Em todos os mapas de cores o espaçamento entre as cores é uniforme. Assim as cores vão aumentando da cor com o menor valor para a maior (no nosso caso, do roxo para o amarelo).