Solucionado (ver solução)
Solucionado
(ver solução)
3
respostas

Como mudar a cor de um ticklabel específico

Pessoal, bom dia!

Nessa aula de marcação dos limites superiores e inferiores de um eixo, eu quis marcar os valores máximo e mínimo no próprio eixo de temperatura. Deu certo! Eis o código:

fig = plt.figure(figsize = (15,8))
eixo = fig.add_axes([0,0,1,1])
eixo.plot(df['data'], df['temperatura'], color = 'g')
eixo.set_title('Temperatura no momento', fontsize = 25, pad = 20)
eixo.set_xlabel('Data', fontsize=20)
eixo.set_ylabel('Temperatura', fontsize=20)
eixo.legend(['Temperatura'], loc='lower right', fontsize=15)
eixo.grid(True)

# definindo os ticks
eixo.set_yticks([max(df['temperatura']), min(df['temperatura']), *eixo.get_yticks()])


# definindo pontos de máxima e mínima
eixo.axhline(max(df['temperatura']), color = 'k', linestyle='--')
eixo.axhline(min(df['temperatura']), color = 'k', linestyle='--')

Só que eu gostaria de dar alguma diferenciada nesses dois labels. Pensei em colocar uma cor vermelha ou um texto em negrito somente nesses dois, mantendo a formatação dos demais. Procurei na documentação do matplotlib, nos fóruns da internet, mas não encontrei nenhuma solução (cheguei até na classe ticker, mas não consegui compreender mto bem como eu endereçava um label tick específico pra formatá-lo).

Há alguma maneira de eu alterar o formato de um label tick específico (sem alterar todos)?

Obrigado pela ajuda!

3 respostas

Acabei fuçando a classe Text criada pela função get_ymajorticklabels() e consegui chegar no resultado que queria (conforme código abaixo). Mas não tenho certeza se essa é a forma mais fácil e correta (inclusive alterei diretamente variáveis privadas, o que já fere a PEP8). Se houver alguma solução diferente, agradeço por compartilharem.

fig = plt.figure(figsize = (15,8))
eixo = fig.add_axes([0,0,1,1])
eixo.plot(df['data'], df['temperatura'], color = 'g')
eixo.set_title('Temperatura no momento', fontsize = 25, pad = 20)
eixo.set_xlabel('Data', fontsize=20)
eixo.set_ylabel('Temperatura', fontsize=20)
eixo.legend(['Temperatura'], loc='lower right', fontsize=15)
eixo.grid(True)

# definindo os ticks
eixo.set_yticks([max(df['temperatura']), min(df['temperatura']), *eixo.get_yticks()])
print(eixo.get_ymajorticklabels()[0].__dict__)  # visualizar as variáveis dentro da classe Text
eixo.get_ymajorticklabels()[0]._color = 'red'
eixo.get_ymajorticklabels()[1]._color = 'red'
print(eixo.get_ymajorticklabels()[1]._fontproperties.__dict__)  # visualizar as variáveis de fontproperties
eixo.get_ymajorticklabels()[0]._fontproperties._weight = 'bold'
eixo.get_ymajorticklabels()[1]._fontproperties._weight = 'bold'


# definindo pontos de máxima e mínima
eixo.axhline(max(df['temperatura']), color = 'k', linestyle='--')
eixo.axhline(min(df['temperatura']), color = 'k', linestyle='--')
solução!

Oi, Fabio! Como você está?

A sua solução é uma opção válida, sim. No entanto, caso você queira deixar o seu código ainda mais "pythônico" e nos padrões propostos pela PEP8, trago aqui uma alternativa interessante: nós podemos percorrer os rótulos de tick e customizar apenas aqueles que se referem às temperaturas extremas (máxima e mínima).

Isso pode ser feito a partir da criação de um laço de repetição, o qual irá passar por todos os rótulos de tick do eixo Y (a partir do método get_ticklabels).

Para cada valor encontrado (representado como um float, ou seja, um número de ponto flutuante), verificamos se ele é igual a max(df['temperatura']) ou min(df['temperatura']), nossos valores extremos:

# Percorrendo os rótulos de tick e aplicando formatação específica
for tick_label in eixo.yaxis.get_ticklabels():
    tick_value = float(tick_label.get_text())
    if tick_value == max(df['temperatura']) or tick_value == min(df['temperatura']):
        tick_label.set_color('red')  # Define a cor vermelha para os rótulos de tick desejados
        tick_label.set_weight('bold')  # Define o texto em negrito para os rótulos de tick desejados

Se a condição for verdadeira, utilizamos set_color() e set_weight() para alterar a cor para vermelho e o peso da fonte para negrito, alcançando, assim, o resultado esperado!

Fabio, caso queira visualizar o código completo, aqui está:

fig = plt.figure(figsize = (15,8))
eixo = fig.add_axes([0,0,1,1])
eixo.plot(df['data'], df['temperatura'], color = 'g')
eixo.set_title('Temperatura no momento', fontsize = 25, pad = 20)
eixo.set_xlabel('Data', fontsize=20)
eixo.set_ylabel('Temperatura', fontsize=20)
eixo.legend(['Temperatura'], loc='lower right', fontsize=15)
eixo.grid(True)

# definindo os ticks
eixo.set_yticks([max(df['temperatura']), min(df['temperatura']), *eixo.get_yticks()])

# definindo pontos de máxima e mínima
eixo.axhline(max(df['temperatura']), color = 'k', linestyle='--')
eixo.axhline(min(df['temperatura']), color = 'k', linestyle='--')

# Percorrendo os rótulos de tick e aplicando formatação específica
for tick_label in eixo.yaxis.get_ticklabels():
    tick_value = float(tick_label.get_text())
    if tick_value == max(df['temperatura']) or tick_value == min(df['temperatura']):
        tick_label.set_color('red')  # Define a cor vermelha para os rótulos de tick desejados
        tick_label.set_weight('bold')  # Define o texto em negrito para os rótulos de tick desejados

Após executar essa sequência de comandos, chegaremos no seguinte gráfico:

Gráfico de temperatura ao longo dos anos.

Espero que tenha gostado da minha sugestão e sinta-se à vontade para adaptá-la, Fabio! Caso apareçam novas dúvidas, fico à disposição.

Um abraço!

Caso este post tenha lhe ajudado, por favor, marcar como solucionado ✓. Bons Estudos!

Muitíssimo obrigado pela ajuda, Andrieli.

Explicação claríssima!