5
respostas

Substituir pontos e virgulas em um DataFrame

Eu estou com os dados no formato abaixo com o type(string). Para plotar o gráfico descobri que tenho que remover as virgulas. Eu consegui transformar para float e criar o gráfico, mas estou achando esse código ruim. Há alguma forma de melhorar o código abaixo? Alguém pode ajudar?

                                                      dotacao                                  empenhada

Programa Governo2217 3.115.753.741,00 1.585.704.785,37

Código utilizado(funcionou) orcamento['dotacao'] = orcamento['dotacao'].str.replace( '.', '').str.replace(',','.').astype(float) orcamento['empenhada'] = orcamento['empenhada'].str.replace( '.', '').str.replace(',','.').astype(float)

5 respostas

Oi Wilson! Tudo bom com você? Espero que sim!

Essa forma de tratamento utilizada é muito boa, você mandou muito bem solucionando seu problema assim!

Existe uma outra forma que é mais direta de tratar esses dados que definindo parâmetros logo na leitura do DataFrame. Essa opção eu irei desenvolver considerando que você está lendo um arquivo csv, tudo bem? Se for um outro tipo de leitura de arquivo, você pode adaptar esse exemplo à sua realidade, sem problemas ;-)

O método read_csv bem como outros métodos de leitura de arquivo do Pandas vem com parâmetros que facilitam a coleta dos dados adaptando-os a realidade da região que os dados foram construídos. Para o caso de existir separação de milhar com pontos e casas decimais com vírgula, o que é algo um pouco fora do comum em algumas regiões e banco de dados, o Pandas trouxe a opção de definir os parâmetros thousands, decimal e dtype logo no método de leitura.

O parâmetro thousands permite que seja definido qual o separador das casas de milhar, decimal permite definir o separador das casas decimais e o dtype permite que possamos definir o tipo das variáveis presentes nas colunas do nosso banco de dados. Então, atribuindo o ponto a thousands, a vírgula a decimal e float64 como o tipo da colunas 'dotacao' e 'empenhada', teremos os dados numéricos, da forma que precisamos para trabalhar com eles, segue abaixo o código dessa aplicação:

# a biblioteca numpy é para facilitar na atribuição dos valores como float
import numpy as np 
import pandas as pd

orcamento = pd.read_csv('orcamento.csv', thousands = '.', decimal = ',', dtype = {'dotacao':np.float64,'empenhada': np.float64})
orcamento

O resultado obtido pode ser observado abaixo:

dotacaoempenhada
3115753741.01585704785.37

Eu espero ter te ajudado! Se surgir outra dúvida estarei à disposição.

Bons estudos!

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

Boa tarde!

Meu arquivo inicial está muito sujo. Então, eu não consigo aplicar esse código diretamente:

execucao  = pd.read_csv('orcamento.csv', thousands = '.', decimal = ',', dtype = {'dotacao':np.float64,'empenhada': np.float64})

Eu fiz uma limpeza para deixar o DataFrame da seguinte forma:

Acao Dotacao Destaque Despesa_Empenhada Despesa_Paga 2 0181 6.790.257,00 0 6.652.367,66 6.194.348,98 3 09HB 4.131.628,00 0 3.901.331,22 3.901.331,22 4 2000 10.612.316,00 0 7.357.362,33 5.678.531,96 5 2004 442.730,00 0 436.857,15 399.344,52 6 20TP 26.414.336,00 0 26.269.230,19 23.794.336,82 7 212B 1.384.276,00 0 1.244.990,49 1.125.002,72 8 216H 172.745,00 0 167.988,33 153.945,00 9 0005 585.725,00 584.725,00 0 0 10 00S6 1.000,00 0 0 0 11 20WQ 1.582.212,00 399.945,00 1.182.211,00 0 12 214S 1.324.818,00 350.000,00 969.637,30 274.817,30 13 4640 0,00 0 0 0 14 7K66 13.280.138,00 0 13.280.138,00 0 15 8340 1.892.098,00 1.221.663,67 0 0 16 8917 0,00 0 0 0

Dessa forma, eu ainda não consigo gerar o gráfico pelo mesmo problema. Tem como eu aplicar dtype = {'dotacao':np.float64,'empenhada': np.float64}) nesse dataframe limpo. Não estou conseguindo encontrar uma solução. Para fazer essa conversão, estou fazendo execucao.to_csv('xxxx/yyyy.csv) e em seguida lendo novamente o arquivo

pd.read_csv('xxxx/yyyy', dtype = {'Dotacao':np.float64,'Destaque':np.float64, 'Despesa_Empenhada':np.float64, 'Despesa_Paga':np.float64}, thousands='.', decimal=",")

Assim, funciona , mas gostaria de fazer isso sem precisar gerar outro arquivo e carregar outra vez.

Oi Wilson! Boa tarde!

Como você está lidando com um DataFrame que precisa ser "limpo" ou pré-processado, infelizmente não tem uma forma bem direta, como é com o read_csv, de conseguir o que você deseja lidando com um DataFrame :/

Mesmo assim, com esses dados que você apresentou agora, é possível transformá-los em numéricos com duas a três linhas de comando, não é tão direto mas é eficiente. Para isso podemos utilizar do comando apply com a função lamba:

colunas = ['Dotacao',"Destaque",'Despesa_Empenhada','Despesa_Paga']

execucao = execucao.apply(lambda x: x.str.replace('.', '')).apply(lambda x: x.str.replace(',', '.'))
execucao = execucao[colunas].astype(np.float64)

execucao.head(3)

Veja que foram selecionadas as colunas que deveriam se tornar valores float e depois foi dado inicio ao processo de substituição dos pontos e virgulas por todo o DataFrame com apply e por fim, a troca do tipo de variável com astype nas colunas especificadas. O resultado obtido pode ser visto abaixo:

AcaoDotacaoDestaqueDespesa_EmpenhadaDespesa_Paga
001816790257.0006652367.666194348.98
109HB4131628.0003901331.223901331.22
2200010612316.0007357362.335678531.96

Outra opção de uso do astype é definido os tipos das colunas por meio de um dicionário que você pode definir outros tipos paras as colunas especificadas, da mesma forma que o utilizado no dtype:

execucao = execucao.astype({'Dotacao':np.float64,"Destaque":np.int64,'Despesa_Empenhada':np.float64,'Despesa_Paga':np.float64})

Espero que desse modo tenha ficado melhor de ser aplicado!

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

Boa tarde!

Mirla, seguindo o exemplo acima, eu plotei um gráfico de barras em que o eixo x='Acao'. Esse gráfico faz justamente o que pretendo. Ele compara com 4 barras as 4 colunas por Ação. Pesquisando eu encontrei alguns gráficos que foram divididos para melhorar a visualização. Porém, ainda, não consegui fazer isso. É possível em vez de um gráfico com todas as ações , dividi-lo em vários gráficos(lado a lado). Assim, cada gráfico teria seria uma ação.

Oi Wilson! Boa tarde!

Você busca então formar vários subplots, dentro de um mesmo plot, correto? Se sim, isso é possível sim! Para isso precisamos utilizar das bibliotecas seaborn e matplotlib para criar a figura, construir a configuração de subplots e montar os plot em barras para cada espaço.

Após importar as bibliotecas seaborn e matplotlib, definimos a quantidade de linhas e colunas que a grade de subplots terá com o comando plt.subplots(n_linhas,n_colunas). O número de linhas e coluna cria espaços para a inserção dos plots na figura, como nesse exemplo apenas utilizarei as três primeiras linhas dos seus dados, foi definida uma grade apenas com 1 linha e 3 colunas, mas você pode ajustar a quantidade de linhas e colunas da forma como você achar mais interessante para seus dados:

import seaborn as sns
import matplotlib.pyplot as plt

fig, axs = plt.subplots(1,3)

O método plt.subplots(1,3) irá retornar dois objetos, sendo o primeiro o objeto da figura e o segundo os objetos referentes aos espaços de plots criados. Mais informações sobre esse método você pode obter na documentação do matplotlib.

Depois, com um laço for podemos ajustar as plotagens de cada ação, de forma que utilizamos o seaborn para construir um gráfico em barras e nele definimos nossos parâmetros x como as 4 colunas que você citou ('Dotacao', 'Destaque', 'Despesa_Empenhada', 'Despesa_Paga'), y como o dado das ações e um parâmetro definido como ax que especificará a posição de cada subplot.

n=0
for i in range(3): # são 3 espaços na figura para subplots
    sns.barplot(ax=axs[i], x = ['Dotacao', 'Destaque', 'Despesa_Empenhada', 'Despesa_Paga'],y=dados[dados['Acao']==dados['Acao'][n]].iloc[0][1:])
    axs[i].set_title(dados['Acao'][n]) # cria um título para cada subplot
    n+=1
plt.show()

Note que a variável n é um contador que vai passar pelos valores de cada ação e permitir que ela seja a selecionada para criar gráfico. A saída que obtive foi a seguinte:

Alt text: Conjunto de três gráficos em barras dispostos lado a lado em uma mesma linha. Os três gráficos apresentam 4 barras em suas estruturas, a barra mais próxima do eixo y é da cor azul e tem a legenda de Dotação a sua esquerda existe um espaço para uma barra de valor zero que não é mostrada e tem a legenda Destaque, a próxima é da cor verde e tem a legenda de Despesa_Empenhada, e a última é da cor vermelha e tem a legenda de Despesa_Paga. O primeiro gráfico tem título 0181,  segundo gráfico tem título 09HB e o terceiro título 2000.  Os valores de cada barra são equivalentes aos valores dos dados utilizados.

Por fim, para entender melhor sobre o que foi feito, sugiro assistir os primeiros 8 minutos do vídeo Subplots: Criando vários gráficos ao mesmo tempo com Matplotlib que irá explicar o que são subplots e a diferença entre figura e axis e também ler o artigo Creating multiple subplots using plt.subplots (em português, Criando múltiplos subplots usando plt.subplots ) disponibilizado pela biblioteca do matplotlib. OBS: Infelizmente os artigos da biblioteca matplotlib estão em inglês, então, caso tenha dificuldade em relação a este idioma, indico que tente utilizar o tradutor do navegador, para conseguir efetuar a leitura em português, mas qualquer dúvida ou dificuldade estarei à disposição.

E caso tenha alguma outra dúvida fora desse contexto sugiro também abrir outro tópico no fórum para que assim outros alunos e alunas possam tirar dúvidas semelhantes a sua mais facilmente ^^ Mesmo assim, se o problema persistir pode comunicar que estarei à disposição! Bons estudos.