<jupyter_start><jupyter_text>Módulo 2: Aula 4 Novo tipo de dados: *Counter* e geração de arquivos CSV  Retomando o programa anterior de contagem de total de habitantes:<jupyter_code>import csv

populacao = 0
arquivo = open('brasil.csv', encoding='utf8')
for registro in csv.DictReader(arquivo):
    populacao += int(registro['habitantes'])
print(f'Total de habitantes no Brasil = {populacao}')<jupyter_output>Total de habitantes no Brasil = 190755799<jupyter_text>Problema:- E se quiséssemos contar para cada estado?    - Usaríamos 27 variáveis-contador?    - Dicionários!        - Chave = estado        - Valor = contador  A biblioteca *collections* torna mais fácil criar contadoresDentro de collections há um tipo novo de dados chamado *Counter*, que é como se fosse um dicionário "melhorado".O Counter também é composto por pares (chave, valor), a diferença é que se pode incrementar diretamente as chaves.Exemplo:<jupyter_code>import collections

contador = collections.Counter()
contador['PR'] += 1000 # isso incrementa a quantidade de habitantes do Paraná em 1000
contador['RJ'] += 10000 # incrementa habitantes do RJ em 10000
contador['PR'] += 500 # é possível incrementar várias vezes a mesma chave
print(contador) # imprime o somatório da variável contador<jupyter_output>Counter({'RJ': 10000, 'PR': 1500})<jupyter_text>Podemos alterar o programa inicial para usar o collections.Counter de forma que a chave do contador será justamente o estado do registro:<jupyter_code>import csv
import collections

populacao = collections.Counter()
arquivo = open('brasil.csv', encoding='utf8')
for registro in csv.DictReader(arquivo):
    populacao[registro['estado']] += int(registro['habitantes'])
print(populacao)<jupyter_output>Counter({'SP': 41262199, 'MG': 19597330, 'RJ': 15989929, 'BA': 14016906, 'RS': 10693929, 'PR': 10444526, 'PE': 8796448, 'CE': 8452381, 'PA': 7581051, 'MA': 6574789, 'SC': 6248436, 'GO': 6003788, 'PB': 3766528, 'ES': 3514952, 'AM': 3483985, 'RN': 3168027, 'AL': 3120494, 'PI': 3118360, 'MT': 3035122, 'DF': 2570160, 'MS': 2449024, 'SE': 2068017, 'RO': 1562409, 'TO': 1383445, 'AC': 733559, 'AP': 669526, 'RR': 450479})<jupyter_text>O programa acima imprimirá o resultado como um contador, um dado do tipo Counter. Para transformá-lo em uma lista, há uma função pronta chamada *most_common*:<jupyter_code>import csv
import collections

populacao = collections.Counter()
arquivo = open('brasil.csv', encoding='utf8')
for registro in csv.DictReader(arquivo):
    populacao[registro['estado']] += int(registro['habitantes'])
print(populacao.most_common())<jupyter_output>[('SP', 41262199), ('MG', 19597330), ('RJ', 15989929), ('BA', 14016906), ('RS', 10693929), ('PR', 10444526), ('PE', 8796448), ('CE', 8452381), ('PA', 7581051), ('MA', 6574789), ('SC', 6248436), ('GO', 6003788), ('PB', 3766528), ('ES', 3514952), ('AM', 3483985), ('RN', 3168027), ('AL', 3120494), ('PI', 3118360), ('MT', 3035122), ('DF', 2570160), ('MS', 2449024), ('SE', 2068017), ('RO', 1562409), ('TO', 1383445), ('AC', 733559), ('AP', 669526), ('RR', 450479)]<jupyter_text>Agora, na saída do print temos uma lista (entre colchetes []) e cada elemento dela, um par ('estado', habitantes), é uma *tupla*, um outro tipo de dados em Python que tem o comportamento parecido com o de uma lista. É possível, então utilizar um outro *for* para percorrer essa sequência, considerando que cada elemento da lista é composto por dois elementos:<jupyter_code>import csv
import collections

arquivo = open('brasil.csv', encoding='utf8') # abrindo o arquivo para leitura
populacao = collections.Counter() # criando um contador vazio

# fazendo a contagem a partir do csv (análise de dados)
for registro in csv.DictReader(arquivo):
    populacao[registro['estado']] += int(registro['habitantes'])

# exibição para o usuário da contagem realizada (visualização da análise)
for estado, habitantes in populacao.most_common():
    print(f'O estado {estado} tem {habitantes} habitantes.')<jupyter_output>O estado SP tem 41262199 habitantes
O estado MG tem 19597330 habitantes
O estado RJ tem 15989929 habitantes
O estado BA tem 14016906 habitantes
O estado RS tem 10693929 habitantes
O estado PR tem 10444526 habitantes
O estado PE tem 8796448 habitantes
O estado CE tem 8452381 habitantes
O estado PA tem 7581051 habitantes
O estado MA tem 6574789 habitantes
O estado SC tem 6248436 habitantes
O estado GO tem 6003788 habitantes
O estado PB tem 3766528 habitantes
O estado ES tem 3514952 habitantes
O estado AM tem 3483985 habitantes
O estado RN tem 3168027 habitantes
O estado AL tem 3120494 habitantes
O estado PI tem 3118360 habitantes
O estado MT tem 3035122 habitantes
O estado DF tem 2570160 habitantes
O estado MS tem 2449024 habitantes
O estado SE tem 2068017 habitantes
O estado RO tem 1562409 habitantes
O estado TO tem 1383445 habitantes
O estado AC tem 733559 habitantes
O estado AP tem 669526 habitantes
O estado RR tem 450479 habitantes<jupyter_text>O *for* vai percorrer a sequência *populacao.most_common* e, para cada elemento dela, vai separar estado e número de habitantes. O resultado obtido será um estado por linha. Exercício:- Mostrar apenas o top 5    - função(parâmetro)<jupyter_code>import csv
import collections

arquivo = open('brasil.csv', encoding='utf8')
populacao = collections.Counter()

for registro in csv.DictReader(arquivo):
    populacao[registro['estado']] += int(registro['habitantes'])

for estado, habitantes in populacao.most_common(5): # função recebe parâmetro que a limita a 5 resultados
    print(f'O estado {estado} tem {habitantes} habitantes.')<jupyter_output><empty_output><jupyter_text>Gerando um CSV para apresentar adequadamente um resultado extenso demais para simplesmente imprimir na tela Utilizar a função do módulo csv *csv.writer*<jupyter_code>import csv

arquivo = open('saida.csv', mode='w', encoding='utf8')
escritor = csv.writer(arquivo, lineterminator='\n')
escritor.writerow(['linha1 coluna1', 'linha1 coluna2'])
escritor.writerow(['linha2 coluna1', 'linha2 coluna2'])
escritor.writerow(['linha3 coluna1', 'linha3 coluna2'])
arquivo.close()<jupyter_output><empty_output><jupyter_text>É preciso passar para a função *writer* um arquivo e podem-se passar opções. Ela vai devolver uma variável *escritor*, que vamos usar para escrever os dados no csv, linha por linha.- A variável arquivo é criada também com a função *open*, porém é necessário fornecer como parâmetro o nome do arquivo que neste caso ainda não existe, será criado pela função.    - Também é preciso passar para o Python que o modo do arquivo é *write* (w), informando que estamos escrevendo um arquivo. Caso contrário, por padrão, ele seria aberto como 'somente leitura'.    - Por fim, passar o parâmetro encoding, neste caso 'utf8'.- Outro parâmetro passado para a função *writer* é o *lineterminator*, a quebra de linha, que será a string \n, para garantir que o arquivo seja aberto da mesma maneira em diferentes sistemas operacionais. A função *writerow* escreve os registros do arquivo que será gerado, e é preciso passar para essa função uma lista (que será no arquivo final uma linha), da qual cada elemento representará uma coluna.- No exemplo acima temos uma tabela de 3 linhas e 2 colunas. Por fim, é preciso fechar o arquivo com a função *close*, que salva os dados na memória permanente do computador.- O arquivo é aberto no início do código e fechado no final. Juntando esse código com o programa criado anteriormente para contar os habitantes de cada estado, podemos gerar um novo arquivo CSV com os dados organizados:<jupyter_code>import csv
import collections

# fazendo a contagem a partir do csv (análise de dados)
arquivo = open('brasil.csv', encoding='utf8')
populacao = collections.Counter()
for registro in csv.DictReader(arquivo):
    populacao[registro['estado']] += int(registro['habitantes'])

# criando o arquivo CSV com o resultado
arquivo_saida = open('estados.csv', mode='w', encoding='utf8')
escritor = csv.writer(arquivo_saida, lineterminator='\n')
escritor.writerow(['estado', 'habitantes']) # cabeçalho da tabela
for estado, habitantes in populacao.most_common():
    escritor.writerow([estado, habitantes])
arquivo_saida.close()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.10374253321955382, 'fraction_numerical': 0.07875167621601853, 'mean_word_length': 5.813953488372093, 'pattern_counts': {'":': 0, '<': 28, '<?xml version=': 0, '>': 28, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '8', 'dir': 'jupyter-structured-clean-dedup', 'id': '84691', 'license': 'Unlicense', 'n_tokens_mistral': 3241, 'n_tokens_neox': 2817, 'n_words': 1000, 'path': 'Modulo2/Notebooks/Modulo2Aula4.ipynb', 'repo_name': 'letuche/python-jornas', 'size': '8203'}