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

Como organizar a apresentação do meu box-plot?

Olá! Fazendo o projeto final do curso de Estatística com Python parte 1, me deparei com o box-plot de renda por estado brasileiro (UF).

Segue o meu código:

# Selecionando os dados
box_plot_renda_por_UF = sns.boxplot(
     x = 'Renda',
     y = 'UF',
     data = dados.query('Renda < 10000'), 
     orient = 'h')

# Ajustando o tamanho da imagem
box_plot_renda_por_UF.figure.set_size_inches(20, 12)

# Definindo o título do gráfico
box_plot_renda_por_UF.set_title(
    'Box-plot da renda por ESTADOS (UF)',
     fontsize = 20)

# Configurando o eixo x
box_plot_renda_por_UF.set_xlabel('Renda (R$)', fontsize = 16)


# Configurando o eixo y
box_plot_renda_por_UF.set_ylabel('Estados', fontsize = 16, )
box_plot_renda_por_UF.set_yticklabels(
   [valor for valor in uf.values()],
   fontsize = 12)

# Plotar o gráfico
box_plot_renda_por_UF

Gostaria de saber:

1) como faço para organizar o meu gráfico por ordem alfabética dos estados?

2) como faço para organizar o meu gráfico da menor para a maior mediana?

Desde já agradeço... Abraço!

5 respostas

Vinicius, tudo bom? Você pode usar o parâmetro order para organizar seu boxplot.

https://seaborn.pydata.org/generated/seaborn.boxplot.html#seaborn.boxplot

Não tenho certeza sobre as medianas, mas eu faria o cálculo delas, colocaria numa lista e plotaria o gráfico. Sinceramente não sei se é a melhor solução.

Tudo bom Ronald?

Então, dei uma olhada na documentação e vi que esse parâmetro order recebe uma lista. Criei uma lista com os keys do dict uf:

uf = {
    11: 'Rondônia', 
    12: 'Acre', 
    13: 'Amazonas', 
    14: 'Roraima', 
    15: 'Pará', 
    16: 'Amapá', 
    17: 'Tocantins', 
    21: 'Maranhão', 
    22: 'Piauí', 
    23: 'Ceará', 
    24: 'Rio Grande do Norte', 
    25: 'Paraíba', 
    26: 'Pernambuco', 
    27: 'Alagoas', 
    28: 'Sergipe', 
    29: 'Bahia', 
    31: 'Minas Gerais', 
    32: 'Espírito Santo', 
    33: 'Rio de Janeiro', 
    35: 'São Paulo', 
    41: 'Paraná', 
    42: 'Santa Catarina', 
    43: 'Rio Grande do Sul', 
    50: 'Mato Grosso do Sul', 
    51: 'Mato Grosso', 
    52: 'Goiás', 
    53: 'Distrito Federal'
}

e coloquei no parâmetro order. Não deu certo.

Dei um .sort() nessa lista, na tentativa de organizar em ordem alfabética. Mas são números e já estão em ordem crescente. Tentei mesmo assim e não deu certo.

Tentei com os values do mesmo dict uf. Ficou tudo branco.

Dei um .sort() nessa lista também, na tentativa de organizar em ordem alfabética. Não ficou tudo branco, mas o resultado foi o mesmo de antes.

Aí pensei que talvez tenhamos que mexer lá no DataFrame original. Mas esses dados são numéricos. Não vai ficar em ordem alfabética. Não adianta dar um .sort_values(by = ['UF']) em dados. Claro que eu já tentei fazer isso, mesmo sabendo que não daria... (vai que, né...) E não deu mesmo!

Quanto às medianas, a minha ideia era melhorar a visualização desse gráfico. Queria deixar os box-plots com menores medianas em cima e as maiores medianas embaixo. Mas não sei como.

Olá Vinicius,

Tem um detalhe importante a ser considerado, você que está definindo os labels com os nomes dos estados no set_yticklabels, então pode ser que você esteja modificando a ordem corretamente mas apenas os labels continuam sem mudanças, passando a falsa impressão de que não foi ordenado.

# Experimente novamente comentando essa parte apenas como teste
box_plot_renda_por_UF.set_yticklabels(
   [valor for valor in uf.values()],
   fontsize = 12)


Sobre ordenar pela mediana pode ser feito utilizando o order também, você pode agrupar os dados pelo estado e calcular a mediana para então ordenar os estados baseado nisso. Exemplo:

# Obtendo a lista dos estados ordenados pela mediana da renda
mediana_estados = dados.query('Renda < 10000').groupby('UF')['Renda'].median()
mediana_estados_ordenado = list(mediana_estados.sort_values().index)

Obs.: Eu fiz todos esses testes que você mencionou acima e mais um pouco antes de perceber o set_yticklabels que estava "mascarando" o resultado.

Espero ter ajudado, se tiver qualquer dúvida em completar o código é só falar!

solução!

Boa tarde meu povo!

Lucas, a sua dica de como ordenar os estados pela mediana foi crucial pro desenrolar dessa novela que foi o desafio que eu mesmo propus.

Organizei os estados com base nisso, como vc sugeriu, utilizei do parâmetro order que o Ronald sugeriu (obrigado Ronald) e...

Funcionou! Sucesso!!!

Segue o código para quem se interessar...

# Obtendo a lista dos estados ordenados pela mediana da renda
mediana_estados = dados.query('Renda < 10000').groupby('UF')['Renda'].median()
mediana_estados_ordenado = list(mediana_estados.sort_values().index)
# Obtendo uma lista com os nomes dos estados ordenados pela mendiana da renda
# Tive que criar esta lista para poder ordenar os labels junto aos box-plots
nomes_uf_ordenados_por_mediana = []
for nome in mediana_estados_ordenado:
  nomes_uf_ordenados_por_mediana.append(uf[nome])
# Selecionando os dados
box_plot_renda_por_UF = sns.boxplot(
     x = 'Renda',
     y = 'UF',
     #hue = 'Sexo',
     data = dados.query('Renda < 10000'), 
     orient = 'h',
     order = mediana_estados_ordenado)

# Ajustando o tamanho da imagem
box_plot_renda_por_UF.figure.set_size_inches(20, 12)

# Definindo o título do gráfico
box_plot_renda_por_UF.set_title(
    'Box-plot da renda por ESTADOS (UF)',
     fontsize = 20)

# Configurando o eixo x
box_plot_renda_por_UF.set_xlabel('Renda (R$)', fontsize = 16)


# Configurando o eixo y
box_plot_renda_por_UF.set_ylabel('Estados', fontsize = 16, )
box_plot_renda_por_UF.set_yticklabels(
   nomes_uf_ordenados_por_mediana,
   fontsize = 12)

# Plotar o gráfico
box_plot_renda_por_UF

E, no desafio de plotar em ordem alfabética dos nomes dos estados, primeiramente, criei uma lista com o nome dos estados e organizei em ordem alfabética:

# Obtendo a lista dos nome dos estados em ordem alfabética
nomes_uf_ordem_alfabetica = list(uf.values())
nomes_uf_ordem_alfabetica.sort()
nomes_uf_ordem_alfabetica

Essa parte foi tranquilo... E joguei essa lista como parâmetro lá no método .set_yticklabels(). Assim, os labels estão em ordem alfabética, mas os box-plots do gráfico ainda não seguem a mesma ordem.

Eu precisava de uma lista com os códigos dos estados. Mas essa lista deveria estar na mesma ordem dos nomes dos estados (que já estavam em ordem alfabética...)

E aí foi a parte mais difícil para mim, pois não achei na documentação um método que me desse as keys de um dicionário a partir dos valuesdo mesmo.

Botei a cabeça pra torrar uns neurônios e depois de um tempo considerável (3 dias) tentando, bolei uma lógica que fizesse isso para mim... E consegui! (tô felizão por isso! =D)

#Obtenedo uma lista com os códigos dos estados na mesma ordem alfabética do nomes do estados
lista = list(uf.items())
lista_codigos = []

for nome in nomes_uf_ordem_alfabetica:
  for key, value in lista:
    if value == nome:
      lista_codigos.append(key)
lista_codigos

Aí corri pro abraço... Só coloquei essa lista no parâmetro order da função .boxplot() (valeu de novo Ronald)...

# Selecionando os dados
box_plot_renda_por_UF = sns.boxplot(
     x = 'Renda',
     y = 'UF',
     data = dados.query('Renda < 10000'), 
     orient = 'h',
     order = lista_codigos)

# Ajustando o tamanho da imagem
box_plot_renda_por_UF.figure.set_size_inches(20, 12)

# Definindo o título do gráfico
box_plot_renda_por_UF.set_title(
    'Box-plot da renda por ESTADOS (UF)',
     fontsize = 20)

# Configurando o eixo x
box_plot_renda_por_UF.set_xlabel('Renda (R$)', fontsize = 16)


# Configurando o eixo y
box_plot_renda_por_UF.set_ylabel('Estados', fontsize = 16, )
box_plot_renda_por_UF.set_yticklabels(
   nomes_uf_ordem_alfabetica,
   fontsize = 12)

# Plotar o gráfico
box_plot_renda_por_UF

e funcionou!!!

Valeu galera! Ajudou muito!! Mais um desafio concluído!!! Até a próxima...

Boa Vinicius, muito bom saber que deu certo, e valeu por compartilhar a explicação detalhada também de cada passo!

Qualquer dúvida é só vir aqui no fórum que a gente tenta ajudar. Bons estudos!