#@title
javascript_functions = {False: "hide()", True: "show()"}
button_descriptions = {False: "Show code", True: "Hide code"}
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from PIL import Image
from wordcloud import WordCloud, STOPWORDS, ImageColorGenerator
import nltk
nltk.download('punkt')
nltk.download('stopwords')
stopwords = nltk.corpus.stopwords.words('portuguese')
[nltk_data] Downloading package punkt to /root/nltk_data... [nltk_data] Package punkt is already up-to-date! [nltk_data] Downloading package stopwords to /root/nltk_data... [nltk_data] Package stopwords is already up-to-date!
#@title
dados = pd.read_csv('/content/drive/MyDrive/DATA/pedidos-recursos-features-process.csv')
#@title
def clear_values_regex(df):
df = df.replace(r'\r\n\r\n',' ', regex=True)
df = df.replace(r'\r\n',' ', regex=True)
df = df.replace(r'\r \r',' ', regex=True)
return df
#@title
dados = clear_values_regex(dados)
O conjunto de dados utilizado é o resultado de uma rotulagem manual de 10 mil pedidos, divididos entre as categorias: Atendido, Parcialmente Atendido, Não Atendido e Não classificado.
Para cada pedido temos as informações referente ao órgão que recebeu a solicitação, o assunto, uma verificação se possui anexo atrelado ao pedido, a resposta fornecida pelo órgão, se é de nível Federativo, Estadual ou Municipal.
Para conhecer como é a distribuição de cada uma dessas variáveis iremos realizar um processo de visualização desses dados para ter um conhecimento de como é a base, nosso objetivo é analisa às informações referente as características dos pedidos e após esse processo analisar as mensagens dos pedidos.
Para uma análise iremos observar como está as distribuições na base em relação a cada uma das características comentadas anteriormente, considerando que no estudo anterior de origem essa base algumas informações já foram plotas e identificadas iremos filtrar para informações especificas de modelagem, portanto, iremos analisar como está a distribuição da base em relação às informações: distribuição de classes de atendimento, ter ou não anexo e área temática.
#@title
dados['atendimento_resposta'].value_counts().sort_values().plot(kind = 'barh')
<matplotlib.axes._subplots.AxesSubplot at 0x7fcdc201f310>
Observamos que a classe de pedidos atendidos é bem superior as demais classes, em números temos Atendidos com 4702, Não Atendidos 2637, Não Classificado 1820 e Parcialmente Atendido 1114. Um ponto importante para se considerar é que os não classificados não tende a contribuir com nossa análise e modelagem, portanto, iremos realizar a filtragem desses dados para podermos trabalhar apenas com as classes de pedidos que obtiveram uma resposta e uma classificação ao seu atendimento.
#@title
dados = dados[dados['atendimento_resposta'] != 'Não Classificado']
dados.groupby(['area_tematica', 'atendimento_resposta']).size().unstack(level=1).plot(kind = 'barh',
title='Distribuição das Areas Tematica dos pedidos',figsize=(12, 7))
<matplotlib.axes._subplots.AxesSubplot at 0x7fcdc2505490>
Observamos que às áreas mais comuns é controle social e atividade fim, em relação as demais observamos um comportamento próximo à distribuição geral considerando que os pedidos atendidos tem uma maior distribuição na base, porém, para Processos observamos um comportamento atípico dos demais onde os pedidos dessa área tem uma distribuição maior em relação a não atendidos.
Para essa analise consideramos que o anexo pode está presente tanto no pedido quanto na resposta do órgão a esse pedido, portanto iremos analisar às duas situações.
dados.groupby(['possui_anexo_no_pedido', 'atendimento_resposta']).size().unstack(level=1).plot(kind = 'barh',
title='Distribuição da presença de Anexo no Pedido',figsize=(12, 7))
<matplotlib.axes._subplots.AxesSubplot at 0x7fcdc20037d0>
Observamos que pouco os pedidos que possui um anexo, nos mostrando ser difícil o requerente enviar algum anexo para o órgão solicitante.
dados.groupby(['possui_anexo_na_resposta', 'atendimento_resposta']).size().unstack(level=1).plot(kind = 'barh',
title='Distribuição da presença de Anexo na Resposta',figsize=(12, 7))
<matplotlib.axes._subplots.AxesSubplot at 0x7fcdc1aaa9d0>
Observamos que as respostas possuem um pouco mais de anexos em relação aos pedidos e observamos que quando tem anexado é provável que o pedido tenha sido atendido.
Para analisar melhor como é os dados em relação ao texto presente nos pedidos e suas respectivas resposta iremos realizar uma análise geral de como está essas distribuições, observar as palavras mais frequentes de cada categoria.
avascript_functions = {False: "hide()", True: "show()"}
button_descriptions = {False: "Show code", True: "Hide code"}
# concatenar as palavras
all_summary = " ".join(s for s in dados[dados['atendimento_resposta'] == 'Atendido']['conteudo_pedido'])
# gerar uma wordcloud
wordcloud = WordCloud(stopwords=stopwords,
background_color="black",
width=1600, height=800).generate(all_summary)
# mostrar a imagem final
fig, ax = plt.subplots(figsize=(10,6))
ax.imshow(wordcloud, interpolation='bilinear')
ax.set_axis_off()
plt.imshow(wordcloud);
Observamos que em maioria as palavras mais frequentes remetem a solicitação de informações, algo que esperamos considerando as circunstâncias dos dados.
# concatenar as palavras
all_summary = " ".join(s for s in dados[dados['atendimento_resposta'] == 'Atendido']['conteudo_resposta'])
# gerar uma wordcloud
wordcloud = WordCloud(stopwords=stopwords,
background_color="black",
width=1600, height=800).generate(all_summary)
# mostrar a imagem final
fig, ax = plt.subplots(figsize=(10,6))
ax.imshow(wordcloud, interpolation='bilinear')
ax.set_axis_off()
plt.imshow(wordcloud);
Observamos ser muito comum os órgãos responderem com algum link de URL que possa fornece as informações ao solicitante, no mais temos um formalismo para resposta algo que também é esperado.
# concatenar as palavras
all_summary = " ".join(s for s in dados[dados['atendimento_resposta'] == 'Parcialmente Atendido']['conteudo_pedido'])
# gerar uma wordcloud
wordcloud = WordCloud(stopwords=stopwords,
background_color="black",
width=1600, height=800).generate(all_summary)
# mostrar a imagem final
fig, ax = plt.subplots(figsize=(10,6))
ax.imshow(wordcloud, interpolation='bilinear')
ax.set_axis_off()
plt.imshow(wordcloud);
Além do que já observamos nos pedidos atendidos, temos a presença de Ano, Processo como algo bem frequente, isso pode nos dar uma visão que esses pedidos podem trazer a solicitação dessas informações em sua maioria.
# concatenar as palavras
all_summary = " ".join(s for s in dados[dados['atendimento_resposta'] == 'Parcialmente Atendido']['conteudo_resposta'])
# gerar uma wordcloud
wordcloud = WordCloud(stopwords=stopwords,
background_color="black",
width=1600, height=800).generate(all_summary)
# mostrar a imagem final
fig, ax = plt.subplots(figsize=(10,6))
ax.imshow(wordcloud, interpolation='bilinear')
ax.set_axis_off()
plt.imshow(wordcloud);
A palavra processo também é bastante frequente nas respostas dos órgãos, isso pode ser entendido que órgão remete a palavra principal da solicitação, também observamos a frequência de URL nas respostas.
# concatenar as palavras
all_summary = " ".join(s for s in dados[dados['atendimento_resposta'] == 'Não Atendido']['conteudo_pedido'])
# gerar uma wordcloud
wordcloud = WordCloud(stopwords=stopwords,
background_color="black",
width=1600, height=800).generate(all_summary)
# mostrar a imagem final
fig, ax = plt.subplots(figsize=(10,6))
ax.imshow(wordcloud, interpolation='bilinear')
ax.set_axis_off()
plt.imshow(wordcloud);
Observamos que os pedidos seguem a característica das demais classes.
Antes de realizar a visualização vamos realizar uma substituição para os casos NaN (13 no total) que seria quando o órgão não respondeu à solicitação ser substituído por uma ‘string’ vazia.
dados['conteudo_resposta'] = dados['conteudo_resposta'].fillna('')
#@title
# concatenar as palavras
all_summary = " ".join(s for s in dados[dados['atendimento_resposta'] == 'Não Atendido']['conteudo_resposta'])
# gerar uma wordcloud
wordcloud = WordCloud(stopwords=stopwords,
background_color="black",
width=1600, height=800).generate(all_summary)
# mostrar a imagem final
fig, ax = plt.subplots(figsize=(10,6))
ax.imshow(wordcloud, interpolation='bilinear')
ax.set_axis_off()
plt.imshow(wordcloud);
Observamos que para esses casos é bem comum o órgão comunicar que não pode repassar determinada informação por conta da lei de acesso à informação.