0% acharam este documento útil (0 voto)
20 visualizações129 páginas

Apostila Python

A apostila 'Introdução a Python para Ciência de Dados' oferece uma visão abrangente sobre conceitos fundamentais de Python e sua aplicação na ciência de dados. O documento abrange tópicos como instalação de IDEs, programação orientada a objetos, funções, classes, módulos, e boas práticas de programação. É uma ferramenta educativa destinada a iniciantes e intermediários que desejam aprender a programar em Python para análise de dados.

Enviado por

Saulo Tiburtius
Direitos autorais
© All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd
0% acharam este documento útil (0 voto)
20 visualizações129 páginas

Apostila Python

A apostila 'Introdução a Python para Ciência de Dados' oferece uma visão abrangente sobre conceitos fundamentais de Python e sua aplicação na ciência de dados. O documento abrange tópicos como instalação de IDEs, programação orientada a objetos, funções, classes, módulos, e boas práticas de programação. É uma ferramenta educativa destinada a iniciantes e intermediários que desejam aprender a programar em Python para análise de dados.

Enviado por

Saulo Tiburtius
Direitos autorais
© All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd

Apostila: Introdução a Python para

Ciência de Dados

Versão 1.0

Anderson Ara
José Jairo de Santana e Silva
Leonardo Melo

Departamento de Estatística e Ciência de Dados - Setor de Ciências


Exatas

Outubro de 2025
2
Sumário

1 Introdução 11
1.1 O que é Ciência de Dados? . . . . . . . . . . . . . . . . . . . . 11
1.2 O que é Python? . . . . . . . . . . . . . . . . . . . . . . . . . 14
1.3 Instalação e IDEs . . . . . . . . . . . . . . . . . . . . . . . . . 18
1.3.1 PyCharm . . . . . . . . . . . . . . . . . . . . . . . . . 18
1.3.2 Spyder . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
1.3.3 Visual Studio Code (VS Code) . . . . . . . . . . . . . 21
1.3.4 Jupyter Notebook / Google Colab . . . . . . . . . . . . 21
1.3.5 RStudio / Positron . . . . . . . . . . . . . . . . . . . . 24
1.4 Programação Orientada a Objetos . . . . . . . . . . . . . . . . 25
1.5 Estrutura dos códigos . . . . . . . . . . . . . . . . . . . . . . . 26

2 Conceitos Básicos 27
2.1 Variáveis e seus tipos . . . . . . . . . . . . . . . . . . . . . . . 27
2.2 Operações Simples e Tipos de Operadores . . . . . . . . . . . 29
2.3 Funções, Métodos e Atributos . . . . . . . . . . . . . . . . . . 31
2.4 Indexação e Fatiamento . . . . . . . . . . . . . . . . . . . . . 35
2.5 Strings, Placeholders e f-strings . . . . . . . . . . . . . . . . . 36
2.6 Estruturas de Dados . . . . . . . . . . . . . . . . . . . . . . . 37
2.6.1 Listas . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
2.6.2 Tuplas . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
2.6.3 Dicionários . . . . . . . . . . . . . . . . . . . . . . . . 44
2.7 Controle de Fluxo (if, while, for) . . . . . . . . . . . . . . . . . 46
2.7.1 If/Else . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
2.7.2 While . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
2.7.3 For . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
2.7.4 List Comprehension . . . . . . . . . . . . . . . . . . . . 52
2.7.5 Operadores Lógicos e de Atribuição . . . . . . . . . . . 52
2.8 Juntando tudo . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
2.9 Desafio: Operações com listas . . . . . . . . . . . . . . . . . . 55

3
4 SUMÁRIO

3 Funções e Classes 57
3.1 Range . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
3.2 Map . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
3.3 Filter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
3.4 Zip . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
3.5 Enumerate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
3.6 Criando sua própria função . . . . . . . . . . . . . . . . . . . 62
3.7 Expressão Lambda . . . . . . . . . . . . . . . . . . . . . . . . 65
3.8 Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
3.8.1 Herança e Polimorfismo . . . . . . . . . . . . . . . . . 68
3.8.2 Outras Características . . . . . . . . . . . . . . . . . . 70
3.9 Desafio: Criando uma nova classe . . . . . . . . . . . . . . . . 70

4 Módulos, Pacotes e Bibliotecas 73


4.1 Trabalhando com Componentes Externos . . . . . . . . . . . . 74
4.2 Math e Statistics . . . . . . . . . . . . . . . . . . . . . . . . . 75
4.3 Functools . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
4.3.1 Função Reduce . . . . . . . . . . . . . . . . . . . . . . 77
4.3.2 Função Partial . . . . . . . . . . . . . . . . . . . . . . 78
4.3.3 Função cmp_to_key . . . . . . . . . . . . . . . . . . . 78
4.4 NumPy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
4.4.1 Operações com Arrays . . . . . . . . . . . . . . . . . . 81
4.4.2 Fatiamento . . . . . . . . . . . . . . . . . . . . . . . . 82
4.4.3 Operações Matriciais . . . . . . . . . . . . . . . . . . . 83
4.4.4 Manipulando Arrays . . . . . . . . . . . . . . . . . . . 85
4.4.5 Funções Matemáticas . . . . . . . . . . . . . . . . . . . 86
4.4.6 Além do NumPy . . . . . . . . . . . . . . . . . . . . . 88
4.5 Pandas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
4.5.1 Dataframe - Conceitos Iniciais . . . . . . . . . . . . . . 88
4.5.2 Criação e Atributos de um DataFrame . . . . . . . . . 90
4.5.3 Indexação . . . . . . . . . . . . . . . . . . . . . . . . . 92
4.5.4 Manipulando Dados . . . . . . . . . . . . . . . . . . . 94
4.5.5 Operadores e Ordenação . . . . . . . . . . . . . . . . . 96
4.5.6 Outros Métodos . . . . . . . . . . . . . . . . . . . . . . 98
4.6 Matplotlib . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
4.6.1 Gráficos de Linha . . . . . . . . . . . . . . . . . . . . . 103
4.6.2 Gráfico de Dispersão . . . . . . . . . . . . . . . . . . . 106
4.6.3 Histograma . . . . . . . . . . . . . . . . . . . . . . . . 107
4.6.4 Boxplot . . . . . . . . . . . . . . . . . . . . . . . . . . 108
4.6.5 Gráficos de Barra e Setor . . . . . . . . . . . . . . . . . 109
4.6.6 Anotações e Setas . . . . . . . . . . . . . . . . . . . . . 112
SUMÁRIO 5

4.7 Seaborn . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114


4.8 Desafio: Construindo seu próprio Módulo . . . . . . . . . . . . 117

5 Boas Práticas em Programação 119


5.1 Preâmbulo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119
5.2 Solicitando dados do usuário . . . . . . . . . . . . . . . . . . . 120
5.3 Tratamento de erros e exceções . . . . . . . . . . . . . . . . . 120
5.4 Dados de conexão a Bancos de Dados . . . . . . . . . . . . . . 121
5.5 Modularização . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
5.6 Comentários . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123
5.7 Término do script . . . . . . . . . . . . . . . . . . . . . . . . . 123
5.8 Exemplo final . . . . . . . . . . . . . . . . . . . . . . . . . . . 124

6 Próximos Capítulos 127


6 SUMÁRIO
Lista de Tabelas

1.1 Linha do Tempo do Python. . . . . . . . . . . . . . . . . . . . 16

2.1 Tipos de Variáveis em Python . . . . . . . . . . . . . . . . . . 27


2.2 Operadores em Python . . . . . . . . . . . . . . . . . . . . . . 31
2.3 Funções em Python . . . . . . . . . . . . . . . . . . . . . . . . 32
2.4 Métodos de strings. . . . . . . . . . . . . . . . . . . . . . . . . 34
2.5 Métodos de listas. . . . . . . . . . . . . . . . . . . . . . . . . . 40
2.6 Operadores Lógicos em Python . . . . . . . . . . . . . . . . . 54
2.7 Operadores Lógicos em Python . . . . . . . . . . . . . . . . . 54

4.1 Diferença entre Módulo, Pacote e Biblioteca. . . . . . . . . . . 73


4.2 Diferenças entre Listas e Arrays. . . . . . . . . . . . . . . . . . 80
4.3 Comparação entre Array e DataFrame . . . . . . . . . . . . . 89
4.4 Módulos do Matplotlib . . . . . . . . . . . . . . . . . . . . . . 102
4.5 Comandos para personalizar gráficos de linha . . . . . . . . . 105

7
8 LISTA DE TABELAS
Lista de Figuras

1.1 Ciência de Dados e algumas das áreas correlatas. . . . . . . . 13


1.2 Guido van Rossum, criador do Python. . . . . . . . . . . . . . 14
1.3 Índice Tiobe de utilização de linguagens de programação no
mundo. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
1.4 Paralelo entre Python e um canivete suíço: os pacotes cons-
truídos nas últimas décadas contribuíram para seu crescimento. 17
1.5 Ambiente do PyCharm . . . . . . . . . . . . . . . . . . . . . . 19
1.6 Ambiente do Spyder . . . . . . . . . . . . . . . . . . . . . . . 20
1.7 Ambiente do VS Code . . . . . . . . . . . . . . . . . . . . . . 21
1.8 Ambiente do Jupyter . . . . . . . . . . . . . . . . . . . . . . . 22
1.9 Ambiente do Colab . . . . . . . . . . . . . . . . . . . . . . . . 23
1.10 Ambiente do RStudio . . . . . . . . . . . . . . . . . . . . . . . 24
1.11 Ambiente do Positron . . . . . . . . . . . . . . . . . . . . . . . 25

2.1 Exemplo de Métodos e Atributos . . . . . . . . . . . . . . . . 33

4.1 Exemplo de importação da biblioteca NumPy e seus métodos. 74


4.2 Exemplo de Gráfico de Linhas . . . . . . . . . . . . . . . . . . 104
4.3 Exemplo de Subplots . . . . . . . . . . . . . . . . . . . . . . . 105
4.4 Exemplo de Gráfico de Dispersão . . . . . . . . . . . . . . . . 106
4.5 Exemplo de Histograma . . . . . . . . . . . . . . . . . . . . . 108
4.6 Exemplo de Boxplot . . . . . . . . . . . . . . . . . . . . . . . 109
4.7 Exemplo de Gráfico de Barra . . . . . . . . . . . . . . . . . . 110
4.8 Exemplo de Gráfico de Setor . . . . . . . . . . . . . . . . . . . 111
4.9 Exemplo de Gráfico de Barras Empilhadas . . . . . . . . . . . 112
4.10 Exemplo de uso do Annotate . . . . . . . . . . . . . . . . . . . 113
4.11 Gráfico de Dispersão com linha de regressão . . . . . . . . . . 115
4.12 Boxplot por dia da semana . . . . . . . . . . . . . . . . . . . . 115
4.13 Fumantes por sexo . . . . . . . . . . . . . . . . . . . . . . . . 116

9
10 LISTA DE FIGURAS
Capítulo 1

Introdução

Foi Hal Varian, economista-chefe da Google, quem certa vez disse: "Esta-
tísticos serão a profissão mais sexy da década"(Davenport and Patil, 2012).
Por "sexy", ele estava querendo se referir a profissionais com qualidades raras
e que seriam altamente demandados pelo mercado. Hal estava se referindo à
década dos anos ‘10.
Bem, a década passou e a profissão de Cientista de Dados só se expandiu.
Hoje, Ciência de Dados vai muito além da Estatística. Temos Analistas de
Dados, Engenheiros de Dados, Analistas de TI, Desenvolvedores, Adminis-
tradores de Banco de Dados, Analistas de DevOPS, de MLOPS e assim por
diante, todos trabalhando de maneira cada vez mais integrada.
Neste universo, Python é a linguagem de programação que mais cresce e
a demanda por bibliografias completas sobre o uso de Python com Ciência de
Dados, que abordem desde os conceitos mais básicos até os mais avançados,
em Português, foi o que motivou a elaboração do presente material.
Neste capítulo introdutório, falaremos brevemente sobre a história do
Python e da Ciência de Dados, explicaremos o que é uma linguagem orientada
a objetos e daremos os primeiros passos com a linguagem Python.

1.1 O que é Ciência de Dados?


Data Science, ou como a chamamos em Português, Ciência de Dados,
é um termo que está em alta e tudo indica que só tende a se expandir cada
vez mais. Talvez você já tenha ouvido a frase "Dados são o novo petróleo"e
não é para menos: estamos na era do Big Data, sendo bombardeados por
toneladas de dados todos os dias. Saber transformar os dados em informação
em nossos tempos é uma habilidade que vale ouro.
Mas afinal, do que estamos falando quando nos referimos a Ciência de

11
12 CAPÍTULO 1. INTRODUÇÃO

Dados? O termo não é exatamente novo, tendo sua origem atribuída ao


Prof. William Cleveland, pesquisador estatístico da American Telephone &
Telegraph (AT&T) e Professor da Universidade de Purdue, o qual definiu o
termo como um plano de ação para ampliar os ramos técnicos da estatística
para diversas áreas de aplicação.
Nesse plano, tanto modelos e métodos quanto computação utilizando da-
dos seriam ferramentas essenciais para um analista (Cleveland, 2001). Vale
ressaltar menções feitas à origem do termo em 1997 e designada ao estatís-
tico Prof. Chien-Fu Jeff Wu da Universidade de Michigam (Chipman et al.,
2016), conhecido por seus trabalhos de pesquisa em estatística computacional
e aplicações industriais. O termo foi utilizado por ele em uma aula inaugu-
ral quando argumentou que os estatísticos deveriam ser renomeados como
”cientistas de dados”, uma vez que eles gastam a maior parte do tempo na
manipulação, organização e limpeza de dados.
Além disso, há mais de 50 anos atrás, John Tukey solicitou uma reforma
das estatísticas acadêmicas e apontou para a existência de uma ciência ainda
não conhecida na época, cujo principal assunto de interesse era ıaprender
com os dadosȷ, ou data analysis (Tukey, 1962).
Porém, a profissão cientista de dados foi impulsionada em 2008 quando,
Jeff Hammerbacher e DJ Patil, respectivos líderes da área de análises de
dados do LinkedIn e no Facebook, utilizaram o termo no recrutamento de
profissionais cujo trabalho principal era lidar com dados continuamente emer-
gentes e tentar identificar padrões.
Hoje em dia, o termo Ciência de Dados ganhou novos significados, dada a
multiplicidade de áreas que acabaram sendo agrupadas dentro de seu escopo:
Estatística, Matemática, Tecnologia da Informação e Inteligência Artificial
são apenas algumas delas.
O profissional que vai trabalhar com Ciência de Dados deve, portanto,
ter conhecimentos interdisciplinares e ser capaz de analisar dados estrutu-
rados ou não, encontrar padrões, fazer previsões, construir painéis, elaborar
relatórios e outras atividades relacionadas com apoio à tomada de decisão
estratégica. Veremos algumas dessas atividades em detalhes ao longo desse
material.
O ciclo de vida da Ciência de Dados pode envolver várias etapas, mas
algumas delas são essenciais:

• Coleta: tudo começa com a coleta de dados, que por si só já pode se


transformar em uma tarefa complexa. Essa fase pode envolver o que
chamamos de ETL (do inglês Extract, transform, load, ou seja, extrair,
transformar e carregar). Existem inúmeras formas e frameworks de se
fazer isso, a depender da finalidade.
1.1. O QUE É CIÊNCIA DE DADOS? 13

Figura 1.1: Ciência de Dados e algumas das áreas correlatas.

• Armazenamento: depois de coletados e transformados de acordo com


o objetivo, os dados precisam ser armazenados em algum lugar. Se
nosso objetivo está focado em BI (Business Intelligence), o armazena-
mento pode ser feito em um DW (Data Warehouse). Se o foco são
aplicações de Big Data, podemos fazer uso de um Data Lake, que ex-
pande o conceito de DW para agregar também dados não estruturados.
Todo esse ecossistema pode se tornar algo extremamente complexo e
não será abordado nesse material, mas falaremos com um pouco mais
de detalhes em capítulos mais avançados.

• Análise: é comum que após o armazenamento, seja realizada uma


análise exploratória dos dados antes de efetivamente se realizar as ope-
rações desejadas. Isso engloba o cálculo de estatísticas descritivas, ela-
boração de gráficos, etc. Se nosso objetivo é BI, essa fase pode com-
preender também a elaboração de painéis ou dashboards de monitora-
mento, e nosso papel estaria cumprido. Essa fase é importante para
identificar possíveis padrões, outliers ou erros de cadastro em bases ins-
titucionais, contribuindo para um dos requisitos mais importantes em
qualquer processo de Ciência de Dados: a qualidade dos dados que
serão tratados.
14 CAPÍTULO 1. INTRODUÇÃO

Figura 1.2: Guido van Rossum, criador do Python.

• Modelagem: essa etapa pode compreender muita coisa, desde mo-


delos de regressão linear simples até o desenvolvimento de estruturas
complexas de aprendizado de máquina e inteligência artificial. Por isso
a etapa anterior é tão importante, pois se a entrada do modelo for ruim,
a saída também será ruim. A modelagem por si só é um processo que
envolve muitas etapas, como: treinamento, teste, validação, compara-
ção de modelos, implementação do modelo final, etc. Veremos alguns
exemplos disso no capítulo ***.

• Atualização: tendo o processo completo implantado e funcionando, a


etapa final compreende agendamento de atualização dos dados. É por
isso que estamos lidando com um ciclo: coletamos os dados, aplicamos
nossa solução, mas depois precisamos de novos dados para que essa
solução continue funcionando a contento.

Como se pode perceber, as tarefas de Ciência de Dados podem ser bas-


tante complexas e requerem uma enorme gama de ferramentas para sua re-
alização. Python é uma delas.

1.2 O que é Python?


Dentro do vasto universo da Ciência de Dados, Python é uma das lingua-
gens mais utilizadas. Sua simplicidade é uma grande vantagem para realizar
desde operações mais simples até as mais complexas.
O Python foi criado por Guido van Rossum, um programador holandês
nascido em 1956 em Haia, nos Países Baixos. Trabalhou no CWI (Centrum
Wiskunde & Informatica) na Holanda, depois na BeOpen, ZopeCorporation,
1.2. O QUE É PYTHON? 15

Figura 1.3: Índice Tiobe de utilização de linguagens de programação no


mundo.

Google e Dropbox e fez mestrado em Matemática e Ciência da Computação


pela Universidade de Amsterdã.
Durante o recesso de Natal de 1989, quando finalmente conseguira um
pouco de tempo livre, acabou criando o Python em apenas algumas semanas.
Fã de comédia britânica, acabou escolhendo o nome da linguagem inspirado
pelo grupo Monty Python’s Flying Circus, pois queria um nome simples e
que fosse fácil de lembrar.
Rossum criou o Python para ser uma linguagem de programação de alto
nível, interpretada e de propósito geral. Seu design prioriza simplicidade e
legibilidade, permitindo que programadores expressem conceitos com poucas
linhas de código. Aqui enumeramos algumas de suas principais característi-
cas:

• Sintaxe clara e intuitiva.

• Multiparadigma (suporte a programação imperativa, orientada a obje-


tos e funcional).

• Ampla biblioteca padrão e ecossistema de pacotes.

• Portabilidade e comunidade ativa.

• Linguagem interpretada, ao invés de ser compilada (como C ou C ++).

Justamente por conta dessas características é que o Python tem crescido


tanto nos últimos tempos, como podemos perceber na figura 1.3., graças a
uma comunidade engajada e altamente ativa.
É claro que esse crescimento foi fruto da evolução da linguagem, como
podemos verificar na tabela 1.1.
16 CAPÍTULO 1. INTRODUÇÃO

Ano Marco Descrição


1991 Python 0.9.0 Primeira versão pública, com
functions, exceptions e modules
2000 Python 2.0 Introdução de list comprehensi-
ons e coleta de lixo (garbage col-
lection).
2001 Fundação Organização sem fins lucrativos
Python para manter e desenvolver o
Sogtware Foun- Python.
dation (PSF)
2008 Python 3.0 Unicode como padrão, mudanças
de sintaxe e quebra de compatibi-
lidade com Python 2.
2010-2015 Crescimento do Popularização de bibliotecas
ecossistema como NumPy, Pandas, Matplo-
tlib e Scikit-learn.
Tabela 1.1: Linha do Tempo do Python.

"Python é como um canivete suíço: simples de usar, mas poderoso


o suficiente para mudar o mundo."
1.2. O QUE É PYTHON? 17

Figura 1.4: Paralelo entre Python e um canivete suíço: os pacotes construídos


nas últimas décadas contribuíram para seu crescimento.
18 CAPÍTULO 1. INTRODUÇÃO

1.3 Instalação e IDEs


Antes de iniciarmos nosso trabalho, é necessário que você instale o Python
em sua máquina local para que seja capaz de reproduzir os exemplos que
trabalharemos ao longo de nossa jornada. Você pode fazer isso diretamente
do site oficial [Link] ou através de distribuições como o pacote Ana-
conda ([Link] Qualquer que seja a opção esco-
lhida, recomenda-se a utilização da versão 3.10.* para garantir que os mesmos
exemplos ilustrados aqui funcionem a contento.
Após a instalação, você pode abrir o Terminal ou Prompt de Comando/-
Powershell para executar o Python, utilizando o comando python. Pronto!
Você já pode começar a escrever seus próprios códigos em Python! Para exe-
cutar um script Python (arquivos com extensão .py), utiliza-se o comando
python [Link] ou python3 [Link], estando no dire-
tório onde o script estiver localizado.
Na prática, no entanto, dificilmente criamos códigos diretamente em um
console. Para isso utilizamos programas específicos que já vem com todo um
ecossistema montado para programação. São os chamados IDEs (do inglês
Integrated Development Environment, ou em português, Ambiente de Desen-
volvimento Integrado). Existem vários IDEs para programar em Python e a
seguir falaremos de alguns deles.

1.3.1 PyCharm
Criado pela JetBrains, o PyCharm é uma dos mais utilizados. Eis algu-
mas de suas características:

• Análise de código inteligente.

• Depuração avançada.

• Integração com ferramentas de desenvolvimento, como Git.

• Suporte a frameworks web.

• Facilidade de refatoração de código.


1.3. INSTALAÇÃO E IDES 19

Figura 1.5: Ambiente do PyCharm


20 CAPÍTULO 1. INTRODUÇÃO

1.3.2 Spyder

Figura 1.6: Ambiente do Spyder

Projetado especificamente para Ciência de Dados, o Spyder já vem com


algumas bibliotecas integradas. Suas características são:

• Interface similar ao MATLAB - para quem já conhece, não há dificul-


dade.

• Editor avançado - destaque de sintaxe, autocomplementa e análise de


código.

• Explorador de variáveis.

• Permite divisão do código em células e você escolhe de que modo quer


executá-lo.

• IPython Console integrado.

• Integração com bibliotecas científicas, como NumPy, SciPy e Matplo-


tlib.

• Depurador integrado
1.3. INSTALAÇÃO E IDES 21

1.3.3 Visual Studio Code (VS Code)

Figura 1.7: Ambiente do VS Code

O VS Code foi desenvolvido pela Microsoft e é uma das IDEs mais popu-
lares do mundo, já que suporta uma infinidade de linguagens. Suas caracte-
rísticas incluem:
• Leveza e velocidade.
• Extensibilidade - várias extensões disponíveis.
• Autocompletar - sugestões de código inteligentes.
• Depuração integrada.
• Terminal integrado.
• Controle de versão Git.

1.3.4 Jupyter Notebook / Google Colab


O nome Jupyter é um acrônimo formado pelas linguagens que ele suporta:
Julia, Python e R. É um ambiente web que já vem com o Anaconda e pode
ser utilizado por quem não deseja instalar um ambiente de desenvolvimento
localmente. É caracterizado por:
22 CAPÍTULO 1. INTRODUÇÃO

Figura 1.8: Ambiente do Jupyter

• Células interativas - divide o código em partes.

• Execução não-linear - cada célula pode ser executada individualmente.

• Visualizações integradas.

• Compartilhamento fácil.

O Jupyter é ideal para o ambiente acadêmico, já que permite misturar


explicações, código latex e equações matemáticas intercalados com o código.
Deve-se tomar certo cuidado, no entanto, pois ele não gera arquivos .py e
sim com uma extensão própria: .ipynb. Esse tipo de arquivo roda apenas no
ambiente Jupyter, ao contrário dos scripts Python tradicionais que podem
rodar em qualquer IDE ou no próprio console.
Para quem não deseja instalar nada em sua máquina local, o Google Colab
pode ser uma opção. Trata-se de um Jupyter Notebook hospedado pela
Google e integrado com suas ferramentas. Como o próprio nome diz, tem
foco em colaboração, permitindo compartilhamento de arquivos de maneira
muito facilitada.
1.3. INSTALAÇÃO E IDES 23

Figura 1.9: Ambiente do Colab


24 CAPÍTULO 1. INTRODUÇÃO

1.3.5 RStudio / Positron

Figura 1.10: Ambiente do RStudio

O R é outra linguagem bastante popular em Ciência de Dados, criada


inicialmente pela comunidade Estatística. O RStudio foi então desenvolvido
para trabalhar com essa linguagem, mas dadas as recentes integrações entre R
e Python, não tardou para que o RStudio passasse a aceitar também códigos
dessa última, através do pacote reticulate. Suas principais características:

• Destaque de sintaxe, autocomplementar, indentação inteligente.

• Executa código diretamente do editor.

• Pula diretamente para definições de função.

• Integrado com editor Markdown, que permite criação de relatórios,


apresentações e páginas HTML.

• Facilidade de gerenciamento de múltiplos diretórios.

• Integrado com a documentação do R.

• Depuração interativa.

• Várias ferramentas de desenvolvimento.


1.4. PROGRAMAÇÃO ORIENTADA A OBJETOS 25

Recentemente o RStudio foi comprado pela empresa Posit, que passou a


desenvolver um novo IDE com várias outras funcionalidades que o RStudio
não comporta. O Positron é, portanto, o mais novo ambiente de desenvol-
vimento focado em Ciência de Dados.

Figura 1.11: Ambiente do Positron

Escolha a IDE com a qual você se sente mais confortável e mãos à obra!

1.4 Programação Orientada a Objetos


Quando falamos de linguagens de programação, há vários paradigmas que
podem ser utilizados. Python é uma linguagem de programação baseada no
paradigma de orientação a objetos (POO). Isso significa que em Python, tudo
será um objeto com suas próprias características: variáveis, funções, classes,
etc.
É importante entender esses conceitos para poder melhor compreender o
funcionamento da linguagem. POO baseia-se no conceito de que cada objeto
possui características (atributos) e comportamentos (métodos) e esses objetos
interagem entre si para realização de tarefas.
Alguns dos conceitos mais clássicos em POO são a herança e o polimor-
fismo, que permitem a reutilização de código e a criação de hierarquias entre
26 CAPÍTULO 1. INTRODUÇÃO

os objetos criados. Justamente por conta disso é que hoje a POO é o para-
digma mais utilizado, em linguagens como Java, C, C ++ , C # , Ruby e assim
por diante.
Também cabe destacar que é o paradigma mais utilizado em uma das
áreas mais proeminentes de Ciência de Dados: o Aprendizado de Máquina.
Veremos alguns desses conceitos em detalhes ao longo dos próximos ca-
pítulos.

1.5 Estrutura dos códigos


Nesse material frequentemente utilizaremos exemplos didáticos ou reais
de como codificar em Python. Esses códigos serão estruturados sempre da
seguinte forma:
1 # Isso é um coment á rio - coment á rios n ã o s ã o lidos pelo
interpretador !
2

3 x = 2 # Nessa lista temos um c ó digo Python . Estamos


atribuindo o valor 2 a uma vari á vel x .
4

5 s = " Isso é uma string . Strings s ã o texto . "


6

7 print ( x )
8 >>> 2 # Essa linha iniciada com " > > >" representa o
resultado retornado ap ó s um comando ser executado .

Não se preocupe se nesse momento você ainda não entende o que são
comentários, variáveis ou strings, pois falaremos disso em detalhes nos próxi-
mos capítulos. Apenas é importante que você perceba como os códigos serão
exibidos ao longo de sua leitura.
Tudo entendido? Então, vamos começar.
Capítulo 2

Conceitos Básicos

2.1 Variáveis e seus tipos


Um dos objetos mais básicos em qualquer linguagem de programação são
as variáveis, que servem para armazenar dados e, através delas, realizar as
mais variadas operações. Os tipos de variáveis em Python são mostrados na
tabela 2.1.
Perceba que os tipos int e float são os mais simples e também os mais
utilizados. Através deles podemos realizar operações aritméticas básicas,
como adição, subtração, multiplicação e assim por diante.
Outro tipo comumente utilizado é o string, justamente por ser o tipo que
suporta textos. Através desse tipo podemos definir variáveis que guardam
resultados que serão impressos na tela, por exemplo, combinando variáveis
do tipo int ou float com string.
Variáveis do tipo complex são mais utilizadas em situações que exijam
cálculos geométricos e científicos, enquanto que as booleanas (bool ) aceitam

Tipo Descrição Exemplo


int Inteiro x=2
float Ponto Flutuante ou Decimal y = 3.14
str String t = ′ Eu adoro Ciência de Dados′
bool Booleano (Verdadeiro/Falso) teste = True
complex Números complexos a = 5+2j
list Lista de valores z = [1,2,5,7,9]
tuple Tupla de valores w = (1,2,5,7,9)
dic Dicionário (estrutura chave: valor) altura ={ Pedro′ : 1.65, ′ José′ : 1.60}

Tabela 2.1: Tipos de Variáveis em Python

27
28 CAPÍTULO 2. CONCEITOS BÁSICOS

apenas valores de Verdadeiro(True) ou Falso(False). São úteis quando que-


remos guardar resultados lógicos.
Já as listas(list) e tuplas(tuple) guardam estruturas de dados (que podem
ser numéricos, texto ou até ambos) e a principal diferença entre elas é que as
tuplas não podem sofrer alterações depois de criadas, enquanto que as listam
podem sofrer adição ou subtração de valores, substituição, etc.
Finalmente, o tipo dic são variáveis que guardam estruturas que sempre
são salvas em uma dupla de chave e valor. São úteis em várias situações nas
quais necessitamos guardar valores e seus respectivos atributos e permitem
acesso rápido aos dados justamente por meio das chaves.
Perceba que não é necessário declarar o tipo de variável antes de sua
utilização. Basta executar o comando conforme os exemplos mencionados
e o Python automaticamente reconhecerá com que tipo de variável se está
trabalhando.
Especificamente para strings, o exemplo fornecido está entre aspas sim-
ples, mas o Python não faz distinção entre aspas simples ou duplas.

Declaração de Variáveis

Em muitas linhguagens de programação, é necessária declaração prévia


de variáveis antes de se utilizá-las propriamente. Isso não é necessário em
Python, que já entende qual é o tipo de variável de acordo com o conteúdo
a ela atribuído.
Não obstante, cabe chamar atenção para alguns cuidados ao se criar va-
riáveis em Python. O nome da variável aceita letras, números e alguns ca-
racteres especiais (é comum utilizar _, por exemplo), mas ela não aceitará
que o número venha antes da letra.
Em outras palavras, é possível criar uma variável chamada x1, mas não
é possível criar uma variável 1x. Além disso, também não se pode utilizar
palavras reservadas como nome de variável, como True, False, class, is, None,
for, if, return entre tantas outras que são utilizadas na codificação. Ao se
tentar criar variável com esses nomes, retornará um erro de sintaxe.
Um recurso interessante, no entanto, é a declaração múltipla, ou seja,
podemos atribuir valores a mais de uma variável em uma mesma linha. Por
exemplo:
1 x , y , z = 10 , 20 , 30
2 nome1 , nome2 , nome3 = " Jo ã o " , " Maria " , " Pedro "

Esse recurso é bastante útil para tornar o código mais limpo e enxuto.
2.2. OPERAÇÕES SIMPLES E TIPOS DE OPERADORES 29

Comandos básicos e conversões


A função print é utilizada sempre que se deseja verificar o conteúdo de
uma certa variável. Utilizar print(x) ou simplesmente digitar x e apertar
ENTER no console são comandos equivalentes e irão retornar o conteúdo de
x, ou um erro caso x ainda não tenha sido declarada.
Quando se está em dúvida sobre qual tipo de variável foi criado, pode-se
utilizar a função type() para verificação.
1 x = 2
2 type ( x )
3 >>> < class ' int ' >

Também é possível, em determinadas situações, converter um tipo de


variável em outra. Por exemplo:
1 x = 2.5
2 int ( x )
3 >>> 2

Neste exemplo, utilizamos a função int para converter a variável x, ini-


cialmente do tipo float, para inteiro. Isso foi possível porque os dois tipos
são numéricos, mas perceba que ao fazer isso, acabou-se truncando o valor
da variável original.
É claro, se você tentar converter uma variável string em inteiro ou float,
ele retornará erro, pois essa operação é inviável.

2.2 Operações Simples e Tipos de Operadores


Uma vez entendido o conceito de variáveis, agora podemos utilizá-las para
realizar operações. A seguir apresentamos um exemplo de código Python que
realiza operações aritméticas simples com variáveis do tipo inteiro:
30 CAPÍTULO 2. CONCEITOS BÁSICOS

1 a = 10
2 b = 3
3

4 soma = a + b
5 subtracao = a - b
6 multiplicacao = a * b
7 divisao = a / b
8 divisao_inteira = a // b
9 resto = a % b
10 exponenciacao = a ** b
11

12 print ( " Soma : " , soma )


13 print ( " Subtra ç ã o : " , subtracao )
14 print ( " Multiplica ç ã o : " , multiplicacao )
15 print ( " Divis ã o : " , divisao )
16 print ( " Divis ã o inteira : " , divisao_inteira )
17 print ( " Resto da divis ã o : " , resto )
18 print ( " Exponencia ç ã o : " , exponenciacao )
19

20 >>>
21 Soma : 13
22 Subtra ç ã o : 7
23 Multiplica ç ã o : 30
24 Divis ã o : 3.3333333333333335
25 Divis ã o inteira : 3
26 Resto da divis ã o : 1
27 Exponencia ç ã o : 1000

Já com o uso de strings, podemos realizar concatenações de texto, como


por exemplo:
1 a = " A cor do meu cabelo é "
2 b = " preta "
3 a+b
4 >>> ' A cor do meu cabelo é preta '

Perceba que o resultado não colocou espaço entre as palavras ”é” e ”preto”.
Isso porque não existe espaço nem no final da variável ”a” e nem no início da
variável ”b”. Se desejamos que o resultado final fique correto, precisaríamos
abordar uma dessas duas soluções.
Ao se imprimir uma string na tela, caso se deseje quebrar uma linha do
texto, podemos utilizar o comando \n no meio da string para tanto. Por
exemplo:
2.3. FUNÇÕES, MÉTODOS E ATRIBUTOS 31

Operador Nome Função


+ Adição Realiza a soma de operandos numé-
ricos ou a concatenação de operan-
dos de texto.
− Subtração Realiza a subtração de ambos ope-
randos.
∗ Multiplicação Realiza a multiplicação de ambos
operandos.
/ Divisão Realiza a Divisão de ambos operan-
dos.
// Divisão inteira Realiza a divisão entre operandos e a
parte decimal de ambos operandos.
% Módulo Retorna o resto da divisão de ambos
operandos.
∗∗ Exponenciação Retorna o resultado da elevação da
potência pelo outro.

Tabela 2.2: Operadores em Python

1 print ( ' Estudar Ci ê ncia de Dados ser á um grande avan ç o \ n


para meu crescimento profissional ' )
2

3 >>> Estudar Ci ê ncia de Dados ser á um grande avan ç o


4 para meu crescimento profissional

O leitor atento deve ter percebido que para realizar operações com as
variáveis, precisamos escrever variável 1, operador e variável 2. Ou seja,
a depender do tipo de operação que desejamos realizar, iremos precisar de
operadores diferentes.
A tabela 2.2 apresenta alguns dos principais operadores aritméticos em
Python.

2.3 Funções, Métodos e Atributos


Alguns dos conceitos mais tradicionais em POO é a existência de funções,
métodos e atributos para cada objeto que é criado em um programa. Já
utilizamos algumas das funções básicas do Python, como print, type e int.
Agora vamos formalmente definir o que são funções e verificar algumas delas.
Podemos dizer que uma função é um comando utilizado para realizar de-
terminada operação a partir de parâmetros de entrada. Em outras palavras,
o que está sendo feito ao se realizar o comando int(x) é solicitar ao inter-
32 CAPÍTULO 2. CONCEITOS BÁSICOS

pretador da linguagem Python que ele realize a seguinte operação: converta


para inteiro o valor que está armazenado na variável x.
Por trás de qualquer função estão programadas linhas de código que rea-
lizam a operação desejada, que podem ser desde as mais simples até as mais
complexas. Mais adiante veremos como podemos utilizar esse conceito para
criar nossas próprias funções.
No entanto, o Python já vem com muitas funções pré-programadas (cha-
madas de funções built-in) e também podemos importar funções que não são
nativas através de pacotes, o que também veremos mais adiante.
Por enquanto, podemos utilizar a tabela 2.3 como referência para conhecer
algumas das funções básicas nativas (ou seja, não necessitam a invocação de
pacotes adicionais) mais utilizadas em Python.

Função Descrição
abs Retorna o valor absoluto de um número.
enumerate Devolve um objeto enumerado.
help Invoca o sistema de ajuda embutido.
int converte um número para inteiro.
float converte um número para decimal.
len Devolve o comprimento de um objeto
map Devolve um iterador que aplica uma fun-
ção a cada item de um iterável
max Retorna o máximo de um objeto.
min Retorna o mínimo de um objeto.
pow(base, exp) Retorna base elevado a exp.
print Exibe o resultado na tela.
range(i,j) Cria uma sequência de números de i até
j-1.
round(n, d) Arredonda o número n para d quantidade
de dígitos.
sort Retorna uma nova lista classificada de um
objeto.
sum Realiza a soma dos itens de um objeto.
type Retorna o tipo de um objeto.
zip Itera sobre vários objetos e retorna tuplas
com um item de cada um.

Tabela 2.3: Funções em Python

Métodos também são funções, porém são funções específicas para de-
terminado tipo de objeto. Assim como atributos são características ou
propriedades de um determinado tipo de objeto. Os IDEs mais atuais em
2.3. FUNÇÕES, MÉTODOS E ATRIBUTOS 33

programação já possuem uma funcionalidade interessante que lhe permite ve-


rificar quais são os métodos e atributos de um objeto, simplesmente digitando
”.” depois do objeto, conforme mostrado na figura 2.1.

Figura 2.1: Exemplo de Métodos e Atributos

Verifica-se, nesse caso, que mesmo uma variável simples do tipo inteiro
possui uma infinidade de métodos e atributos atribuídas a ela e o IDE já nos
traz uma descrição de cada uma delas. Se utilizarmos [Link], por
exemplo, teremos como resultado o menor denominador de x (no caso, 1).
Esse é um atributo de x.
Já se utilizarmos x.as_integer_ratio(), estaremos invocando um método
para a variável x, que retornará um par de inteiros cuja razão será exatamente
igual ao valor de x com um denominador positivo. No exemplo, (3,1).
Para strings, alguns métodos mais utilizados são mostrados na tabela 2.4,
mas evidentemente que esses são apenas alguns exemplos. Assim como no
exemplo para a variável x, para utilizar qualquer um deles devemos primeiro
escrever ’.’ depois do nome da variável. Ou seja, para utilizar o método upper
para uma string s, utiliza-se [Link]().
É claro que existe uma infinidade de funções nativas e específicas para
cada pacote, além de incontáveis métodos e atributos para cada tipo de
objeto. Sempre recomenda-se consultar a documentação para verificar se já
não existe uma função, método ou atributo que realize o que desejamos.
34 CAPÍTULO 2. CONCEITOS BÁSICOS

Método Descrição
captalize Tranforma a primeira letra do texto
para maiúscula.
count(’a’) Conta quantas vezes a letra ’a’ aparece
no texto.
endswith(’a’) Verifica se o texto termina com a letra
’a’.
find Retorna o índice da primeira ocorrência
de um caractere.
lower Transforma o texto em minúscula.
split Divide o texto em vários espaços.
strip Remoce os espaços da string. rstrip
pode ser usado para remover apenas
os da direita e lstrip apenas os da es-
querda.
startswith Verifica se a string inicia com determi-
nada sequência.
title Converte para maiúsuclas todas as pri-
meiras letras de uma string.
upper Transforma o texto em maiúscula.
Tabela 2.4: Métodos de strings.
2.4. INDEXAÇÃO E FATIAMENTO 35

2.4 Indexação e Fatiamento


Em qualquer linguagem de programação, em especial as que lidam com
números e operações matemáticas, precisamos entender como funciona a in-
dexação de variáveis para que possamos realizar operações, seja com textos
ou com números. A indexação correta nos permite selecionar caracteres es-
pecíficos de uma string por exemplo, ou partes de uma sequência de números.
Em Python, a indexação sempre começará em 0. Vamos exemplificar
criando uma string simples:
s = ’Python’
Ao executar esse comando no console, cada letra da string recebeu um
índice, a saber: P = 0, y = 1, t = 2 e assim por diante. Sabendo disso,
podemos selecionar qualquer uma dessas letras, ou parte da string, se assim
desejarmos. Os exemplos a seguir ilustram algumas formas de fazer isso:
1 s = " Python "
2

3 s [0]
4 >>> " P "
5

6 s [4]
7 >>> " o "
8

9 s [0:4]
10 >>> " Pyth "
11

12 s [:4]
13 >>> " Pyth "
14

15 s [1:4]
16 >>> " yth "
17

18 s [4:]
19 >>> " on "
20

21 s [ -1]
22 >>> " n "

Perceba que podemos extrair um conjunto de caracteres, delimitado por


um par de números separados por ":", que indicam o início e o fim da sequên-
cia (exclusivo, ou seja, o número desse índice não será incluído no resultado).
Caso não seja definido o primeiro número, a seleção começará do início e
caso não seja definido o segundo número, a seleção terminará no fim. Essa
36 CAPÍTULO 2. CONCEITOS BÁSICOS

é a chamada notação de slicing, ou fatiamento, que pode ser utilizada em


qualquer estrutura de dados.
Por isso, no exemplo acima, é equivalente utilizar o comando "s[0 : 4]"ou
"s[: 4]". Como a sequência sempre inicia com índice 0, é indiferente escrever
0 ou não.
Também podemos utilizar índices negativos, ou seja, trazer os resultados
de trás para frente. É o que foi feito com o comando "s[−1]".
Todas essas operações também podem ser realizadas com estruturas que
comportem números, o que veremos mais adiante, na seção sobre listas.

2.5 Strings, Placeholders e f-strings


Podemos trabalhar com variáveis numéricas e variáveis de texto conjun-
tamente, o que chamamos de composição. Isso é feito utilizando-se marca-
dores de posição (placeholders), como por exemplo:

• %d: números inteiros.

• %s: strings.

• %f : números decimais.

• %3d: controlar tamanho mínimo.

• %03d: controlar zero à esquerda.

• %5.2f : controlar casas decimais.

Uma outra opção seria utilizar o que chamamos de f-string, que tem a se-
guinte sintaxe: f’texto da string e {variável}’. A seguir um exemplo
simples:
2.6. ESTRUTURAS DE DADOS 37

1 x = 2
2

3 # Utilizando placeholder :
4 print ( " O valor de x é % d " % x)
5 >>> O valor de x é 2
6

7 # Utilizando dois placeholders ao mesmo tempo :


8 x = 1.70
9 nome = " Jo ã o "
10 print ( " A altura de % s é % d " % ( nome , x ) )
11 >>> A altura de Jo ã o é 1.700000
12

13 # Utilizando f - string para o primeiro exemplo :


14 print ( f " O valor de x é : { x } " )
15 >>> O valor de x é 2

A diferença de se utilizar a f-string é que ela aceitará não apenas os valores


da variável que está entre chaves, mas também operações e atributos dessa
variável, como veremos mais adiante.

2.6 Estruturas de Dados


Os tipos de variáveis que trabalhamos até agora - int, float, string - são
conhecidos por armazenarem apenas um tipo de valor. Há, no entanto, outros
tipos de variáveis que podem armazenar vários valores ao mesmo tempo. São
as listas, tuplas e dicionários.
Listas são definidas ao se declarar a variável com colchetes - [valores],
enquanto as tuplas são definidas por parênteses - (valores) e os dicionários,
por chaves - {chave : valor}. Veremos cada um deles em detalhes.
38 CAPÍTULO 2. CONCEITOS BÁSICOS

2.6.1 Listas
Listas podem armazenar dados de qualquer tipo em uma sequência. Pode-
mos ter apenas strings, combinação de strings com números, apenas números
e até mesmo uma lista vazia, o que é útil para quando queiramos ir salvando
o resultado de uma iteração em uma variável, como veremos mais adiante.
Vejamos alguns exemplos.
1 # lista de strings .
2 lst1 = [ " Jos é " , " Pedro " , " Escobar " ]
3 # lista combinada .
4 lst2 = [ " laranja " , " ma ç ã " , " banana " , 10 , 20 , 30]
5 # lista de inteiros .
6 lst3 = [2 , 3 , 5 , 7 , 11 , 13 , 17 , 19]
7 # lista de decimais ( float ) .
8 lst4 = [3.14 , 2.72 , 4.66]
9 # lista vazia .
10 lst5 = []

Da mesma forma que trabalhamos com indexação com strings, o mesmo


pode ser feito com listas. Vejamos alguns resultados.
1 x = lst3 [0]
2 >>> 2
3

4 y = lst3 [2:4]
5 >>> [5 , 7]

Perceba que como no primeiro comando estamos selecionando apenas


um número, o resultado será um número, ou seja, x será do tipo int. Já
no segundo, o resultado será outra lista, já que estamos selecionando um
subconjunto da variável original.
2.6. ESTRUTURAS DE DADOS 39

Manipulando Listas: Métodos e Funções


Além do fatiamento, a lista pode ser manipulada de várias formas. Veja-
mos um primeiro exemplo:
1 l = [16 , 18 , 17 , 19 , 10 , 11 , 15]
2 l [3] = 99
3 print ( l )
4 >>> [16 , 18 , 17 , 99 , 10 , 11 , 15]
5

6 l . append (66)
7 print ( l )
8 [16 , 18 , 17 , 99 , 10 , 11 , 15 , 66]
9

10 del l [1]
11 print ( l )
12 [16 , 17 , 99 , 10 , 11 , 15 , 66]

Neste caso, fizemos várias operações com apenas alguns comandos. No


primeiro exemplo, substituímos um valor da lista que está na posição 3
(lembre-se sempre: indexação em Python começa com 0) pelo valor 99.
Em seguida, acrescentamos um valor na lista utilizando o método append.
Esse método é extremamente útil, mas específico para variáveis do tipo lista,
não sendo possível sua utilização em outros tipos de variáveis.
Finalmente, excluímos da lista o valor que estava na posição 1 utilizando
a função del. A tabela 2.5 resume alguns dos métodos mais utilizados com
listas.
40 CAPÍTULO 2. CONCEITOS BÁSICOS

Método Descrição
append(valor) Inclui um valor na lista.
clear Limpa a lista.
copy Copia a lista.
count(i) Conta quantas vezes i aparece na lista.
extend(lista) inclui os valores de uma outra lista na
lista.
index Retorna o índice de um valor na lista.
insert(index, object) Insere um objeto no índice fornecido.
pop(índice) Remove um item da lista a partir de
seu índice e retorna seu valor.
remove Remove a primeira ocorrência de um
valor.
reverse Inverte a ordem dos valores de uma
lista.
sort Ordena os valores da lista.

Tabela 2.5: Métodos de listas.


2.6. ESTRUTURAS DE DADOS 41

Vejamos alguns exemplos de utilização de alguns desses métodos.


1 z = [1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9]
2 z . insert (5 , 17)
3 print ( z )
4 >>> [1 , 2 , 3 , 4 , 5 , 17 , 6 , 7 , 8 , 5 , 5]
5

6 z . count (5)
7 >>> 3
8

9 z . remove (5)
10 print ( z )
11 >>> [1 , 2 , 3 , 4 , 17 , 6 , 7 , 8 , 5 , 5]
12

13 z . reverse ()
14 print ( z )
15 >>> [5 , 5 , 8 , 7 , 6 , 17 , 4 , 3 , 2 , 1]
16

17 z . sort ()
18 print ( z )
19 >>> [1 , 2 , 3 , 4 , 5 , 5 , 6 , 7 , 8 , 17]

Pelo exemplo dado, notamos o seguinte: O método insert foi utilizado


para adicionar o valor 17 na posição 5 da lista. Perceba que todos os valores
depois do 17 ganharam novos índices depois dessa operação.
Em seguida, count nos retorna quantas vezes o número 5 aparece na lista
e remove remove o primeiro deles. Novamente, ao se remover um item da
lista, todos os valores seguintes são re-indexados.
Já o método reverse pode ser utilizado para inverter a ordem dos valores
da lista, enquanto sort é utilizado para ordená-la em ordem crescente.
Podemos ainda realizar algumas operações com listas utilizando funções
e operadores específicos. Vejamos:
42 CAPÍTULO 2. CONCEITOS BÁSICOS

1 x = [1 ,2 ,3]
2 y = [4 ,5 ,6]
3 z = x+y
4

5 print ( z )
6 [1 , 2 , 3 , 4 , 5 , 6]
7

8 len ( z )
9 >>> 6
10

11 min ( z )
12 >>> 1
13

14 max ( z )
15 >>> 6
16

17 z . index (5)
18 >>> 4

O primeiro comando dado aqui foi utilizar o operador "+"para concatenar


duas listas, resultando em uma lista nova. Atente que esse foi o mesmo
operador que foi utilizado para soma de variáveis do tipo int ou float. Em
listas ou strings, esse operador é utilizado para concatenação.
Em seguida, fizemos uso de algumas funções para retornar informações
sobre a lista z. len retorna o comprimento da lista, enquanto min e max
retornam os valores mínimo e máximo, respectivamente. E ainda, utilizamos
o método index para descobrir qual é o índice do valor 5 na lista.
Reiteramos, é claro, que além dos comandos ensinados nesta seção, exis-
tem inúmeros outros que podem ser utilizados para manipular as listas de
acordo com seu objetivo. Sempre consulte a documentação da linguagem
para descobrir novas formas de fazer o que você deseja.
2.6. ESTRUTURAS DE DADOS 43

Listas Aninhadas
Podemos ainda trabalhar com listas dentro de listas, ou seja:
1 x = [
2 [12 , 11 , 16 , 10 , 19 , 11 , 14] ,
3 [17 , 13 , 13] ,
4 [11 , 14 , 15 , 12]]
5

6 x [0]
7 >>> [12 , 11 , 16 , 10 , 19 , 11 , 14]
8

9 x [0][2]
10 >>> 16

Aqui a variável x é uma lista de listas. Perceba que as listas internas


não precisam ser do mesmo tipo nem do mesmo tamanho. Agora, porém,
se quisermos encontrar um item específico dentro da lista interna, temos que
utilizar índices duplos.
Em outras palavras, se quisermos saber qual é o valor de x na posição 0,
o retorno será a primeira lista da variável. No entanto, ao utilizarmos x[0][2],
estamos solicitando o valor que esteja na posição 2 dentro do primeiro objeto
de x.

Diferença entre append e extend


Vimos que o método append por ser utilizado para acrescentar valores em
uma lista. Porém, se utilizarmos esse método para acrescentar mais de um
valor, perceba o que acontece:
1 z . append ([7 ,8])
2 print ( z )
3

4 >>> [1 , 2 , 3 , 4 , 5 , 6 , [7 , 8]]

Ou seja, o próximo valor da lista acabou se tornando uma lista interna.


Se quisermos adicionar os valores 7 e 8 na lista como valores simples, assim
como os demais elementos, o correto seria utilizar o comando extend.
1 z . extend ([7 ,8])
2 print ( z )
3

4 >>> [1 , 2 , 3 , 4 , 5 , 6 , 7 , 8]
44 CAPÍTULO 2. CONCEITOS BÁSICOS

Sempre fique atento ao realizar operações com listas. Escreva seu código
e vá testando o resultado de cada operação para garantir que o que você
escreveu retornou realmente o resultado que você desejava.

2.6.2 Tuplas
Em Python, as tuplas são estruturas bastante similares às listas, com a
diferença de que não se pode manipulá-las. Elas aceitam diferentes tipos
de valores, mas não aceitam, por exemplo, métodos append ou extend ou
qualquer outro método ou função que vimos anteriormente que são utilizados
para modificar a estrutura dos dados contidos na tupla.
Elas podem ser utilizadas, por exemplo, em saídas de operações quando
se deseja preservar os resultados e evitar modificações.

2.6.3 Dicionários
Dicionários é um tipo de estrutura bastante útil quando se deseja arma-
zenar pares de chave/valor. No exemplo a seguir, criamos um dicionário que
armazena o número de alunos matriculados para cada curso em uma certa
faculdade.
1 dict = { " Administra ç ã o " : 40 ,
2 " Artes " : 10 ,
3 " Estat í stica " : 30 ,
4 " Matem á tica " : 20 ,
5 " Engenharia Civil " : 80
6 }
7

8 dict [ " Engenharia El é trica " ] = 30


9 print ( dict )
10

11 >>> { ' Administra ç ã o ' : 40 , ' Artes ' : 10 , ' Estat í stica ' : 30 ,
' Matem á tica ' : 20 , ' Engenharia Civil ' : 80 , ' Engenharia
El é trica ' : 30}

Neste exemplo, primeiramente criamos o dicionário com 5 cursos e atri-


buímos valores a cada um deles. Em seguida, adicionamos um sexto curso
ao dicionário. Perceba que, devido à natureza única desse tipo de estrutura,
utilizar append ou extend não seria suficiente.
Ou seja, os métodos utilizados agora são diferentes dos utilizados para
manipular listas, embora possam haver algumas funções em comum. Vejamos
alguns exemplos.
2.6. ESTRUTURAS DE DADOS 45

1 len ( dict )
2 >>> 6
3

4 dict . keys ()
5 >>> dict_keys ([ ' Administra ç ã o ' , ' Artes ' , ' Estat í stica ' , '
Matem á tica ' , ' Engenharia Civil ' , ' Engenharia El é trica '
])
6

7 dict . values ()
8 >>> dict_values ([40 , 10 , 30 , 20 , 80 , 30])
9

10 dict . items ()
11 >>> dict_items ([( ' Administra ç ã o ' , 40) , ( ' Artes ' , 10) , ( '
Estat í stica ' , 30) , ( ' Matem á tica ' , 20) , ( ' Engenharia
Civil ' , 80) , ( ' Engenharia El é trica ' , 30) ])

Veja que apesar de utilizarmos a função len para verificar o tamanho


do dicionário, outros métodos foram utilizados para verificar o conteúdo da
variável dict. Utilizamos keys para verificar quais são as chaves utilizadas,
values para ver os valores e items para ver o conteúdo completo.
Ao invés de usar concatenação, os dicionários utilizam o método update
caso se queira importar valores de um dicionário para outro. Por exemplo:

1 dict2 = { " Contabilidade " : 20 ,


2 " Economia " : 20 ,
3 }
4

5 dict . update ( dict2 )


6 print ( dict )
7

8 >>> { ' Administra ç ã o ' : 40 , ' Artes ' : 10 , ' Estat í stica ' : 30 ,
' Matem á tica ' : 20 , ' Engenharia Civil ' : 80 , ' Engenharia
El é trica ' : 30 , ' Contabilidade ' : 20 , ' Economia ' : 20}

Da mesma forma, podemos trabalhar com indexação, dicionários aninha-


dos e fazer uso de métodos e atributos para manipular o dicionário. No
entanto, não vamos nos aprofundar nesse tipo de variável pois mais adiante
trabalharemos com a biblioteca pandas, que permite a manipulação de dados
de uma forma muito mais eficiente.
Dicionários seguem o mesmo topo de estrutura de arquivos do tipo .JSON,
o que pode ser útil para trabalhar com dados extraídos da web.
46 CAPÍTULO 2. CONCEITOS BÁSICOS

2.7 Controle de Fluxo (if, while, for)


Estruturas em loop são comuns em programação para execução de tarefas
de controle de fluxo da informação, ou seja, tomar decisões ou realizar ope-
rações iterativas. Nessa seção veremos as estruturas mais comuns utilizadas
em Python.

2.7.1 If/Else
Uma das estruturas de decisão mais básicas que existem é o IF (traduzindo
do inglês seria o nosso Se). Ela serve para tomar decisão a partir de uma
escolha binária, ou seja:

SE a sentença é verdadeira
ENTÂO execute essa tarefa

Essa estrutura por si só já é funcional, pois caso a sentença não seja


verdadeira, a tarefa não será executada. No entanto, é muito comum com-
pletarmos a sentença informando o que acontece caso a sentença não seja
verdadeira, utilizando o comando SENÃO (ou, em Python, com ELSE, ou
ainda, no caso de múltiplos condicionais, podemos usar o ELIF).

SE a sentença é verdadeira
ENTÂO execute a tarefa A
SENÃO execute a tarefa B

Vejamos alguns casos de uso do condicional IF em Python.


1 if 5 > 3:
2 print ( " O primeiro n ú mero é maior . " )
3

4 >>> O primeiro n ú mero é maior .


5

6 x = 10
7 y = 3
8

9 if x % y == 0:
10 print ( " A divis ã o de x por y é exata ! " )
11 else :
12 print ( " A divis ã o de x por y n ã o é exata ! " )
13

14 >>>A divis ã o de x por y n ã o é exata !


2.7. CONTROLE DE FLUXO (IF, WHILE, FOR) 47

Esses são exemplos simples, mas que nos trazem muita informação sobre a
forma que o Python realiza as operações condicionais. Primeiro, percebamos
a forma como é montada a sintaxe: ao começar a linha com if, não importa
qual seja a condicional que será definida, a linha necessariamente deverá
terminar com dois pontos.
Além disso, a próxima linha necessariamente deverá estar indentada, ou
seja, deve-se criar um espaço utilizando a tecla TAB do teclado para só
então iniciar a descrição da tarefa a ser executada caso a condicional seja
verdadeira.
O Python é uma linguagem que considera a indentação do código, de
maneira que se as linhas não estiverem corretamente alinhadas, será retor-
nado erro. Felizmente, a maioria dos IDEs hoje em dia nos auxiliam nesse
processo, indentando automaticamente quando vamos criar estruturas com
IF, WHILE, FOR, ou definindo classes e funções.
Já no segundo exemplo, fazemos uso de variáveis antes de simplesmente
realizar uma comparação arbitrária entre dois números inteiros. Dessa forma,
permitimos que x ou y assumam quaisquer valores sem a necessidade de
alterarmos a regra de nosso condicional. Percebamos aqui algumas coisas
importantes:

• O operador igual em Python é ==. Se utilizarmos apenas =, o código


não irá funcionar, pois esse operador é de atribuição e não de igualdade.

• A palavra reservada else deve estar alinhada com a outra palavra re-
servada que iniciou o condicional, ou seja, if.

• não é necessário que conheçamos ou que imprimamos na tela o resul-


tado da sentença que foi definida na primeira linha (x%y). Nesse caso,
desejamos apenas saber se o resultado da divisão é exato ou não.

Agora que está entendida a estrutura geral do uso do IF, vamos aumentar
um pouco a complexidade.
48 CAPÍTULO 2. CONCEITOS BÁSICOS

1 n = 13
2 if n > 0:
3 print ( " O n ú mero é positivo . " )
4 elif n == 0:
5 print ( " O n ú mero é zero . " )
6 else :
7 print ( " O n ú mero é negativo . " )
8 >>> O n ú mero é positivo .
9

10 n = -13
11 if n >= 0:
12 if n == 0:
13 print ( " O n ú mero é zero . " )
14 else :
15 print ( " O n ú mero é positivo . " )
16 else :
17 print ( " O n ú mero é negativo . " )
18 >>> O n ú mero é negativo .

Aqui vemos duas formas de realizar a mesma operação: verificar se um


número é positivo, negativo ou zero. No primeiro exemplo, utilizamos a
condicional ELIF para podemos ter uma terceira opção de verificação além
do IF e do ELSE. Se necessário, poderíamos utilizar quantos ELIF quanto
fossem necessários para efetuar as verificações, mas essa não é uma forma
muito prática de se trabalhar.
Fazendo dessa forma, o interpretador primeiro irá validar a primeira sen-
tença, depois a segunda, depois a terceira e assim por diante. Utilizando
vários IF aninhados, no entanto, isso não será necessário. É o que vemos no
segundo exemplo.
Nesse caso, se o interpretador verificar que o número não é ≥ 0, ele não irá
realizar as demais verificações que estão dentro do segundo IF. Ao contrário,
ele irá ler diretamente a linha do último ELSE. Esse tipo de abordagem pode
ser a diferença entre um código mais ou menos eficiente.
2.7. CONTROLE DE FLUXO (IF, WHILE, FOR) 49

2.7.2 While
Esse outro tipo de estrutura trabalha de forma ligeiramente diferente do
IF, da seguinte forma: ENQUANTO uma sentença for verdadeira, uma certa
operação é realizada. Por exemplo:
1 x = 1
2 while x < 5:
3 print ( " O valor de x é % d " % x )
4 x = x +1
5

6 >>>
7 O valor de x é 1
8 O valor de x é 2
9 O valor de x é 3
10 O valor de x é 4
11

12 # Uma outra forma :


13 while x < 5:
14 print ( " O valor de x é % s " % x )
15 x += 1

Neste exemplo utilizamos alguns conceitos vistos anteriormente e apren-


demos algumas coisas novas. Vejamos:
• Da mesma forma que o IF, o WHILE deve terminar com dois pontos e
a próxima linha deve estar indentada;
• Utilizamos o conceito de placeholder (%s) para tornar o valor de x
dinâmico a cada iteração;
• verificamos que a soma de uma variável nela mesma pode ser escrita
de duas formas: x = x + 1 é equivalente a escrever x+ = 1. O mesmo
pode ser feito para subtração.
Deve-se tomar alguns cuidados, no entanto, ao se utilizar o loop WHILE.
Perceba que, enquanto a condição definida não for atingida, ele continuará
executando o código indefinidamente. Se não tivéssemos colocado a operação
x = x + 1 dentro do loop, o valor de x continuaria sendo 1 e o programa
iria continuar imprimindo o valor de x na tela ininterruptamente. É sua
responsabilidade, portanto, evitar que esse tipo de coisa aconteça, para não
"quebrar"o código.
Assim como no IF, podemos utilizar ELSE como uma tarefa alternativa
a ser executada caso a condição definida no WHILE tenha sido atingida. Por
exemplo:
50 CAPÍTULO 2. CONCEITOS BÁSICOS

1 while x < 5:
2 print ( " O valor de x é % s " % x )
3 x = x +1
4 else :
5 print ( " Fim do loop ! " )

Podemos ainda utilizar WHILE e IF em conjunto e também com os co-


mandos PASS e BREAK. Vejamos:
1 x = 0
2 while x < 10:
3 if x == 4:
4 break
5 else :
6 pass
7 print ( " O valor de x é % s " % x )
8 x += 1
9

10 >>>
11 O valor de x é 0
12 O valor de x é 1
13 O valor de x é 2
14 O valor de x é 3

Nesse caso, colocamos uma condição para que quando o loop atingir o
valor 4, ele pare de ser executado. Novamente, atente para o fato de que deve-
se alterar o valor da variável para evitar que o loop fique sendo executado
indefinidamente.

2.7.3 For
O loop FOR é um dos mais utilizados em qualquer linguagem de progra-
mação, dada sua ampla utilidade. Vejamos um exemplo simples:
1 l = [ " Marca 1 " , " Marca 2 " , " Marca 3 " ]
2 for i in l :
3 print ( i )
4

5 >>>
6 Marca 1
7 Marca 2
8 Marca 3
2.7. CONTROLE DE FLUXO (IF, WHILE, FOR) 51

Aqui criamos uma lista com três strings e em seguida construímos um


loop FOR para imprimir cada item da lista l. Perceba, no entanto, a forma
como isso foi feito: o que dissemos para o interpretador na linha for i in l
foi o seguinte: "Para todo item i dentro da lista l...". E aí poderíamos ter
solicitado qualquer tarefa para ser realizada com a lista, mas optamos por
executar a impressão na tela de cada item i.
O uso do i aqui não é obrigatório, podendo ser substituído por qualquer
letra, mas convenciona-se o uso do ”i” por vir de ”índice”. E assim podemos
utilizar o FOR para realizar operações dentro de qualquer estrutura iterativa.
Podemos ainda utilizar vários FOR de maneira aninhada, como no exem-
plo a seguir.
1 x = [1 ,3 ,5 ,7]
2 y = [2 ,4 ,6]
3

4 for i in x :
5 for j in y :
6 z = i*j
7 print ( z )
8 print ( ' ---X - - - ' )
9

10 >>>
11 2
12 4
13 6
14 ---X - - -
15 6
16 12
17 18
18 ---X - - -
19 10
20 20
21 30
22 ---X - - -
23 14
24 28
25 42
26 ---X - - -

Perceba que nesse caso, o primeiro loop percorreu a lista x e o segundo


percorreu a lista y. O que aconteceu aqui: na primeira iteração, o primeiro
item de x foi multiplicado por cada elemento de y e o resultado foi impresso
na tela. Depois, o segundo elemento de x foi multiplicado por cada elemento
52 CAPÍTULO 2. CONCEITOS BÁSICOS

de y e o resultado também foi impresso. E assim por diante, até que não
restassem mais elementos em x.
O loop FOR é riquíssimo e permite uma série de operações em combinação
com outros elementos. Veremos muitos outros exemplos mais adiante.

2.7.4 List Comprehension


Ao se trabalhar com loop FOR para manipular listas, existe uma forma
mais elegante e funcional que pode ser utilizada, chamada List Comprehen-
sion. Para exemplificar, suponha que tenhamos uma lista de números e
queiramos gerar uma segunda lista com os dobros de seus respectivos valo-
res.
1 numeros = [1 , 2 , 3 , 4 , 5]
2

3 # Forma usual :
4 dobros = []
5 for i in numeros :
6 dobros . append ( i *2)
7

8 # Com list comprehension :


9 dobros = [ i * 2 for i in numeros ]
10 print ( dobros )
11 >>> [2 , 4 , 6 , 8 , 10]

As duas formas são equivalentes, porém, percebe-se a economia de código


que se tem ao se utilizar a segunda. Na primeira, tivemos que primeiramente
criar uma lista vazia, depois criar um loop FOR e, dentro de cada iteração,
realizar um append de cada resultado. Com list comprehension, bastou uma
linha de código para realizar a mesma operação.

2.7.5 Operadores Lógicos e de Atribuição


Qualquer que seja o tipo de loop que está sendo criado, podemos ter
interesse em criar regras mais complexas do que simplesmente comparar nú-
meros. Para isso, precisamos de operadores lógicos, como AND, OR ou NOT.
Vejamos alguns exemplos.
2.7. CONTROLE DE FLUXO (IF, WHILE, FOR) 53

1 x = [1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10]
2 for i in x :
3 if i %2 == 0 and i >5:
4 print ( i )
5 >>>
6 6
7 8
8 10
9

10

11 for i in x :
12 if i == 5 or i ==7:
13 print ( i )
14 >>>
15 5
16 7
17

18 y = [3 ,5 ,7]
19 for i in x :
20 if i not in y :
21 print ( i )
22 >>>
23 1
24 2
25 4
26 6
27 8
28 9
29 10

Nestes exemplos simples, criamos estruturas iterativas utilizando FOR


em conjunto com IF e vimos como podemos utilizar esses operadores para
criar algumas regras diferentes. No primeiro caso, o loop só imprimirá valores
pares e maiores do que 5. No segundo, imprimirá apenas se o valor for igual
a 5 ou a 7. E no último, imprimirá qualquer valor da lista x que não está
contida na lista y.
Para finalizar, na tabela 2.6 uma lista de operadores lógicos que podem
ser utilizados nessas expressões:
Também, conforme vimos, existem operadores de atribuição que possuem
formas equivalentes, como x = x + 1 e x+ = 1. A tabela 2.7 apresenta as
demais formas.
54 CAPÍTULO 2. CONCEITOS BÁSICOS

Operador Nome
== Igual a
!= Diferente de
> Maior que
>= Maior ou igual a
< Menor que
<= Menor ou igual a
and "e". Retorna True se ambas as condições
forem verdadeiras.
or "ou". Retorna True se pelo menos uma
condição for verdadeira.
not "não". Retorna False se as condição for
verdadeira.
in "está contido em". Retorna True se o ob-
jeto estiver contido em outro objeto espe-
cificado.

Tabela 2.6: Operadores Lógicos em Python

Operador Forma Equivalente


= x=1
+= x=x+1
−= x=x−1
∗= x=x∗1
/= x = x/1
%= x = x%1

Tabela 2.7: Operadores Lógicos em Python

2.8 Juntando tudo


No exemplo anterior, utilizamos duas estruturas de loop conjuntamente.
Isso é bastante comum e aí começa a entrar a criatividade do programador,
ao combinar os diferentes conceitos aprendidos para realizar suas próprias
operações e solucionar problemas.
Esse capítulo trouxe ao leitor uma série de conceitos que podem ser uti-
lizados em conjunto. Experimente construir seu próprio loop com FOR,
IF e/ou WHILE, utilizando operadores lógicos diferentes, fazendo operaçoes
matemáticas diferentes, utilizando placeholders, listas, dicionários, métodos
e funções vistas até aqui.
Somente a prática leva à perfeição!
2.9. DESAFIO: OPERAÇÕES COM LISTAS 55

2.9 Desafio: Operações com listas


Crie um código Python que execute as seguintes operações:

• Crie uma lista "x"com 10 valores quaisquer;

• Crie uma lista "y"com 7 valores quaisquer;

• Execute as seguintes operações:

a) Pegue o valor na posição 0 de x e adicione com o valor na posição


1 de y;
b) Pegue o valor na posição 5 de x e multiplique pelo valor na posição
3 de y;
c) Pegue o resto da divisão do maior valor de x pelo menor valor de
y;
d) Pegue o valor na posição 7 de x, diminua do valor na posição 0 de
y e eleve ao quadrado;

• Salve todas essas operações em uma nova lista z;

• Para cada valor de z, imprima na tela: "O resultado da operação a) é:


", "O resultado da operação b) é: "e assim por diante.

• Imprima os valores ordenados de z.


56 CAPÍTULO 2. CONCEITOS BÁSICOS
Capítulo 3

Funções e Classes

No capítulo anterior vimos alguns conceitos básicos em Python e desco-


brimos que existem várias funções prontas para uso. Agora verificaremos
algumas das funções mais utilizadas em Python e também como podemos
criar nossas próprias funções.
Também investigaremos o que são Classes e como utilizá-las, já que esse
é um dos conceitos mais utilizados em POO.

3.1 Range
A função range pode ser utilizada em uma série de contextos para criar
uma sequência de números. Ela pode receber 1, 2 ou 3 parâmetros:

• range(n): gera valores de 0 até n-1.

• range (i, n) gera valores de i até n-1.

• range (i, n, p): gera valores de i até n-1, pulando de p em p.

Podemos utilizar então essa função para, por exemplo, criar listas.

57
58 CAPÍTULO 3. FUNÇÕES E CLASSES

1 L1 = list ( range (5) )


2 print ( L1 )
3 >>> [0 , 1 , 2 , 3 , 4]
4

5 L2 = list ( range (3 ,8) )


6 print ( L2 )
7 >>> [3 , 4 , 5 , 6 , 7]
8

9 L3 = list ( range (2 ,11 ,3) )


10 print ( L3 )
11 >>> [2 , 5 , 8]

Poderíamos utilizar essa mesma lógica com o loop FOR, mas sem ne-
cessariamente gerar uma lista, apenas imprimindo o resultado na tela. Por
exemplo:
1 for i in range (5) :
2 print ( i )
3 >>>
4 0
5 1
6 2
7 3
8 4

Perceba, no entanto, que o simples uso de range não gera um objeto do


tipo lista de números. O que o interpretador faz ao executar esse comando
é criar a sequência de números e armazenar na memória. Porém, para utili-
zarmos o resultado, se assim quisermos, devemos necessariamente salvar em
um objeto iterável.

3.2 Map
Em algumas situações, podemos estar interessados em aplicar uma deter-
minada função em um objeto iterável (uma lista ou uma tupla por exemplo).
É exatamente isso que faz a função map. Vejamos um exemplo:
1 x = [1 , -1 , 2 , -2 , 3 , -3]
2 y = list ( map ( abs , x ) )
3 print ( y )
4 > > >[1 , 1 , 2 , 2 , 3 , 3]
3.3. FILTER 59

Neste caso, aplicamos a função abs em cada elemento de x e salvamos


esse resultado (valor absoluto) em uma lista, que foi armazenada na variável
y.
Essa é a sintaxe esperada: map(função, objeto iterável). Com isso, pode-
mos utilizar qualquer função, inclusive criada por nós, para gerar qualquer
resultado que seja desejado, sem a necessidade de criar um loop para isso.
Perceba que, uma vez mais, criamos uma lista para poder visualizar o
resultado. Isso porque o resultado da função é um iterator, ou seja, um
objeto iterável. Novamente, não visualizamos que objeto é esse, mas ele está
na memória do computador.
Por ser um objeto iterável, da mesma forma que utilizamos um FOR para
imprimir o resultado de range na tela na seção anterior, o mesmo poderia
ser feito algo com map. Faça o teste!

3.3 Filter
Seguindo a mesma lógica de aplicar uma função a um objeto iterável,
eventualmente podemos estar interessados em filtrar esse objeto e retornar
apenas aqueles que satisfaçam uma dada condição. Vejamos:
1 lista = [ " 1 " ," 2 " ," 3 " ," Jo ã o " ," Maria " ," Jos é " ," Paula " ]
2 x = list ( filter ( str . isdigit , lista ) )
3 print ( x )
4 >>> [ ' 1 ' , ' 2 ' , ' 3 ' ]
5

6 y = list ( map ( int , x ) )


7 print ( y )
8 >>> [1 , 2 , 3]

Neste exemplo, primeiramente utilizamos filter com a função [Link]


para extrair da lista apenas os valores que eram dígitos. Porém, como pode-
mos perceber, o resultado ainda é uma lista de strings. Utilizamos, então, a
função map com int para converter essas strings em valores inteiros.

3.4 Zip
A função zip é ligeiramente diferente das demais que vimos até agora,
mas também retorna um objeto iterável. Seu objetivo é agrupar pares de
valores de objetos diferentes. Vejamos alguns exemplos.
60 CAPÍTULO 3. FUNÇÕES E CLASSES

1 x = [1 ,2 ,3]
2 y = [4 ,5 ,6]
3 z = [7 ,8 ,9 ,10]
4 result1 = list ( zip (x , y ) )
5 result2 = list ( zip (x , z ) )
6

7 print ( result1 )
8 >>> [(1 , 4) , (2 , 5) , (3 , 6) ]
9

10 print ( result2 )
11 >>> [(1 , 7) , (2 , 8) , (3 , 9) ]

No primeiro resultado, foram combinados exatamente os pares de valores


de x e y da seguinte forma: o primeiro elemento de x com o primeiro de y, o
segundo de x com o segundo de y e assim por diante.
Perceba, no entanto, o que acontece com objetos de tamanhos diferen-
tes: a combinação ocorre até onde é possível. Quando não é mais possível
combinar, os elementos restantes ficam de fora do resultado.

3.5 Enumerate
Em algumas situações, podemos estar interessados em acessar o índice de
um objeto iterável. Para isso, utilizamos a função enumerate. Perceba seu
funcionamento:
1 lista = [ " Primeiro " , " Segundo " , " Terceiro " ]
2 lista_com_indice = list ( enumerate ( lista ) )
3 print ( lista_com_indice )
4 >>> [(0 , ' Primeiro ' ) , (1 , ' Segundo ' ) , (2 , ' Terceiro ' ) ]
3.5. ENUMERATE 61

O que enumerate faz é atribuir um índice a cada elemento do objeto iterá-


vel, sempre começando com 0. Isso é particularmente útil quando queremos,
por exemplo, criar um loop FOR no qual necessitamos acessar o índice. Por
exemplo:
1 notas = [6.5 , 7.0 , 8.2 , 5.9 , 9.1 , 6.8]
2 # Aplica b ô nus de 1 ponto s notas em posi ç õ es í mpares
3 for i , nota in enumerate ( notas ) :
4 if i % 2 == 1:
5 notas [ i ] = min ( nota + 1 , 10.0) # Garante que a
nota n ã o ultrapasse 10
6

7 print ( notas )
8 >>> [6.5 , 8.0 , 8.2 , 6.9 , 9.1 , 7.8]

Esse é um exemplo simples no qual podemos perceber como funciona a


utilização de um loop FOR com essa função. Em um FOR simples, utilizamos
simplesmente ”for i in...”. Agora, porém utilizamos tanto o índice como seu
elemento: ”for i, nota in...”. Vejamos outro exemplo:
1 poligonos =[[[1 , 4] , [15 , 4] , [15 , 20] , [1 , 20]] ,
2 [[8 , 12] , [25 , 8] , [25 , 18]] ,
3 [[2 , 6] , [2 , 1] , [15 , 2] , [20 , 1] , [20 , 6]]]
4 result_pol = []
5

6 for idx_pol , pol in enumerate ( poligonos ) :


7 cat = class_poligono ( poligonos [ idx_pol ])
8 res = f " { idx_pol +1}: { cat } "
9 result_pol . append ( res )

Nesse caso, poligonos tem três listas aninhadas. A primeira linha refere-
se a um polígono, com as listas de coordenadas x e y de seus 4 vértices. O
segundo polígono possui três vértices e o terceiro, 5.
O objetivo do FOR é classificar os polígonos utilizando uma função que
foi criada para isso, chamada class_poligono. Como essa função foi criada
não é importante, mas basta saber que a entrada da função é uma lista de
vértices do polígono.
Perceba então que não basta utilizar diretamente class_poligono(poligonos)
dentro do FOR, pois a função está esperando uma lista de vértices, e não
uma lista de polígonos. Se fizermos isso, o interpretador retornará erro. Ao
utilizamos, no entanto, idx_pol, estaremos passando para a função uma li-
nha de cada vez, ou seja, um polígono de cada vez, que é o que a função está
esperando.
62 CAPÍTULO 3. FUNÇÕES E CLASSES

O loop então utiliza uma f-string para salvar os resultados como strings.
O resultado final será algo como:

1: Simples e Convexo
2: Simples e Não Convexo
3: Não Simples

Sempre que houver a necessidade de iterar pelo índice de um objeto,


devemos utilizar enumerate.

3.6 Criando sua própria função


Em muitas situações, pode ser que não exista uma função nativa ou em
algum pacote para realizar o que desejamos. Nesse caso, podemos criar
nossas próprias funções. Para fazer isso, utiliza-se a palavra reservada def, o
nome da função e quais os parâmetros de entrada, se existirem. Em seguida,
escreve-se as linhas de código necessárias para realizar as operações desejadas
e utiliza-se return para definir qual é o resultado esperado da função.
Para exemplificar de forma simples, vamos criar uma função que verifique
se um número é par.
1 def eh_par ( numero ) :
2 return numero % 2 == 0
3

4 lst = [1 ,2 ,3 ,4 ,5 ,6]
5

6 for i in lst :
7 if eh_par ( i ) :
8 print ( i )
9 else :
10 print ( " N ã o é par " )
11 >>>
12 N ã o é par
13 2
14 N ã o é par
15 4
16 N ã o é par
17 6

Vejamos o que aconteceu aqui. Primeiramente, criamos uma função sim-


ples chamada eh_par, que irá verificar se a divisão por 2 tem resto zero.
Perceba que o resultado dessa função é simplesmente um booleando, ou seja,
irá retornar True ou False.
3.6. CRIANDO SUA PRÓPRIA FUNÇÃO 63

Utilizamos então essa função dentro de um loop FOR com IF para im-
primir os números pares de uma lista. Poderíamos ter feito isso de outras
formas. O loop criado poderia estar dentro da função e seu retorno poderia
ser o próprio print. Tudo depende da forma que o programador achar melhor
de se trabalhar.
Podemos também usar essa função em conjunto com outras funções que
vimos anteriormente. Por exemplo:
1 list ( filter ( eh_par , lst ) )
2 >>> [2 , 4 , 6]

Devemos, no entanto, tomar alguns cuidados ao criar nossas funções. O


primeiro deles é entender a diferença entre variável global e variável local. O
primeiro caso já conhecemos: ao definir uma variável no código, essa variável
pode ser utilizada para qualquer operação em qualquer lugar do código.
No entanto, se declararmos uma variável dentro da função, ela só será
utilizada nas operações daquela função. Perceba a diferença:
1 x = 2
2

3 def teste () :
4 y = 3
5 print ( y )
6

7 print ( x )
8 >>> 2
9

10 print ( y )
11 >>> NameError : name ' y ' is not defined
12

13 teste ()
14 >>> 3

Neste exemplo simples, estamos definindo x como uma variável global e


y como variável local. Prova disso é que se solicitarmos ao interpretador que
imprima o conteúdo de y, ele retorna um NameError, uma vez que y não está
definida. No entanto, se rodarmos a função teste(), onde y está definida,
ele então imprimirá seu conteúdo, pois é isso que a função faz.
Vejamos então um exemplo um pouco mais completo.
64 CAPÍTULO 3. FUNÇÕES E CLASSES

1 def somar_listas ( lista1 , lista2 ) :


2 resultado = [] # vari á vel local para armazenar os
resultados
3

4 for a , b in zip ( lista1 , lista2 ) :


5 soma = a + b # vari á vel local para a soma de
cada par
6 resultado . append ( soma )
7

8 return resultado
9

10 l1 = [1 , 2 , 3 , 4]
11 l2 = [10 , 20 , 30 , 40]
12 somas = somar_listas ( l1 , l2 )
13 print ( somas )
14 >>> [11 , 22 , 33 , 44]

Analisemos com cuidado cada parte desse código:

• Definimos dois parâmetros de entrada: lista1 e lista2.

• Criamos uma variável local, resultado, do tipo lista, que em primeiro


momento está vazia.

• Criamos um FOR com dois elementos. Sim, isso é possível! Até agora
havíamos visto apenas a criação de loops com um elemento, que deno-
távamos por ”i”. Nesse caso, a se refere ao elemento da lista1 e b se
refere ao elemento da lista2.

• A cada iteração, utilizamos o método append para adicionar o resultado


da soma na lista de resultados.

• O retorno da função é a lista de resultados.

Agora você já conhece o suficiente de Python para dar asas à sua ima-
ginação como programador. Revise o conteúdo visto até aqui e use sua
criatividade para criar suas próprias funções!
3.7. EXPRESSÃO LAMBDA 65

3.7 Expressão Lambda


Agora já estamos aptos a criar nossas próprias funções, mas em algumas
situações isso pode não ser necessário. Se quisermos definir uma função para
uma única situação específica, não precisamos definir a função no sentido
tradicional, já que não teremos interesse em utilizá-la novamente.
Para isso, podemos utilizar a expressão lambda, que cria uma função
anônima em tempo de execução.
1 numeros = [1 , 2 , 3 , 4 , 5]
2 dobrados = list ( map ( lambda x : x * 2 , numeros ) )
3 print ( dobrados )
4 >>> [2 , 4 , 6 , 8 , 10]
5

6 impares = list ( filter ( lambda x : x % 2 != 0 , numeros ) )


7 print ( impares )
8 >>> [1 , 3 , 5]

3.8 Classes
Lembra-se de que no primeiro capítulo falamos sobre POO? Pois bem,
tudo o que vimos até agora - variáveis, funções, métodos, atributos - são
objetos. Uma variável do tipo lista, por exemplo, é um objeto que contém
elementos e possui seus próprios métodos e atributos.
As listas, no entanto, são um objeto Python. Não existe no mundo real.
Analogamente, podemos estar interessados em representar objetos do mundo
real dentro do Python. É para isso que existem as classes.
Vamos exemplificar imaginando que desejamos construir um sistema de
gerenciamento de uma biblioteca ou livraria. Se não utilizarmos as classes,
teríamos que manter separadamente as características de cada livro e criar
funções isoladas para controlar as operações que podem ser feitas (venda,
empréstimo, etc.).
Utilizando as classes, no entanto, cria-se uma representação virtual do
que acontece de fato no mundo real, agrupando-se as características e com-
portamentos relacionados com aquele objeto de interesse (livro). Isso torna
o código muito mais limpo e organizado, além de otimizar a eficiência para
adicionar ou modificar funcionalidades.
Continuaremos com esse exemplo para ilustrar como se dá a criação de
classes. Utilizamos a palavra reservada class seguida do nome da classe,
que tradicionalmente se dá com a inicial maiúscula. Isso não é obrigatório,
mas uma convenção para diferenciar classe de função.
66 CAPÍTULO 3. FUNÇÕES E CLASSES

1 class Livro :
2 def __init__ ( self , titulo , autor ) :
3 self . titulo = titulo
4 self . autor = autor
5

6 def infos ( self ) :


7 print ( f ' T í tulo : { self . titulo } , Autor : { self . autor
}')
8

9 l = Livro ( " O Conde de Monte Cristo " , " Alexandre Dumas " )
10 print ( l )
11 >>> < __main__ . Livro object at 0 x000002094D97A460 >
12

13 l . infos ()
14 >>> T í tulo : O Conde de Monte Cristo , Autor : Alexandre
Dumas

Neste exemplo, as linhas 1 a 7 referem-se à construção da classe. Ao


executá-las, não será retornado nada na tela, pois estamos simplesmente
criando um objeto, mas ainda não fizemos nada com ele.
Percebamos, no entanto, tudo que foi feito aqui: A primeira função criada
na linha 2 é chamada de método construtor, pois é justamente ele quem define
a construção da classe, graças à utilização da palavra reservada __initit__.
Neste método inicial, definimos dois atributos para a nossa classe Livro:
título e autor. Em seguida, nas linha 6 e 7, definimos um método para a
nossa classe, que simplesmente imprime na tela os atributos do Livro.
Agora, a classe está pronta para ser utilizada. Com isso, criamos um
objeto l, da classe Livro. Perceba que ao utilizar print(l), o que retorna na
tela é simplesmente a informação de que l é um objeto da classe Livro.
Utilizamos então o método infos e ele executa exatamente o que fora
programado para fazer: imprime na tela as informações do objeto.
Esse é um exemplo simples, mas poderíamos ter criado quantos atribu-
tos e quantos métodos julgássemos necessários. Lembre-se que métodos são
funções, e podem ser bastante simples, como no exemplo ilustrado, quanto
extremamente complexas, fazendo uso das mais variadas operações.
Esses métodos podem ser definidos sem parâmetros, conforme fizemos
inicialmente, ou requerer parâmetros, se isso for necessário. Vejamos um
exemplo:
3.8. CLASSES 67

1 class Livro :
2 def __init__ ( self , cod , titulo , autor ) :
3 self . cod = cod
4 self . titulo = titulo
5 self . autor = autor
6

7 def infos ( self , cod ) :


8 print ( f ' T í tulo : { self . titulo } , Autor : { self . autor
}')
9

10

11 l = Livro ( ' 01 ' , ' O Conde de Monte Cristo ' , ' Alexandre
Dumas ' )
12 l . infos ( ' 01 ' )

Neste caso, criamos um código para o livro, que chamamos apenas de cod,
e exigimos que ele seja passado como parâmetro ao utilizar o método infos.
68 CAPÍTULO 3. FUNÇÕES E CLASSES

3.8.1 Herança e Polimorfismo


Uma das maiores vantagens em se utilizar uma linguagem de POO é o
conceito de herança, que permite a reutilização de classes. Para entender
um pouco melhor, vamos pensar que nossa classe Livro é, na verdade, um
caso particular de uma classe maior, chamada Publicação.
1 class Publicacao :
2 def __init__ ( self , titulo , autor , ano ) :
3 self . titulo = titulo
4 self . autor = autor
5 self . ano = ano
6

7 def exibir_info ( self ) :


8 print ( f " T í tulo : { self . titulo } " )
9 print ( f " Autor : { self . autor } " )
10 print ( f " Ano : { self . ano } " )
11

12 class Livro ( Publicacao ) :


13 def __init__ ( self , titulo , autor , ano , isbn , paginas )
:
14 super () . __init__ ( titulo , autor , ano ) # chama o
construtor da classe m ã e
15 self . isbn = isbn
16 self . paginas = paginas
17

18 def exibir_info ( self ) :


19 super () . exibir_info () # reutiliza o m é todo da
classe m ã e
20 print ( f " ISBN : { self . isbn } " )
21 print ( f " P á ginas : { self . paginas } " )

Veja que a utilização é bastante simples, bastando referenciar a classe


mãe na construção da classe filha e os métodos e atributos criados na classe
pai podem se reutilizados. Nesse exemplo, foram acrescentados os atributos
de isbn e número de páginas, mas os demais não precisaram ser recriados.
Outro conceito bastante utilizado é o de polimorfismo, no qual um
método de mesmo nome pode ter diferentes comportamentos a depender da
subclasse. Vejamos:
3.8. CLASSES 69

1 class Publicacao :
2 def __init__ ( self , titulo , autor , ano ) :
3 self . titulo = titulo
4 self . autor = autor
5 self . ano = ano
6

7 def resumo ( self ) :


8 return f " { self . titulo } , por { self . autor } ({ self .
ano }) "
9

10 class Livro ( Publicacao ) :


11 def __init__ ( self , titulo , autor , ano , isbn ) :
12 super () . __init__ ( titulo , autor , ano )
13 self . isbn = isbn
14

15 def resumo ( self ) :


16 return f " Livro : { self . titulo } - ISBN { self . isbn } "
17

18 class Revista ( Publicacao ) :


19 def __init__ ( self , titulo , autor , ano , edicao ) :
20 super () . __init__ ( titulo , autor , ano )
21 self . edicao = edicao
22

23 def resumo ( self ) :


24 return f " Revista : { self . titulo } - Edi ç ã o { self .
edicao } "
25

26 publicacoes = [
27 Livro ( " 1984 " , " George Orwell " , 1949 , " 9780451524935 " )
,
28 Revista ( " National Geographic " , " V á rios " , 2023 , "
Agosto " ) ,
29 Livro ( " Dom Casmurro " , " Machado de Assis " , 1899 , "
1234567890 " )
30 ]
31

32 for item in publicacoes :


33 print ( item . resumo () )
34 >>>
35 Livro : 1984 - ISBN 9780451524935
36 Revista : National Geographic - Edi ç ã o Agosto
37 Livro : Dom Casmurro - ISBN 1234567890
70 CAPÍTULO 3. FUNÇÕES E CLASSES

Perceba que o método foi definido de maneira diferente para Livro e para
Revista, mas isso não importa: ao invocarmos o método, ele se comportará
de acordo com o esperado.

3.8.2 Outras Características


Por conta do Python ser uma linhagem do POO, as classes criadas permi-
tem ainda o uso de outras características. Uma delas é o encapsulamento, no
qual podemos utilizar os prefixos _ e __ antes do nome de um atributo ou
método para defini-lo como protegido ou reservado, respectivamente. Atri-
butos privados não podem ser acessados ou modificados diretamente fora da
classe, necessitando de métodos específicos para tal.
Também existem os chamados métodos mágicos, que permitem ainda a
execução de outras tarefas específicas, mas não falaremos deles aqui. Ao leitor
interessado em se aprofundar na programação POO voltada para construção
de sistemas ou aplicativos, recomendamos que pesquise sobre o assunto.
É claro que os exemplos vistos neste capítulo são didáticos e na prática,
as coisas funcionam de forma diferente, pois você terá uma interface com
usuário, irá salvar os dados em um banco de dados e terá outras estruturas
que fazem para de um sistema completo.
Em uma situação real, serão criados métodos para coletar os dados de
uma interface e salvar no banco, ou para exibir os resultados do banco em
uma interface. Não é nosso foco entrar nesses detalhes, mas falaremos um
pouco melhor disso no capítulo ***.

3.9 Desafio: Criando uma nova classe


Desenvolver uma classe que represente uma playlist de músicas, per-
mitindo adicionar, remover e analisar as faixas usando funções nativas do
Python.
Crie uma classe chamada Playlist que represente uma lista de músicas.
Cada música pode ser representada como um dicionário com os seguintes
campos: - titulo (str) - artista (str) - duracao (int, em segundos)
A classe deve conter um atributo faixas, que é uma lista de músicas e os
métodos:

• adicionar_musica(musica): adiciona uma música à playlist.

• remover_musica(titulo): remove a música com o título informado.

• duracao_total(): retorna a soma das durações das músicas.


3.9. DESAFIO: CRIANDO UMA NOVA CLASSE 71

• musica_mais_longa(): retorna a música com maior - maior duração.

• listar_musicas(): imprime os títulos em ordem alfabética.

• quantidade_musicas(): retorna o número de faixas.

Use funções nativas do Python para facilitar os cálculos e ordenações.


Explore como sum, max, len e sorted podem ser aplicadas para criar os
métodos solicitados.
72 CAPÍTULO 3. FUNÇÕES E CLASSES
Capítulo 4

Módulos, Pacotes e Bibliotecas

Em várias linguagens, é comum a construção de componentes externos


que agrupem coleções de funções sobre um determinado determinado tema,
como por exemplo: cálculos aritméticos, ferramentas estatísticas, funções
gráficas, etc.
Em Python, esses componentes recebem os nomes de módulos, pacotes
ou bibliotecas. Embora corriqueiramente esses termos sejam utilizados como
sinônimos, eles não são exatamente a mesma coisa. A tabela 4.1 explica um
pouco melhor essas diferenças.

Nome Descrição Exemplo


Módulo É um arquivo único (.py) que contém math, random
funções e variáveis utilizáveis.
Pacote É uma coleção de módulos organi- [Link], [Link]
zados em pastas, com um arquivo
__init__.py
Biblioteca É um termo mais abrangente, usado numpy, pandas, scikit-learn
para se referir a um conjunto de módu-
los e pacotes, geralmente pensado como
uma solução completa para certo domí-
nio.

Tabela 4.1: Diferença entre Módulo, Pacote e Biblioteca.

Nesse capítulo falaremos sobre os componentes mais utilizados e para que


servem.

73
74 CAPÍTULO 4. MÓDULOS, PACOTES E BIBLIOTECAS

4.1 Trabalhando com Componentes Externos


Antes de se importar um componente - seja ele módulo, pacote ou bi-
blioteca - e utilizar suas funções, primeiramente é preciso instalá-lo. Isso é
feito simplesmente invocando o comando pip install no console (terminal
ou prompt de comando). Por exemplo:
1 pip install numpy
2 pip install pandas

Se você está utilizando o IDE RStudio ou Positron, provavelmente está


usando também o pacote reticulate para poder rodar os códigos em Python.
Nesse caso, há outros comandos que podem ser utilizados no ambiente R:
1 reituculate :: py_install ( " pandas " )
2 # ou
3 reituculate :: py_require ( " pandas " )

Com o componente instalado, agora sim ele pode ser utilizado. Para
realizar a importação do mesmo, utilizamos a função import, que pode ou
não vir seguida de um apelido (alias) para facilitar seu uso. Por exemplo:
1 import numpy as np

Após a importação, você pode usar o nome do componente ou seu apelido


seguido por . para verificar quais são as suas funções. Evidentemente, con-
sultar a documentação do componente sempre é recomendado para entender
o que ele faz e quais são suas funções, variáveis, etc.

Figura 4.1: Exemplo de importação da biblioteca NumPy e seus métodos.

Sempre que desejamos utilizar uma função específica de um componente,


podemos utilizar essa notação de [Link]ção. Por isso, costumeiramente
atribui-se o apelido de forma abreviada, facilitando seu uso. Mas também
4.2. MATH E STATISTICS 75

podemos importar funções específicas, com from pacote import função.


Por exemplo:
1 # Exemplo utilizando alias
2 import numpy as np
3 np . concatenate ()
4

5 # Exemplo importando apenas a fun ç ã o de interesse


6 from numpy import concatenate
7 concatenate ()
8

9 # Importanto todas as fun ç õ es da biblioteca


10 from numpy import *

A forma de utilização dos componentes e suas funções depende muito


do objetivo de cada script. Pode parecer complicado para quem nunca teve
contato com nenhuma linguagem de programação, mas os casos de uso ficarão
mais claro na medida em que nos aprofundarmos nos próximos exemplos.

4.2 Math e Statistics


Algumas operações aritméticas não estão disponíveis no Python nativa-
mente, porém o pacote math pode nos auxiliar com isso. A seguir alguns
exemplos de uso:
76 CAPÍTULO 4. MÓDULOS, PACOTES E BIBLIOTECAS

1 import math
2 # Raiz Quadrada
3 math . sqrt (9)
4

5 # # Exponencial
6 math . exp ( -1)
7

8 # Logaritmo base 10
9 math . log10 (20)
10

11 # Logaritmo Natural
12 math . log (20)
13

14 # Fatorial
15 math . factorial (5)
16

17 # Seno
18 math . sin (9)
19

20 # Coseno
21 math . cos (8)
22

23 # Tangente
24 math . tan (7)
4.3. FUNCTOOLS 77

Da mesma forma, o pacote statistics dispõe do principal ferramental


estatístico.
1 import statistics as stats
2 # M é dia
3 stats . mean ( data )
4

5 # Desvio Padr ã o
6 stats . stdev ( data )
7

8 # Mediana
9 stats . median ( data )
10

11 # Moda
12 stats . mode ( data )
13

14 # Quartis
15 stats . quantiles ( data , n =4)

4.3 Functools
Esse módulo traz várias funções úteis similares a outras que já vimos
anteriormente, como range, map e filter. Vejamos algumas.

4.3.1 Função Reduce


A função reduce faz exatamente o que o nome sugere: reduz um conjunto
de números a apenas um, aplicando-se uma função pré-definida. A sintaxe é
bastante similar ao da função map que vimos anteriormente.
1 from functools import reduce
2 l = [12 , 19 , 45 , 67]
3 reduce ( lambda a , b : a +b , l )
4 > > >143

Neste exemplo fizemos várias operações. Primeiramente, do pacote functools,


importamos apenas a função reduce. Em seguida criamos uma lista e uti-
lizamos a expressão lambda para criar uma função anônima em tempo de
execução, evitando assim a necessidade de criar uma função que somasse
dois números. E perceba que na mesma linha, utilizamos essa função para
reduzir a lista l a apenas um número.
Nesse caso, optamos por criar uma função que somasse os números, mas
poderíamos ter criado qualquer outra, ou utilizado uma função existente.
78 CAPÍTULO 4. MÓDULOS, PACOTES E BIBLIOTECAS

4.3.2 Função Partial


Se quisermos criar uma função com argumentos já definidos, podemos
utilizar a função partial.

1 from functools import partial


2 def multiplicar (a , b ) :
3 return a * b
4

5 dobro = partial ( multiplicar , 2)


6 print ( dobro (5) )
7 >>> 10

Exemplo bastante simples, mas que pode ser útil em algumas situações.

4.3.3 Função cmp_to_key


Essa função não é muito usual, mas pode ser utilizada para ordernar uma
lista a partir de um critério específico que não simplesmente ordem crescente,
decrescente ou alfabética.
Suponha, por exemplo, que dentro de uma lista numérica, queiramos
ordenar primeiramente os números pares antes dos ímpares e dentro de cada
grupo, em ordem crescente. Podemos então criar uma função para isso e
utilizar cmp_to_key para executar a comparação.

1 from functools import cmp_to_key


2 def comparar (a , b ) :
3 # Pares v ê m antes dos í mpares
4 if a % 2 == 0 and b % 2 != 0:
5 return -1
6 elif a % 2 != 0 and b % 2 == 0:
7 return 1
8 else :
9 return a - b # ordem crescente dentro do grupo
10

11 lista = [5 , 2 , 9 , 1 , 4 , 7]
12 ordenada = sorted ( lista , key = cmp_to_key ( comparar ) )
13 print ( ordenada )
14 >>> [2 , 4 , 1 , 5 , 7 , 9]
4.4. NUMPY 79

4.4 NumPy
O NumPy é uma das bibliotecas mais utilizadas em Python para ope-
rações matemáticas com arrays. Esses são objetos diferentes daqueles que
vimos anteriormente - listas, tuplas e dicionários - pois permitem armazenar
e manipular coleções de dados de forma eficiente.
Um array pode ser entendido como uma tabela de elementos do mesmo
tipo. Cada item ocupa uma posição ordenada, e o acesso a qualquer elemento
é feito diretamente pelo índice. Isso garante velocidade e previsibilidade, duas
características essenciais em cálculos numéricos de grande escala.
Os arrays podem ser de uma dimensão (vetor), duas dimensões (matriz)
ou até três dimensões (coleção de matrizes). É claro que quanto maior a
dimensão, maior a complexidade.
A principal diferença entre arrays e listas é que essas últimas, embora
flexíveis, não são otimizadas para operações matemáticas e quando se precisa
realizar esse tipo de tarefa, pode haver um alto custo de memória. Com
arrays, no entanto, isso já não acontece, pois eles foram projetados para lidar
com coleções homogêneas e realizar cálculos de maneira muito mais eficiente.
A tabela 4.2 resume as principais diferenças entre essas duas estruturas.
Mais detalhes sobre o NumPy e sua respectiva documentação podem ser
encontrados em [Link]
No Python puro, existe o módulo array, que permite criar arrays ho-
mogêneos. Entretanto, seu uso é restrito e menos comum. Para ciência de
dados, estatística e aprendizado de máquina, a comunidade científica adota
o NumPy, que fornece arrays n-dimensionais poderosos e uma enorme varie-
dade de funções matemáticas.
Iniciado em 2006, o NumPy utiliza um objeto de array multidimensional
e oferece diversas funções e ferramentas para trabalhar com esses arrays.
Além disso, o NumPy pode ser facilmente integrado a outros pacotes do
ecossistema Python e oferece recursos para interação com outras linguagens
de programação, como C e C++.
Veremos a seguir alguns exemplos de utilização.
80 CAPÍTULO 4. MÓDULOS, PACOTES E BIBLIOTECAS

# Lista Array
1 A lista é usada para coletar itens Um array também é um compo-
que geralmente consistem em ele- nente importante que coleta vá-
mentos de múltiplos tipos de da- rios itens do mesmo tipo de dado.
dos.
2 A lista não consegue realizar ope- O array consegue realizar opera-
rações aritméticas. ções aritméticas.
3 A lista pode conter elementos de O array contém elementos que
diferentes tipos de dados. pertencem ao mesmo tipo de
dado.
4 Em termos de flexibilidade, a lista Em termos de flexibilidade, o ar-
é perfeita, pois permite fácil mo- ray não é tão adequado, já que
dificação dos dados. não permite modificações tão fá-
ceis.
5 Consome mais memória. Consome menos memória que
uma lista.
6 Em uma lista, todos os elementos Em um array, é obrigatório usar
podem ser acessados sem a neces- um loop para acessar os compo-
sidade de um loop específico. nentes.
7 É mais adequado para sequências É mais adequado para sequências
curtas de dados. longas de dados.

Tabela 4.2: Diferenças entre Listas e Arrays.


4.4. NUMPY 81

4.4.1 Operações com Arrays


Criar um array NumPy é bastante simples e, partir dele, podemos realizar
inúmeras operações.
1 import numpy as np
2 a = np . array ([1 , 2 , 3 , 4 , 5])
3 b = np . array ([5 , 6 , 7 , 8 , 9])
4

5 a *2
6 >>> array ([ 2 , 4, 6, 8 , 10])
7

8 b /2
9 >>> array ([2.5 , 3. , 3.5 , 4. , 4.5])
10

11 a*b
12 >>> array ([ 5 , 12 , 21 , 32 , 45])

Perceba a diferença de resultados se compararmos com as operações com


listas. Se a fosse uma lista e multiplicássemos ela por 2, o resultado seria
apenas uma repetição da lista.
Com o NumPy, entretanto, os objetos gerados (vetores) permitem opera-
ções matemáticas vetorizadas, ou seja, cada elemento do array é multiplicado
por 2. É justamente essa característica que torna os arrays tão úteis em cál-
culos numéricos.
A função ‘[Link]()‘ também permite definir arrays de várias dimensões.
Por exemplo:
1 b = np . array ([[1 , 2] , [3 , 4]])
2 print ( b )
3 >>>
4 [[1 2]
5 [3 4]]

Nesse caso, temos uma matriz 2x2. Essa generalização para dimensões
maiores é a base para manipulação de dados em estatística, imagens, sinais
e até redes neurais.
Uma das vantagens do NumPy é o controle sobre o tipo dos dados. É
possível especificar que um array deve ser inteiro, ponto flutuante ou mesmo
valores complexos. Isso garante consistência e evita erros ao realizar opera-
ções matemáticas em larga escala.
82 CAPÍTULO 4. MÓDULOS, PACOTES E BIBLIOTECAS

1 # array de inteiros
2 arr_int = np . array ([1 , 2 , 3 , 4] , dtype = int )
3 print ( " Inteiros : " , arr_int , " | Tipo : " , arr_int . dtype )
4 >>> Inteiros : [1 2 3 4] | Tipo : int32
5

6 # array de floats
7 arr_float = np . array ([1 , 2 , 3 , 4] , dtype = float )
8 print ( " Floats : " , arr_float , " | Tipo : " , arr_float . dtype )
9 >>> Floats : [1. 2. 3. 4.] | Tipo : float64
10

11 # array de n ú meros complexos


12 arr_complex = np . array ([1 , 2 , 3 , 4] , dtype = complex )
13 print ( " Complexos : " , arr_complex , " | Tipo : " , arr_complex .
dtype )
14 >>> Complexos : [1.+0. j 2.+0. j 3.+0. j 4.+0. j ] | Tipo :
complex128

4.4.2 Fatiamento
Assim como nas listas, o acesso aos elementos de um array NumPy é feito
por índices.
1 # Criando um array NumPy
2 a = np . array ([10 , 20 , 30 , 40 , 50 , 60])
3

4 # Acesso por í ndice


5 print ( " Primeiro elemento ( a [0]) : " , a [0])
6 >>> 10
7

8 print ( " Terceiro elemento ( a [2]) : " , a [2])


9 >>> 30
10

11 # Slicing
12 print ( " Elementos de í ndice 1 at é 3 ( a [1:4]) : " , a [1:4])
13 >>> [20 30 40]
14

15 print ( " Todos os elementos a partir do í ndice 2 ( a [2:]) : " ,


a [2:])
16 >>> [30 40 50 60]
17

18 print ( " Elementos at é o í ndice 3 ( a [:4]) : " , a [:4])


19 >>> [10 20 30 40]
4.4. NUMPY 83

Além do slicing tradicional, o NumPy oferece seleção por máscaras boole-


anas. Isso significa que podemos criar condições e extrair apenas os elementos
que as satisfazem. Esse recurso é essencial em análises estatísticas e filtragem
de dados.
1 a = np . array ([1 , 2 , 3 , 4 , 5 , 6])
2

3 # M á scara booleana : elementos maiores que 2


4 masc = a > 2
5 print ( " M á scara booleana : " , masc )
6 >>> M á scara booleana : [ False False True True True
True ]
7

8 # Usando a m á scara para filtrar elementos


9 print ( " Elementos maiores que 2: " , a [ masc ])
10 >>> Elementos maiores que 2: [3 4 5 6]
11

12 # Outro exemplo : n ú meros pares


13 print ( " Elementos pares : " , a [ a % 2 == 0])
14 >>> Elementos pares : [2 4 6]

4.4.3 Operações Matriciais


Os arrays NumPy também permitem operações matriciais. A multipli-
cação entre matrizes pode ser feita com @ ou com a função [Link](). Isso
aproxima o NumPy da álgebra linear tradicional e conecta Python a áreas
como estatística multivariada e aprendizado de máquina.
1 # Definindo duas matrizes 2 x2
2 A = np . array ([[1 , 2] ,
3 [3 , 4]])
4 B = np . array ([[5 , 6] ,
5 [7 , 8]])
6

7 # Multiplica ç ã o matricial
8 print ( " A @ B =\ n " , A @ B )
9 >>>A @ B =
10 [[19 22]
11 [43 50]]
12 print ( " np . dot (A , B ) =\ n " , np . dot (A , B ) )
13 >>> np . dot (A , B ) =
14 [[19 22]
15 [43 50]]
84 CAPÍTULO 4. MÓDULOS, PACOTES E BIBLIOTECAS

Outra característica fundamental é a capacidade de manipular a forma


(shape) dos arrays. Com reshape(), podemos transformar um vetor de
tamanho 6 em uma matriz 2x3. Essa flexibilidade é útil para reorganizar
dados de acordo com a análise desejada.
1 # Criando um array 1 D ( vetor ) com 6 elementos
2 a = np . array ([1 , 2 , 3 , 4 , 5 , 6])
3 print ( " Shape original : " , a . shape )
4 >>> Shape original : (6 ,)
5

6 # Transformando em uma matriz 2 x3


7 b = a . reshape (2 , 3)
8 print ( " \ nArray reshape para 2 x3 :\ n " , b )
9 >>>
10 Array reshape para 2 x3 :
11 [[1 2 3]
12 [4 5 6]]
13

14 print ( " Novo shape : " , b . shape )


15 >>>
16 Novo shape : (2 , 3)
17

18 # Tamb é m podemos criar uma matriz 3 x2


19 c = a . reshape (3 , 2)
20 print ( " \ nArray reshape para 3 x2 :\ n " , c )
21 >>>
22 Array reshape para 3 x2 :
23 [[1 2]
24 [3 4]
25 [5 6]]

Há também o broadcasting, que é um mecanismo do NumPy que permite


realizar operações matemáticas entre arrays de tamanhos ou formas diferen-
tes, sem escrever laços explícitos. Em vez de duplicar os dados, o NumPy
“expande virtualmente” os arrays menores para que tenham a mesma forma
que os maiores, aplicando a operação elemento a elemento.
1 A = np . array ([[1 , 2 , 3] ,
2 [4 , 5 , 6]])
3 b = np . array ([10 , 20 , 30])
4 print ( A + b )
5 >>>
6 [[11 22 33]
7 [14 25 36]]
4.4. NUMPY 85

4.4.4 Manipulando Arrays


Há diversas operações que podemos realizar para manipular os dados dos
arrays. Vejamos alguns exemplos.
1 # Substituindo valor em um vetor .
2 a = np . array ([1 ,2 ,3 ,4 ,5 ,6])
3 a [0] = 10
4 print ( a )
5 >>> [10 2 3 4 5 6]
6

7 # Substituindo valor em uma matriz .


8 A [0 ,0] = 10
9 print ( A )
10 >>>
11

12 [[10 2 3]
13 [ 4 5 6]]
14

15 arr = np . array ([[1 , 2 , 3] ,


16 [4 , 5 , 6]])
17

18 # Adicionar nova linha


19 nova_linha = np . array ([[7 , 8 , 9]])
20 arr_expandido = np . vstack (( arr , nova_linha ) )
21 print ( " \ nArray ap ó s adicionar nova linha :\ n " ,
arr_expandido )
22 >>>
23 Array ap ó s adicionar nova linha :
24 [[1 2 3]
25 [4 5 6]
26 [7 8 9]]
86 CAPÍTULO 4. MÓDULOS, PACOTES E BIBLIOTECAS

1 # Concatenar arrays
2 outro_arr = np . array ([[10 , 11 , 12]])
3 concatenado = np . concatenate (( arr_expandido , outro_arr ) ,
axis =0)
4 print ( " \ nArray ap ó s concatenar outro array :\ n " ,
concatenado )
5 >>>
6 Array ap ó s concatenar outro array :
7 [[ 1 2 3]
8 [ 4 5 6]
9 [ 7 8 9]
10 [10 11 12]]
11

12 # Removendo a primeira coluna


13 removido = np . delete ( concatenado , 0 , axis =1)
14 print ( " \ nArray ap ó s remover a primeira coluna :\ n " ,
removido )
15 >>>
16 Array ap ó s remover a primeira coluna :
17 [[ 2 3]
18 [ 5 6]
19 [ 8 9]
20 [11 12]]
21

22 # Removendo a ú ltima linha


23 removido2 = np . delete ( removido , -1 , axis =0)
24 print ( " \ nArray ap ó s remover a ú ltima linha :\ n " , removido2
)
25 >>>
26 Array ap ó s remover a ú ltima linha :
27 [[2 3]
28 [5 6]
29 [8 9]]

4.4.5 Funções Matemáticas


Um dos pontos fortes do NumPy é a grande coleção de funções mate-
máticas prontas para uso. Operações como soma, média, desvio padrão,
logaritmos e exponenciais podem ser aplicadas diretamente ao array inteiro,
sem a necessidade de laços de repetição. Isso deixa o código mais limpo e
muito mais rápido.
4.4. NUMPY 87

1 b = np . array ([1 , 2 , 3 , 4])


2 print ( " Exponencial : " , np . exp ( b ) )
3 >>> Exponencial : [ 2.71828183 7.3890561 20.08553692
54.59815003]
4

5 print ( " Logaritmo : " , np . log ( b ) )


6 >>> Logaritmo : [0. 0.69314718 1.09861229
1.38629436]
7

8 print ( " Raiz quadrada : " , np . sqrt ( b ) )


9 >>> Raiz quadrada : [1. 1.41421356 1.73205081 2.
]
10

11 a = np . array ([1 , 2 , 3 , 4 , 5])


12 print ( " Soma : " , np . sum ( a ) )
13 >>> Soma : 15
14

15 print ( " M é dia : " , np . mean ( a ) )


16 >>> M é dia : 3.0
17

18 print ( " Vari â ncia : " , np . var ( a ) )


19 >>> Vari â ncia : 2.0
20

21 print ( " Desvio padr ã o : " , np . std ( a ) )


22 >>> Desvio padr ã o : 1.4142135623730951
23

24 print ( " M í nimo : " , np . min ( a ) )


25 >>> M í nimo : 1
26

27 print ( " M á ximo : " , np . max ( a ) )


28 >>> M á ximo : 5
88 CAPÍTULO 4. MÓDULOS, PACOTES E BIBLIOTECAS

4.4.6 Além do NumPy


Apesar do NumPy ser, conforme já foi comentado, a biblioteca mais utili-
zada para operações numéricas, existem outras. Podemos citar, por exemplo,
o SymPy, elaborada para matemática simbólica, com resolução de equações,
cálculo diferencial e integral, gradientes, laplacianos e diversas outras funções
de Matemática avançada, Física e Engenharia.
E há também outra biblioteca construída sobre o NumPy, o SciPy, cri-
ada para processamento de sinais e imagens, engenharia e estatística. Pos-
sui funções de distribuições de probabilidade, testes estatísticos, geração de
amostras, otimização, álgebra linear, integração, interpolação, etc. Veremos
o SciPy em maiores detalhes em capítulo específico.

4.5 Pandas
Pandas é um nome derivado de “Panel Data”, um termo de econometria
para dados multidimensionais. Iniciado em 2008 por Wes McKinney, o Pan-
das é uma biblioteca de código aberto de alto desempenho para manipulação
e análise de dados em Python.
Utiliza principalmente seus objetos DataFrame (estrutura de dados ta-
bular bidimensional com rótulos) e Series (unidimensional com rótulos), e
oferece um conjunto vasto de ferramentas para trabalhar com essas estrutu-
ras.
Fornece recursos para limpeza de dados, filtragem, agrupamento (group
by), junção (merge/join), tratamento de dados ausentes e análise de séries
temporais. Sua documentação está disponível em
[Link]

4.5.1 Dataframe - Conceitos Iniciais


A estrutura mais básica e importante do Pandas é o DataFrame, sobre
o qual são realizadas todas as operações necessárias. Uma instância do tipo
DataFrame é um objeto de duas (ou mais) dimensões com as seguintes ca-
racterísticas:

• Suas dimensões podem ser modificadas decorrente da modificação dos


dados.

• Possui rótulos para linhas e colunas, ao invés de exclusivamente por


índices.
4.5. PANDAS 89

• Pode conter diferentes tipos de dados (numéricos, strings, booleanos,


etc.) em diferentes colunas.

Um DataFrame é construído sobre os arrays do NumPy, mas adiciona fun-


cionalidades para a análise de dados reais. A tabela 4.3 resume as principais
diferenças entre as duas estruturas.

Característica Array (NumPy) DataFrame (Pandas)


Tipos de Dados Homogêneo: todos os ele- Heterogêneo: colunas po-
mentos do mesmo tipo. dem ter tipos diferentes (nú-
meros, texto, etc.).
Rótulos (Índices) Acesso por índices numéri- Rótulos explícitos para li-
cos (ex: ‘array[0, 1]‘). nhas (‘index‘) e colunas
(‘columns‘).
Dados Faltantes Suporte básico com Funções robustas e inte-
‘[Link]‘. gradas para tratar dados
faltantes (ex: ‘fillna()‘,
‘dropna()‘).
Uso Principal Computação numérica e ál- Manipulação, limpeza e
gebra linear. O "motor". análise de dados tabulares.
O "veículo".
Flexibilidade Tamanho fixo após a cria- Tamanho pode ser alterado
ção. (novas colunas/linhas po-
dem ser adicionadas).

Tabela 4.3: Comparação entre Array e DataFrame

A classe DataFrame da biblioteca pandas possui um método construtor


com alguns parâmetros:

• data: recebe os dados em formato de lista, dicionário ou até um Data-


Frame.

• index: recebe uma string que define os rótulos das linhas.

• columns: recebe uma string que define os rótulos das colunas.

• dtype: recebe um tipo de dados com intuito de forçar a conversão em


DataFrame. Por padrão, esse parâmetro é none e os tipos são inferidos
automaticamente.
90 CAPÍTULO 4. MÓDULOS, PACOTES E BIBLIOTECAS

4.5.2 Criação e Atributos de um DataFrame


Existem diversas maneiras de criar um DataFrame do pandas. Vejamos
algumas.
1 import pandas as pd
2

3 # DataFrame a partir de uma lista de tuplas


4 nomes = [ ' Ana ' , ' Bruno ' , ' Carla ' ]
5 idades = [23 , 35 , 29]
6 dados = list ( zip ( nomes , idades ) )
7 print ( dados )
8 >>> [( ' Ana ' , 23) , ( ' Bruno ' , 35) , ( ' Carla ' , 29) ]
9

10 df = pd . DataFrame ( dados )
11 print ( df )
12 >>>
13 0 1
14 0 Ana 23
15 1 Bruno 35
16 2 Carla 29
17

18 # DataFrame a partir de um dicion á rio


19 dados = { ' Nome ' : [ ' Ana ' , ' Bruno ' , ' Carla ' ] ,
20 ' Idade ' : [23 , 35 , 29]}
21 df = pd . DataFrame ( dados )
22

23 # DataFrame a partir de r ó tulos personalizados


24 dados = [( ' Ana ' , 23) , ( ' Bruno ' , 35) , ( ' Carla ' , 29) ]
25 colunas = [ ' Nome ' , ' Idade ' ]
26 linhas = [ ' A ' , ' B ' , ' C ' ]
27 df = pd . DataFrame ( dados , columns = colunas , index = linhas )
28 print ( df )
29 >>>
30 Nome Idade
31 A Ana 23
32 B Bruno 35
33 C Carla 29

Perceba que no último exemplo a estrutura é a mesma, porém as colunas e


linhas já foram nomeadas através de rótulos pré-definidos. Isso também pode
ser feito posteriormente à criação do DataFrame, utilizando-se os métodos
columns e index.
4.5. PANDAS 91

1 # Modificando os r ó tulos das colunas


2 df . columns = [ ' Nome ' , ' Idade ' ]
3 # Modificando os r ó tulos das linhas
4 df . index = [ ' A ' , ' B ' , ' C ' ]

Objetos do tipo DataFrame possuem diversos atributos que são bastante


úteis:

• index: retorna os rótulos das linhas em formato de lista.

• columns: retorna os rótulos das colunas em formato de lista.

• ndim: retorna o número de dimensões do DataFrame.

• shape: retorna uma tupla com o número de linhas e colunas do Data-


Frame.

• size: retorna o número total de elementos do DataFrame.

• dtypes: retorna os tipos de dados de cada coluna do DataFrame.

• empty: retorna True se o DataFrame estiver vazio e False caso contrá-


rio.

Vejamos alguns exemplos de uso a partir do DataFrame que criamos nos


exemplos anteriores:
1 print ( list ( df . index ) ) # R ó tulos das linhas
2 >>> [ ' A ' , ' B ' , ' C ' ]
3 print ( list ( df . columns ) ) # R ó tulos das colunas
4 >>> [ ' Nome ' , ' Idade ' ]
5 print ( df . ndim ) # N ú mero de dimens õ es
6 >>> 2
7 print ( df . shape ) # N ú mero de linhas e colunas
8 >>> (3 , 2)
9 print ( df . size ) # N ú mero total de elementos
10 >>> 6
11 print ( df . empty ) # Verifica se o DataFrame est á vazio
12 >>> False
92 CAPÍTULO 4. MÓDULOS, PACOTES E BIBLIOTECAS

4.5.3 Indexação
Diferentemente dos arrays do NumPy, os dados de um DataFrame podem
ser acessados tanto pelos rótulos (índices) quanto pelos índices numéricos. A
forma de acessar um dado de um DataFrame é a seguinte:
dataframe[<coluna>][<linha>].
Em nosso exemplo:
1 print ( df [0][0] , df [0][1] , df [0][2])
2 >>> Ana Bruno Carla

Além disso, existem métodos que também facilitam acesso os dados:


• .T[]: Transpõe o DataFrame (troca linhas por colunas).
• .loc[]: Acessa dados por rótulos (índices).
• .iloc[]: Acessa dados por posições (índices numéricos).
• .at[]: Acessa um único valor por rótulo.
• .iat[]: Acessa um único valor por posição.
Vejamos como eles podem ser utilizados.
1 # DF original
2 print ( df )
3 >>>
4 Nome Idade
5 A Ana 23
6 B Bruno 35
7 C Carla 29
8 # DF transposto
9 print ( df . T )
10 >>>
11 A B C
12 Nome Ana Bruno Carla
13 Idade 23 35 29
14 # Acessa o valor na linha ' C ' e coluna ' Nome '
15 df . at [ ' C ' , ' Nome ' ]
16 >>> ' Carla '
17 # Acessa o valor na linha ' A ' e coluna ' Idade '
18 df . at [ ' A ' , ' Idade ' ]
19 >>> 23
20 # Acessa o valor da linha 2 na coluna 0
21 print ( df . iat [2 , 0])
22 # Carla
4.5. PANDAS 93

É preciso ter atenção, contudo, ao utilizar o método at. Esse indexador


opera apenas nos rótulos e não nos índices dos elementos. Caso os índices
sejam fornecidos ao invés dos rótulos, um erro será gerado.
Para acessar os dados a partir dos índices, deve ser utilizado o método
iat, conforme explicitado no último exemplo. O mesmo vale para loc e
iloc.
1 print ( df . loc [[ ' B ' ,' C ' ]])
2 >>>
3 Nome Idade
4 B Bruno 35
5 C Carla 29
6 # Acessa as linhas ' A ' e ' C ' e a coluna ' Nome '
7 print ( df . loc [[ ' A ' ,' C ' ] , [ ' Nome ' ]])
8 Nome
9 A Ana
10 C Carla
11 # Acessa a linha ' B ' e as colunas ' Nome ' e ' Idade '
12 print ( df . loc [ ' B ' , [ ' Nome ' , ' Idade ' ]])
13 Nome Bruno
14 Idade 35
15 Name : B , dtype : object
16

17 print ( df . loc [[ True , False , True ] , ' Nome ' ])


18 A Ana
19 C Carla
20 Name : Nome , dtype : object
21 # Acessa a linhas nas posi ç õ es 1 e 2
22 print ( df . iloc [[1 , 2]])
23 Nome Idade
24 B Bruno 35
25 C Carla 29
26 # Acessa a ú ltima linha do DataFrame
27 print ( df . iloc [ -1])
28 Nome Carla
29 Idade 29
30 Name : C , dtype : object
31 # Acessa as linhas nas posi ç õ es 0 e 2 e a coluna na posi ç
ão 0
32 print ( df . iloc [[0 , 2] , [0]])
33 Nome
34 A Ana
35 C Carla
94 CAPÍTULO 4. MÓDULOS, PACOTES E BIBLIOTECAS

4.5.4 Manipulando Dados


Seguindo do mesmo exemplo, veremos a seguir como podemos realizar
algumas operações de manipulação do DataDrame. Vejamos como podemos
adicionar colunas naquele mesmo objeto.
1 print ( df )
2 >>>
3 Nome Idade
4 A Ana 23
5 B Bruno 35
6 C Carla 29
7

8 # Adiciona uma nova coluna ' Cidade ' com valor padr ã o
9 df [ ' Cidade ' ] = ' S ã o Paulo '
10 print ( df )
11 >>>
12 Nome Idade Cidade
13 A Ana 23 S ã o Paulo
14 B Bruno 35 S ã o Paulo
15 C Carla 29 S ã o Paulo
16

17 # Modifica a coluna ' Cidade ' com novos valores


18 df [ ' Cidade ' ] = [ ' S ã o Paulo ' , ' Rio de Janeiro ' , ' Belo
Horizonte ' ]
19 print ( df )
20 >>>
21 Nome Idade Cidade
22 A Ana 23 S ã o Paulo
23 B Bruno 35 Rio de Janeiro
24 C Carla 29 Belo Horizonte

Para adicionar novas linhas a um DataFrame, podemos usar o método


[Link](). Esse método concatena dois ou mais DataFrames ao longo de
um eixo (linhas ou colunas).
4.5. PANDAS 95

1 # Concatenando por linha


2 dados1 = [( ' Ana ' , 21 , ' F ' ) , ( ' Bruno ' , 20 , ' M ' ) ]
3 df1 = pd . DataFrame ( data = dados1 , columns =[ ' Nome ' , ' Idade
' ,' Sexo ' ])
4 dados2 = [ { ' Nome ' : ' Carla ' , ' Idade ' : 22 , ' Sexo ' : ' F ' } , {
' Nome ' : ' Daniel ' , ' Idade ' : 18 , ' Sexo ' : ' M ' } ]
5 df2 = pd . DataFrame ( data = dados2 )
6 df3 = pd . concat ([ df1 , df2 ] , ignore_index = True )
7 print ( df3 )
8 >>>
9 Nome Idade Sexo
10 0 Ana 21 F
11 1 Bruno 20 M
12 2 Carla 22 F
13 3 Daniel 18 M
14

15 # Concatenando por coluna


16 dados1 = [( ' Ana ' , 21) , ( ' Bruno ' , 20) ]
17 df1 = pd . DataFrame ( data = dados1 , columns =[ ' Nome ' , ' Idade
' ])
18 dados2 = [( ' F ' ) , ( ' M ' ) ]
19 df2 = pd . DataFrame ( data = dados2 , columns =[ ' Sexo ' ])
20 df3 = pd . concat ([ df1 , df2 ] , axis =1)
21 print ( df3 )
22 >>>
23 Nome Idade Sexo
24 0 Ana 21 F
25 1 Bruno 20 M

Para remover linhas ou colunas de um DataFrame, podemos usar o mé-


todo drop(). Esse método retorna um novo DataFrame com as linhas ou
colunas especificadas removidas. Alguns dos parâmetros mais comuns do
método drop() são:

• index: rótulos das linhas a serem removidas.

• columns: rótulos das colunas a serem removidas.

• inplace: se True, modifica o DataFrame original; se False (padrão),


retorna um novo DataFrame.
96 CAPÍTULO 4. MÓDULOS, PACOTES E BIBLIOTECAS

1 print ( df )
2 >>>
3 Nome Idade Cidade
4 A Ana 23 S ã o Paulo
5 B Bruno 35 Rio de Janeiro
6 C Carla 29 Belo Horizonte
7

8 # Remove a linha com r ó tulo ' B ' no DataFrame original


9 df . drop ( index =[ ' B ' ] , inplace = True )
10 print ( df )
11 >>>
12 Nome Idade Cidade
13 A Ana 23 S ã o Paulo
14 C Carla 29 Belo Horizonte

4.5.5 Operadores e Ordenação


Os mesmos operadores que vimos anteriormente (aritméticos, lógicos,
comparativos) podem ser usados pelo pandas para realizar operações em
suas colunas.
1 print ( df1 )
2 >>>
3 Nome Idade Sexo
4 0 Ana 21 F
5 1 Bruno 20 M
6 2 Carla 22 F
7 3 Daniel 18 M
8

9 # Incrementar a idade em 1
10 df1 [ ' Idade ' ] += 1
11 print ( df1 )
12 >>>
13 Nome Idade Sexo
14 0 Ana 22 F
15 1 Bruno 21 M
16 2 Carla 23 F
4.5. PANDAS 97

A aplicação de operadores lógicos em colunas junto com o indexador


loc[] permite a seleção de dados em um DataFrame de forma ágil. Como
vimos anteriormente, o resultado da aplicação de um operador lógico em
uma coluna é uma lista de valores booleanos (True/False). Essa lista pode
ser usada para selecionar linhas específicas de um DataFrame.
1 # Verificar quais pessoas do DataFrame s ã o do sexo
masculino
2 list ( df1 [ ' Sexo ' ] == ' M ' )
3 >>>> [ False , True , False , True ]
4

5 # Usando o indexador para trazer os dados


6 df1 . loc [ df1 [ ' Sexo ' ] == ' M ' ]
7 >>>
8 Nome Idade Sexo
9 1 Bruno 21 M
10 3 Daniel 19 M

Para ordená-lo, podemos usar o método sort_values(), que retorna um


novo DataFrame ordenado com base nos valores de uma ou mais colunas.
Esse método também possui alguns parâmetros bastante úteis, tais como:

• axis: define o eixo para ordenação (0 para linhas, 1 para colunas).


Padrão é 0.

• ascending: se True (padrão), ordena em ordem crescente; se False,


ordena em ordem decrescente.

• kind: define o tipo de ordenação (ex: ’quicksort’, ’mergesort’, etc.).


Padrão é ’quicksort’.

• inplace: se True, modifica o DataFrame original; se False (padrão),


retorna um novo DataFrame.

Suponha que queiramos ordenar o DataFrame anterior. Podemos fazer


isso de várias formas.
98 CAPÍTULO 4. MÓDULOS, PACOTES E BIBLIOTECAS

1 # Ordenando por Idade . Por padr ão , a ordem ser á


ascendente .
2 df1 . sort_values ( by = ' Idade ' )
3 >>>
4 Nome Idade Sexo
5 3 Daniel 19 M
6 1 Bruno 21 M
7 0 Ana 22 F
8 2 Carla 23 F
9

10 # Ordenando pelo í ndice em rodem descendente .


11 df1 . sort_index ( ascending = False )
12 >>>
13 Nome Idade Sexo
14 3 Daniel 19 M
15 2 Carla 23 F
16 1 Bruno 21 M
17 0 Ana 22 F

4.5.6 Outros Métodos


O Pandas possui diversos métodos para realizar operações estatísticas nas
colunas dos DataFrames, oferecendo uma alternativa mais prática do que os
métodos dados pelo Stats ou pelo NumPy ao se trabalhar com DataFrames.
A seguir listamos os mais comuns:

• mean(): calcula a média dos valores.

• median(): calcula a mediana dos valores.

• std(): calcula o desvio padrão dos valores.

• var(): calcula a variância dos valores.

• min(): retorna o valor mínimo.

• max(): retorna o valor máximo.

• sum(): calcula a soma dos valores.

• count(): conta o número de valores não nulos.

• describe(): gera estatísticas descritivas resumidas.


4.5. PANDAS 99

Além dos métodos estatísticos, também podemos citar outros bastante


úteis para manipulação de DataFrames.

• head(n): retorna as primeiras n linhas do DataFrame.

• tail(n): retorna as últimas n linhas do DataFrame.

• info(): exibe um resumo conciso do DataFrame, incluindo o número


de entradas, colunas, tipos de dados e uso de memória.

• value_counts(): conta a frequência de valores únicos em uma coluna.

• isnull(): retorna um DataFrame booleano indicando a presença de


valores nulos.

• dropna(): remove linhas ou colunas com valores nulos.

• fillna(value): preenche valores nulos com um valor especificado.

• apply(func): aplica uma função ao longo de um eixo do DataFrame


(linhas ou colunas).

• groupby(by): agrupa o DataFrame por uma ou mais colunas e permite


a aplicação de funções agregadas.

O pandas também oferece métodos para realizar operações matriciais,


como soma, subtração, multiplicação e divisão. Elas podem ser realizadas
entre DataFrames ou entre um DataFrame e um escalar.
As operações são realizadas elemento por elemento, ou seja, cada elemento
do DataFrame é operado com o elemento correspondente do outro DataFrame
ou com o escalar. Algumas das operações mais comuns são:

• add(): soma dois DataFrames ou um DataFrame e um escalar.

• sub(): subtrai dois DataFrames ou um DataFrame e um escalar.

• mul(): multiplica dois DataFrames ou um DataFrame e um escalar.

• div(): divide dois DataFrames ou um DataFrame e um escalar.

• pow(): eleva os elementos de um DataFrame a uma potência especifi-


cada.

• eq(): verifica a igualdade entre dois DataFrames ou entre um Data-


Frame e um escalar.
100 CAPÍTULO 4. MÓDULOS, PACOTES E BIBLIOTECAS

• ne(): verifica a desigualdade entre dois DataFrames ou entre um Da-


taFrame e um escalar.

• dot(): realiza o produto escalar entre dois DataFrames.

• to_numpy: transforma o DataFrame em uma matriz NumPy.

Vamos criar um novo DataFrame para utilizar os métodos que calculam


a média e o desvio padrão.
1 dados = {
2 ' Nome ' : [ ' Ana ' , ' Bruno ' , ' Carla ' , ' Daniel ' , ' Eva ' ] ,
3 ' Matem á tica ' : [85 , 92 , 78 , 90 , 88] ,
4 ' F í sica ' : [80 , 95 , 82 , 88 , 91] ,
5 ' Qu í mica ' : [78 , 89 , 85 , 87 , 90]
6 }
7 df = pd . DataFrame ( dados )
8 print ( df )
9 >>>
10 Nome Matem á tica F í sica Qu í mica
11 0 Ana 85 80 78
12 1 Bruno 92 95 89
13 2 Carla 78 82 85
14 3 Daniel 90 88 87
15 4 Eva 88 91 90
16

17 # Calculando a m é dia e o desvio padr ã o e salvando em um


novo DataFrame
18 medias = list ( df [[ ' Matem á tica ' ,' F í sica ' ,' Qu í mica ' ]]. mean
() )
19 desviosp = list ( df [[ ' Matem á tica ' ,' F í sica ' ,' Qu í mica ' ]]. std
() )
20 mean_std = pd . DataFrame ([ medias , desviosp ] , columns =[ '
Matem á tica ' ,' F í sica ' ,' Qu í mica ' ] , index =[ ' M é dia ' ,'
Desvio Padr ã o ' ])
21 print ( mean_std )
22 >>>
23 Matem á tica F í sica Qu í mica
24 M é dia 86.600000 87.200000 85.800000
25 Desvio Padr ã o 5.458938 6.220932 4.764452
4.6. MATPLOTLIB 101

E a seguir alguns exemplos de operações matriciais.


1 df1 = pd . DataFrame ([ [19 , 23 , 34] ,
2 [15 , 55 , 60] ,
3 [7 , 32 , 15] ])
4

5 df2 = pd . DataFrame ([ [2 , 3 , 4] ,
6 [5 , 6 , 7] ,
7 [8 , 9 , 10] ])
8 df3 = df1 . add ( df2 ) # Soma df1 e df2
9 print ( df3 )
10 >>>
11 0 1 2
12 0 21 26 38
13 1 20 61 67
14 2 15 41 25
15

16 df4 = df1 . mul (2) # Multiplica df1 por 2


17 print ( df4 )
18 >>>
19 0 1 2
20 0 38 46 68
21 1 30 110 120
22 2 14 64 30

Evidentemente que o pandas não se limita às funções apresentadas aqui.


Utilizaremos essa biblioteca amplamente ao longo dos próximos capítulos,
mas de maneira alguma os exemplos aqui abordados serão exaustivos. Veja
a documentação, pesquise, aplique em seus próprios problemas. Como já
dissemos anteriormente, o pandas é uma das bibliotecas de Python mais
poderosa que existe. Use-a!

4.6 Matplotlib
Para encerrar essa primeira visão geral dos componentes mais utilizados
em Ciência de Dados, iremos explorar um pouco duas bibliotecas gráficas
mais conhecidas. A primeira delas é Matplotlib, que possui uma série de mó-
dulos específicos para cada função, sendo o mais comum o chamado pyplot,
justamente por permitir a plotagem de gráficos de maneira simples e intui-
tiva.
Com poucas linhas de código podemos criar gráficos rapidamente, com
controle sobre títulos, eixos, legendas, cores, estilos de linha, etc. Justa-
102 CAPÍTULO 4. MÓDULOS, PACOTES E BIBLIOTECAS

mente por isso é que daremos maior enfoque nesse módulo, importando-o da
seguinte forma:
1 import matplotlib . pyplot as plt

Apesar de ser o módulo mais utilizado, existem outros, que permitem um


controle mais detalhado sobre as capacidades do Matplotlib. Não veremos
esses outros módulos em detalhes mas, a título de conhecimento, a tabela 4.5
relaciona alguns deles.

Módulo Função Principal


[Link] Criação e manipulação de objetos de fi-
gura.
[Link] Controle detalhado dos eixos e sub-
plots.
[Link] Criação de animações interativas e ex-
portáveis.
[Link] Manipulação de cores e mapas de cores
personalizados.
[Link] Exibição e manipulação de imagens.
[Link] Aplicação de estilos predefinidos aos
gráficos.
[Link] Interface com diferentes backends grá-
ficos (TkAgg, Qt5Agg, etc.).

Tabela 4.4: Módulos do Matplotlib

Também é possível utilizar estilos pré-definidos para os gráficos, ou até


mesmo criar o seu próprio estilo. Use o comando [Link] para
ver os estilos disponíveis e depois implemente os exemplos que utilizaremos
aqui (alguns foram extraídos de VanderPlas (2025)) em estilos diferentes.
Para usar o estilo clássico, por exemplo, use [Link](’classic’).
Antes de começarmos, é importante também explicar o uso do comando
[Link](). A depender da IDE que você esteja utilizando, esse comando
pode não ser necessário, mas estaremos utilizando ele mesmo assim. Geral-
mente, ao executar a partir de um script, o comando será requerido, pois
ele procura todos os objetos do tipo figure que estão ativos e então gera o
gráfico desejado.
Se você está utilizando comandos diretamente do console/terminal ou do
Jupyter Notebook, por exemplo, ele não será necessário. Teste a execução
com e sem o comando e veja se ele funciona para você.
4.6. MATPLOTLIB 103

4.6.1 Gráficos de Linha


Vamos utilizar um exemplo simples gerando uma sequência de números
pelo NumPy e então plotando as curvas do seno e cosseno dessa variável
arbitrária criada.
1 import numpy as np
2 import matplotlib . pyplot as plt
3

4 # Criando uma sequ ê ncia de n ú meros


5 x = np . linspace (0 ,10 ,100)
6

7 # Criando o gr á fico
8 plt . figure ()
9 plt . plot (x , np . sin ( x ) , ' -' , label = ' seno ' , color = ' blue ' )
10 plt . plot (x , np . cos ( x ) , ' --' , label = ' coseno ' , color = ' orange
')
11 plt . title ( ' Seno e Cosseno de X ' )
12 plt . xlabel ( " X " )
13 plt . ylabel ( " Curvas " )
14 plt . legend ()
15 plt . show ()

O código do exemplo irá gerar o gráfico apresentado na figura 4.2. Ana-


lisemos cada comando para entender o que foi solicitado ao interpretador.
O primeiro comando apenas indica o início de comandos gráficos e cria
uma área onde a figura será construída. Poderíamos ter salvo a figura cri-
ada em uma variável, fazendo por exemplo fig = [Link](), mas isso
não é necessário por enquanto. Esse comando pode ser útil se quiseremos
manipular a figura gerada diretamente, como salvá-la através do comando
[Link](), mas como a maioria das IDEs já suporta nativamente ma-
neiras de gerar arquivos em diferentes formatos a partir das figuras geradas,
não nos preocuparemos com isso.
O comando plot já especifica que o gráfico gerado será o gráfico de linhas.
Geramos então a primeira linha especificando os parâmetros dos dois eixos
- x e sin(x) - o que por si só já seria suficiente para plotar o gráfico. No
entanto, podemos personalizá-lo da maneira que julgarmos mais interessante.
Definimos o tipo da linha com ’-’, seu rótulo com label e sua cor com
color. Depois, adicionamos uma segunda linha onde y agora é cos(x) e a
personalizamos com os mesmos parâmetros.
Por fim, definimos outros parâmetros gerais para o gráfico, que sempre
são importantes. Os títulos dos eixos são definidos com xlabel e ylabel e
a legenda é invocada com legend e utiliza os rótulos previamente definidos
104 CAPÍTULO 4. MÓDULOS, PACOTES E BIBLIOTECAS

Figura 4.2: Exemplo de Gráfico de Linhas

nos labels de cada linha. Por fim, [Link]() é o comando que junta
todos os comandos prévios e gera os gráficos. Lembrando que, conforme dito
anteriormente, isso pode não ser necessário na IDE que você está trabalhando.
Podemos ainda dividir a área do gráfico em subplots. Vejamos o exemplo
a seguir.
1 plt . figure ()
2 plt . subplot (2 ,1 ,1) # Linhas , colunas , n ú mero do painel
3 plt . plot (x , np . sin ( x ) )
4 plt . subplot (2 ,1 ,2)
5 plt . plot (x , np . cos ( x ) )
6 plt . show ()

Poderíamos ainda ter adicionado uma grade com grid, controlando sua
transparência com alpha (o que também pode ser aplicado a outros objetos da
figura). Por exemplo: [Link](True, alpha = 0.3), lynestile=’:’.
Há uma infinidade de comandos que podem ser utilizados para ajustar
o gráfico gerado. Não faremos exemplos de todas as possibilidades, mas
listaremos a seguir alguns comandos úteis.
4.6. MATPLOTLIB 105

Figura 4.3: Exemplo de Subplots

Comando Resultado
linestyle=’solid’ ou ’-’ Linha sólida
linestyle=’dashed’ ou ’–’ Linha tracejada
linestyle=’dashdot’ ou ’-.’ Linha com traço e ponto
linestyle=’dotted’ ou ’:’ Linha pontilhada
’-g’ Combinação de estilo e cor. No
caso, sólido e verde (green). Pode
ser usado c para ciano, r para red,
e assim por diante.
[Link](li, ls) Limite de escala para eixo x. Ex:
[Link](-1,11)
[Link](li, ls) Limite de escala para eixo y.
Tabela 4.5: Comandos para personalizar gráficos de linha
106 CAPÍTULO 4. MÓDULOS, PACOTES E BIBLIOTECAS

4.6.2 Gráfico de Dispersão


Gráficos de dispersão são particularmente úteis quando desejamos ver a
relação entre duas variáveis e tentar identificar padrões. Com o Matplotlib,
isso pode ser feito com o comando scatter.
1 # Gerar n ú meros aleat ó rios de x e y a partir de uma
Distribui ç ã o Normal
2 rng = np . random . default_rng (0)
3 x = rng . normal ( size =100)
4 y = rng . normal ( size =100)
5

6 # Plotar o gr á fico
7 plt . figure ()
8 plt . scatter (x , y , marker = ' o ' , s =100 , alpha =0.8 , c = ' gray ' )
9 plt . show ()

Figura 4.4: Exemplo de Gráfico de Dispersão

Nesse exemplo, o parâmetro marker define o formato visual de cada ponto.


Por exemplo:

• ’o’: círculo (padrão);

• ’s’: quadrado;
4.6. MATPLOTLIB 107

• ’∧’: triângulo para cima;


• ’v’: triângulo para baixo;
• ’*’: estrela;
• ’p’: pentágono;
• ’P’: cruz preenchida;
• ’X’: X simples;
• ’+’: cruz simples
Já os parâmetros s, alpha e c controlam o tamanho, transparência e a
cor respectivamente. Vá em frente: altere esses parâmetros e veja o que
acontece!

4.6.3 Histograma
Ao se fazer uma análise descritiva de dados de interesse, utilizamos o
histograma para verificar como esses dados são distribuídos. A criação desse
tipo de gráfico pelo Matplotlib é bastante simples, através do comando hist.
1 rng = np . random . default_rng (100)
2 data = rng . normal ( size =1000)
3 plt . figure ()
4 plt . hist ( data , bins =30 , density = True , histtype = ' ba r ' ,
color = ' steelblue ' , edgecolor = ' black ' )
5 plt . show ()

Para o histograma, o comando bins controle em quantas classes queremos


agrupar os dados e density normaliza os dados, plotando sua densidade ao
invés dos dados brutos se for utilizado True. Os tipos de histograma são
definidos por histtype e podem ser:
• ’bar’: barras tradicionais verticais (padrão).
• ’barstacked’: barras empilhadas.
• ’step’: linhas em forma de escada e sem preenchimento.
• ’stepfilled’: linhas em forma de escada com preenchimento entre os
degraus.
E finalmente, edgecolor controla a cor da borda das barras, que pode
ser ’None’ se você preferir um histograma sem bordas.
108 CAPÍTULO 4. MÓDULOS, PACOTES E BIBLIOTECAS

Figura 4.5: Exemplo de Histograma

4.6.4 Boxplot
Uma alternativa comum ao histograma é o boxplot, que além de mostrar
a dispersão dos dados, também nos permite ver o resumo de cinco números.
Vejamos um exemplo comparando 3 boxplots diferentes.
1 # Gerando dados simulados
2 np . random . seed (42)
3 grupo_A = np . random . normal ( loc =50 , scale =10 , size =100)
4 grupo_B = np . random . normal ( loc =60 , scale =15 , size =100)
5 grupo_C = np . random . normal ( loc =55 , scale =20 , size =100)
6

7 # Criando o boxplot
8 plt . figure ()
9 plt . boxplot ([ grupo_A , grupo_B , grupo_C ] , labels =[ ' Grupo A
' , ' Grupo B ' , ' Grupo C ' ])
10 plt . title ( ' Distribui ç ã o dos Grupos ' )
11 plt . ylabel ( ' Valores ' )
12 plt . grid ( True )
13 plt . show ()

Lembrando como se interpretar um boxplot: as linhas de baixo e de


cima representam o mínimo e o máximo, respectivamente, sem considerar
os outliers. Na caixa, a linha inferior representa o primeiro quartil, a linha
4.6. MATPLOTLIB 109

Figura 4.6: Exemplo de Boxplot

interna representa a média e a linha superior representa o terceiro quartil.


Se houver pontos para cima ou para baixo das linhas de mínimo e máximo,
esses são considerados outliers.

4.6.5 Gráficos de Barra e Setor


Frequentemente precisamos comparar categorias e verificar a distribuição
de dados em cada uma delas. O gráfico mais indicado para esse tipo de análise
é o gráfico de barras, enquanto que os gráficos de setor (também chamados de
gráficos de "pizza"ou "torta") são menos recomendados pois podem acabar
enviesando a análise. No entanto, quando há poucas categorias a serem
comparadas e a distribuição entre elas é similar, esse gráfico pode surgir
como uma alternativa eficaz.
110 CAPÍTULO 4. MÓDULOS, PACOTES E BIBLIOTECAS

1 categorias = [ ' A ' , ' B ' , ' C ' , ' D ' ]


2 valores = [25 , 35 , 20 , 20]
3 cores = [ ' red ' , ' green ' , ' blue ' , ' orange ' ]
4

5 # Gr á fico de Barras
6 plt . figure ()
7 plt . bar ( categorias , valores , color = cores )
8 plt . title ( ' Distribui ç ã o por Categoria ' )
9 plt . xlabel ( ' Categorias ' )
10 plt . ylabel ( ' Valores (%) ' )
11 plt . grid ( axis = ' y ' )
12 plt . show ()
13

14 # Gr á fico de Setor
15 plt . figure ()
16 plt . pie ( valores , labels = categorias , autopct = ' %1.1 f %% ' ,
startangle =90)
17 plt . title ( ' Distribui ç ã o por Categoria ' )
18 plt . axis ( ' equal ' ) # Mant é m o c í rculo perfeito
19 plt . show ()

Figura 4.7: Exemplo de Gráfico de Barra


4.6. MATPLOTLIB 111

Figura 4.8: Exemplo de Gráfico de Setor

Para usar os gráficos de barras empilhadas, os comandos são ligeiramente


diferentes.
1 import numpy as np
2 base = np . array ([30 , 40 , 20 , 10])
3 extra = np . array ([20 , 15 , 10 , 5])
4 labs = [ " Q1 " ," Q2 " ," Q3 " ," Q4 " ]
5

6 plt . figure ( figsize =(7 ,4) )


7 plt . bar ( labs , base , label = " Base " )
8 plt . bar ( labs , extra , bottom = base , label = " Extra " )
9 plt . title ( " Barras empilhadas " )
10 plt . legend ()
11 plt . show ()
112 CAPÍTULO 4. MÓDULOS, PACOTES E BIBLIOTECAS

Figura 4.9: Exemplo de Gráfico de Barras Empilhadas

4.6.6 Anotações e Setas


Muitas vezes pode ser útil incluir na figura setas e anotações para destacar
algum ponto de interesse. Podemos fazer isso com o comando annotate.
Vejamos um exemplo.
1 x = np . linspace (0 , 2* np . pi , 256)
2 plt . figure ( figsize =(7 ,4) )
3 plt . plot (x , np . sin ( x ) )
4 plt . ylim (( -1 ,1.5) )
5 plt . annotate ( " Pico " , xy =( np . pi /2 , 1) , xytext =(2.2 , 1.2) ,
6 arrowprops = dict ( arrowstyle = " ->" ) )
7 plt . title ( " Usando annotate para destacar pontos " )
8 plt . show ()
4.6. MATPLOTLIB 113

Figura 4.10: Exemplo de uso do Annotate


114 CAPÍTULO 4. MÓDULOS, PACOTES E BIBLIOTECAS

4.7 Seaborn
O Matplotlib foi criado mais de uma década antes do pandas, de maneira
que suas versões iniciais apresentavam dificuldades em se visualizar dados
em dataframes, além de propiciar interfaces limitadas. Apesar da biblioteca
ter se adaptado aos novos tempos, o Seaborn acabou surgindo como uma
alternativa e oferece uma ampla gama de opções gráficas para Ciência de
Dados.
Essa nova biblioteca foi construída em cima do Matplotlib, de maneira
que ambas são necessárias para plotar os gráficos mais sofisticados. Vejamos
alguns exemplos utilizando o conjunto de dados ’tips’, que já vem embutido
com o Seaborn.
1 # Dadaset de gorjetas
2 df = sns . load_dataset ( ' tips ' )
3

4 # Gr á fico de dispers ã o com linha de regress ã o


5 plt . figure ()
6 sns . lmplot ( x = ' total_bill ' , y = ' tip ' , data = df )
7 plt . title ( ' Rela ç ã o entre Conta Total e Gorjeta ' )
8 plt . show ()
9

10 # Boxplot por dia da semana


11 plt . figure ()
12 sns . boxplot ( x = ' day ' , y = ' total_bill ' , data = df , palette = '
Set2 ' )
13 plt . title ( ' Distribui ç ã o da Conta por Dia da Semana ' )
14 plt . show ()
15

16 # Contagem de fumantes por sexo


17 plt . figure ()
18 sns . countplot ( x = ' sex ' , hue = ' smoke r ' , data = df , palette = '
pastel ' )
19 plt . title ( ' Fumantes por Sexo ' )
20 plt . show ()

Seaborn oferece atalhos estatísticos, colormaps padrão e temas consisten-


tes, enquanto Matplotlib dá controle fino de cada elemento. Dessa forma,
utiliza-se o Seaborn para explorar e Matplotlib para lapidar.
4.7. SEABORN 115

Figura 4.11: Gráfico de Dispersão com linha de regressão

Figura 4.12: Boxplot por dia da semana


116 CAPÍTULO 4. MÓDULOS, PACOTES E BIBLIOTECAS

Figura 4.13: Fumantes por sexo


4.8. DESAFIO: CONSTRUINDO SEU PRÓPRIO MÓDULO 117

4.8 Desafio: Construindo seu próprio Módulo


Escreva um código em um arquivo .py para criar funções estatísticas.
Você pode usar todo o conhecimento adquirido até aqui e integrá-lo com
outros módulos e pacotes. Seu arquivo deve conter funções capazes de realizar
as seguintes operações:

1. Resumo de 5 números.

2. Cálculo de variância e desvio padrão.

3. Plotagem de histograma, boxplot e gráfico de dispersão.

4. Cálculo de média móvel.

5. Execução de um teste T para comparação de 2 conjuntos de dados.

Depois de concluído, teste seu módulo contra conjuntos de dados diferen-


tes. Como sugestão, você pode usar os datasets disponíveis no repositório
[Link]
118 CAPÍTULO 4. MÓDULOS, PACOTES E BIBLIOTECAS
Capítulo 5

Boas Práticas em Programação

Até esse capítulo, o leitor foi municiado de uma série de conceitos en-
volvendo a linguagem Python, para que soubesse o mínimo necessário para
iniciar sua jornada dentro do vasto universo da Ciência de Dados.
Antes de avançarmos para esse assunto, no entanto, cabe chamarmos
atenção para um tópico frequentemente ignorado em muitos materiais bibli-
ográficos sobre o tema, mas que faz toda a diferença em seu desempenho
profissional.
Nesse capítulo abordaremos algumas das boas práticas ao se desenvolver
códigos que serão usados para scritps ou sistemas. Evidentemente que es-
sas práticas podem ser adotadas em qualquer linguagem, mas naturalmente
daremos enfoque maior no Python.

5.1 Preâmbulo
Todo script em Python deve começar com as seguintes linhas:
1 # !/ usr / bin / env python3
2 # -* - coding : utf -8 -* -

A primeira é chamada de shebang ou hashbang e garante que o script pode


rodar em um terminal ou console. O caminho definido localiza o interpretador
do Python na máquina do usuário. Já a segunda é chamada de encondig
declaration e informa ao interpretador que está se utilizando no script a
codificação UTF-8. Essas linhas também podem ser chamadas de magic
comment, por serem comentários que acabam tendo algum efeito junto ao
interpretador da linguagem.
Também é comum sempre começar o script com um comentário com
informações sobre a função do mesmo, autor e data de criação. Por exemplo:

119
120 CAPÍTULO 5. BOAS PRÁTICAS EM PROGRAMAÇÃO

1 '''
2 Script para execu ç ã o de ETL nos dados de vendas do
Sistema XYZ .
3 Autor : Jos é da Silva .
4 Criado em agosto /2025.
5 '''

5.2 Solicitando dados do usuário


Em algumas situações podemos estar interessados em solicitar dados de
um usuário final. Isso para alguma interface web na qual queiramos, por
exemplo, coletar dados, tratá-los e retornar análises estatísticas sobre eles.
Isso pode ser feito com o uso da função input. Vejamos um exemplo:
1 entrada = []
2

3 while True :
4 ent = input ()
5 if not entrada : # Verificar se o usu á rio apenas
pressionou ' Enter '
6 break
7 else :
8 entrada . append ( ent )

Nesse script simples, o usuário digitará no console quantos valores ele


quiser, até simplesmente digitar ENTER e encerrar a inserção. Os dados
digitados então serão salvos em uma lista que chamamos de entrada.

5.3 Tratamento de erros e exceções


É bastante óbvio que antes de colocar qualquer script em produção para
ser executado, ele será testado várias vezes para garantir que está sendo feito
o que se espera. No entanto, dificilmente controlamos fatores externos ao que
acontece no script.
Mudanças em bancos de dados, usuários digitando coisas que não devem,
erros de execução... tudo isso podem nos causar problemas. É uma boa
prática, portanto, programar o script de maneira que ele nos informe quando
houver um erro de execução. É o que chamamos de exceptions.
Peguemos o exemplo anterior no qual solicitamos dados do usuário. Agora,
vamos criar uma função para realizar essa operação e, dentro dessa função,
5.4. DADOS DE CONEXÃO A BANCOS DE DADOS 121

adicionaremos a função try para acusar um erro em caso de exceção do có-


digo. Nesse exemplo, trataremos como exceção qualquer situação na qual o
usuário digite um valor diferente de números inteiros.
1 def ler_entrada () :
2 entrada = []
3 print ( " Digite valores inteiros ( pressione ENTER sem
digitar nada para finalizar ) : " )
4

5 while True :
6 ent = input ()
7 if ent == " " : # Se o usu á rio apenas pressionar
ENTER , encerra
8 break
9 try :
10 valor = int ( ent )
11 entrada . append ( valor )
12 except ValueError :
13 print ( " Entrada inv á lida . Insira apenas
valores inteiros . " )
14

15 return entrada

Perceba que se o usuário digitar qualquer coisa diferente de inteiro, o


Python retornará erro, pois a variável valor só aceita inteiros. No entanto, ao
invés de deixar o Python retornar um erro de valor sem especificar exatamente
qual é o problema, personalizamos nossa mensagem de erro para explicar ao
usuário o que está sendo feito de errado.
Essa lógica de tratamento de erros e exceções é útil em diversas situações,
incçusive para geração de logs. Suponha que tenhamos um script rodando
em um servidor através de uma rotina diária, semanal ou mensal. E por
algum motivo, verificamos que a operação esperada para a qual o script fora
programado não aconteceu.
Através dos logs que gravaram as mensagens de erro das exceções, po-
demos rastrear a causa do problema. O próprio Python possui um módulo
nativo chamado logging para fazer isso. Combine suas funções com o tra-
tamento de erros e seu script ficará bastante funcional.

5.4 Dados de conexão a Bancos de Dados


No capítulo *** veremos como utilizar Python em conjunto com SQL, o
que é útil em uma série de situações. Naturalmente que um primeiro passo
122 CAPÍTULO 5. BOAS PRÁTICAS EM PROGRAMAÇÃO

necessário para isso é a conexão com o banco, que envolve utilizar credenciais
de acesso como IP, usuário e senha, que por razões de segurança, sempre são
restritas.
Nos exemplos que veremos nesse material, utilizaremos esses dados de
acesso explicitamente, mas aqui estamos trabalhando para fins didáticos.
Em termos práticos, não é uma boa forma deixar esses dados escritos de
forma explícita nos scripts. Ao invés disso, recomenda-se o uso de variáveis
de ambiente. (esse item será melhor detalhado depois)

5.5 Modularização
Vimos nos capítulos anteriores que podemos criar nossos próprios módu-
los, que são arquivos .py com uma coleção de funções e classes que podemos
criar para realizar operações de nosso interesse.
Em scripts que fiquem muito complexos e difíceis de entender, é comum
"quebrarmos"o código em partes menores para facilitar o entendimento do
que está sendo realizado.
Por exemplo, suponha que queiramos realizar uma operação de ETL para
um problema de BI, como veremos no capítulo ***. Podemos criar um mó-
dulo para a conexão com o banco de dados, um módulo para controlar os
logs, um módulo para salvar as queries que serão executadas no banco de
dados e assim por diante. Assim, separamos as operações por assunto e no
script principal, teremos algo como:

1 import conectar_banco
2 import criar_logs
3 import querries
4

5 # Ou
6 from conectar_banco import *
7 from criar_logs import *
8 from querries import *

Após importar os módulos criados, utilizamos suas funções diretamente,


realizando as operações necessárias em poucas linhas, sem a necessidade de
se ter de definir funções em um mesmo script, o que fatalmente acabará
aumentando muito o seu tamanho.
Dessa forma, o código fica muito mais limpo, organizado e fácil de se dar
manutenção.
5.6. COMENTÁRIOS 123

5.6 Comentários
Qualquer que seja o código que você esteja escrevendo, é essencial que
ele seja bem documentado. Isso ajuda você a compreender o que foi feito
e também facilita o entendimento de outras pessoas que porventura possam
vir a trabalhar no seu código futuramente.
Quando estamos criando um script, é comum utilizar os comentários em
código para isso. Para comentar código em Python, podem ser utilizadas
duas opções:
1 # Esse é um coment á rio em uma linha
2

3 ou
4

5 '''
6 Esse
7 é
8 um
9 coment á rio
10 em bloco
11 '''

Os comentários também podem ser úteis em outras situações. Por exem-


plo, pode não ser mais desejável a execução de algum pedaço de código,
mas não queremos simplesmente removê-lo do script. Podemos então sim-
plesmente utilizar o comentário em código para deixá-lo comentado. Dessa
forma, quando o script for executado, o interpretador apenas irá ignorar
aquela parte.

5.7 Término do script


Falamos rapidamente sobre como modularizar o seu código é uma boa
prática, deixando o script principal mais limpo e organizado. Também é
usual que os comandos definidos nesse script estejam alocados dentro de
uma função principal, usualmente chamada de main() e que essa função seja
invocada ao final do script da seguinte forma:
1 if __name__ == " __main__ " :
2 main ()

Fazemos isso por uma série de motivos. Primeiro, é preciso entender


que todo arquivo Python possui uma variável especial chamada __name__.
Quando você executa diretamente um script no console, o valor dessa variável
124 CAPÍTULO 5. BOAS PRÁTICAS EM PROGRAMAÇÃO

é __main__. No entanto, se esse script por impotado como um módulo em


outro arquivo, o valor será o nome do arquivo.
Adicionando essa condição ao final do script, evitamos sua execução de
forma indesejada, ou seja: se ele for importado em outro lugar, não será
executado automaticamente, o que evita efeitos colaterais.
Em outras palavras, seu script principal pode ser importado em outro
local para utilizar eventualmente alguma função ou classe que você criou
dentro dele, mas assim o script destino não irá executar a função principal
do script origem.
Outra vantagem de se fazer isso é a legibilidade. Assim como modu-
larização e comentários melhoram o entendimento do seu script, colocar a
função main() dentro da condição final indica para qualquer pessoa que for
lê-lo imediatamente entende qual é o ponto de partida, o que facilita testes
e manutenção.
Em sua, essa é uma prática recomendada por motivos de segurança, le-
gibilidade e facilidade de manutenção.

5.8 Exemplo final


Juntando tudo o que vimos nesse capítulo, vejamos um exemplo simples
de como pode ser escrito um script utilizando todos esses conceitos
1 """
2 Script para atualizar tabelas de dados de Gradua ç ã o a
partir do sistema acad ê mico .
3 Autor : Cientista de Dados X
4 Data : janeiro /2017
5 """
6

7 # Importa Bibliotecas e arquivos


8 from bd import *
9 from dados_con import *
10 from func_grad import *
11

12 # Parametriza o ano e o semestre


13 ano_letivo = 2025
14 sem_letivo = 2
15

16 def main () :
17 # Cria as conex õ es
18 conn , cursor = conexao_bd ( scrts )
19
5.8. EXEMPLO FINAL 125

20 # Executa as opera ç õ es
21 try :
22 importa_dados ( cursor , conn , ano_letivo ) # Passo
1: importa os dados
23 except :
24 print ( " Erro na importa ç ã o ! " )
25

26 try :
27 if sem_letivo == 1: # Passo 2: atualiza aa base
de acordo com o semestre letivo .
28 update_ind_ano ( cursor , conn , ano_letivo -1 , 2)
# Atualiza primeiro para o 2 o . semestre do ano
anterior .
29 update_ind_ano ( cursor , conn , ano_letivo , 1) #
Atualiza para o semestre corrente .
30 else :
31 update_ind_ano ( cursor , conn , ano_letivo , 1) #
Atualiza primeiro para o 1 o . semestre do ano .
32 update_ind_ano ( cursor , conn , ano_letivo , 2) #
Atualiza para o semestre corrente .
33 except :
34 print ( " Erro na atualiza ç ã o dos dados ! " )
35

36 # Fecha as conex õ es
37 fecha_conexao ( cursor , conn )
38

39 if __name__ == " __main__ " :


40 main ()

Perceba que nesse script estamos importando módulos que foram criados
para realizar a conexão com o banco (bd), guardar os dados de conexão
(dados_con) e realizar as operações (funcgrad). Eles foram importados com
a sintaxe from módulo import *, de maneira que suas funções podem ser
utilizadas diretamente sem invocar o nome de cada módulo.
Isso foi feito para deixar o código mais simples e limpo, mas poderia
ter sido feito do jeito tradicional - import bd, import dados_con, import
funcgrad - e dessa forma deixaríamos claro qual função pertence a cada mó-
dulo, utilizando por exemplo: bd.conexao_bd, func_grad.importa_dados.
Tudo depende também do objetivo do script, por quem será utilizado, quem
terá acesso, etc.
Além disso, procurou-se utilizar todas as boas práticas mencionadas aqui:
preâmbulo, comentários, modularização, exceções e função principal invocada
pela condição especial ao final do script.
126 CAPÍTULO 5. BOAS PRÁTICAS EM PROGRAMAÇÃO

Não há uma regra universal. Apenas bom senso e muita prática o levarão
a se tornar um bom programador em Python.
Capítulo 6

Próximos Capítulos

Nos próximos capítulos serão abordados os seguintes temas:

• Estatística Básica: aborda tratamento de arquivos, análise exploratória


e inferência estatística com os pacotes vistos nos capítulos anteriores e
com SciPy.

• Inteligência de Negócio: onde será visto os conceitos básicos de BI,


modelagem de DW e linguagem SQL, conexão a Banco de Dados e
construção de uma dashboard completa.

• Modelos de Regressão: os modelos mais básicos com Statsmodels.

• Aprendizado de Máquina: metodologias mais utilizadas com o Scikit-


Learn, Tensorflow e Keras.

• Aplicações práticas: como construir uma aplicação utilizando Flask e


Django Noções básicas de html.

• Agentes de IA: como Python está sendo utilizado em aplicações de


Inteligência Artificial.

• Tendências para o Futuro.

127
128 CAPÍTULO 6. PRÓXIMOS CAPÍTULOS
Referências Bibliográficas

H. A. Chipman, J. R. Joseph, et al. A conversation with jeff wu. Statistical


Science, 31 (4):624–636, 2016.

W. S. Cleveland. Data science: an action plan for expanding the technical


areas of the ield of statistics. International Statistical Review, 69 (1):21–26,
2001.

T. H. Davenport and D. Patil. Data scientist: The sexiest job of the 21st
century. Harvard Business Review, 2012.

J. W. Tukey. The future of data analysis. The annals of mathematical


statistics, 33 (1):1–67, 1962.

J. VanderPlas. Guia do Python para Data Science. Alta Books Editora, 2


edition, 2025.

129

Você também pode gostar