Escolar Documentos
Profissional Documentos
Cultura Documentos
Rick J. Scavetta
Boyan Angelov
Novatec
Authorized Portuguese translation of the English edition of Python and R for the Modern Data
Scientist, ISBN 9781492093404 © 2021 Boyan Angelov and Rick J. Scavetta. This translation is
published and sold by permission of O'Reilly Media, Inc., the owner of all rights to publish and
sell the same.
Tradução em português autorizada da edição em inglês da obra Python and R for the Modern
Data Scientist, ISBN 9781492093404 © 2021 Boyan Angelov and Rick J. Scavetta. Esta tradução é
publicada e vendida com a permissão da O'Reilly Media, Inc., detentora de todos os direitos para
publicação e venda desta obra.
© Novatec Editora Ltda. [2022].
Todos os direitos reservados e protegidos pela Lei 9.610 de 19/02/1998. É proibida a reprodução
desta obra, mesmo parcial, por qualquer processo, sem prévia autorização, por escrito, do autor e
da Editora.
Editor: Rubens Prates GRA20220905
Tradução: Aldir Coelho Corrêa da Silva
Revisão gramatical: Tássia Carvalho
ISBN do impresso: 978-65-86057-95-9
ISBN do ebook: 978-65-86057-96-6
Histórico de impressões:
Setembro/2022 Primeira edição
Novatec Editora Ltda.
Rua Luís Antônio dos Santos 110
02460-000 – São Paulo, SP – Brasil
Tel.: +55 11 2959-6529
Email: novatec@novatec.com.br
Site: https://novatec.com.br
Twitter: twitter.com/novateceditora
Facebook: facebook.com/novatec
LinkedIn: linkedin.com/in/novatec
GRA20220905
Aos meus pais por me darem o melhor início de vida possível.
À minha esposa por ser meu porto seguro.
Aos meus lhos por sonharem com um mundo melhor.
–Boyan Angelov
Prefácio
Parte I Descoberta de uma nova linguagem
Capítulo 1 No começo
Origens do R
Origens do Python
Começa a guerra de linguagens
A batalha pela primazia na área da ciência de dados
Convergência para a cooperação e a criação de comunidade
Considerações nais
Interações técnicas
Aceitar que o mundo é extenso, diverso e complexo demais para uma
única ferramenta atender às demandas que enfrentamos apresenta um
desa o que pode ser superado mais apropriadamente de maneira direta e
antecipada.
Essa perspectiva ampliada resulta em um aumento nas interações técnicas.
Devemos considerar a linguagem de programação, pacotes, convenções de
nomenclatura, a arquitetura de arquivos do projeto, IDEs (integrated
development environments, ambientes de desenvolvimento integrado),
editores de texto, entre outros recursos, que atenderão melhor à situação.
A diversidade faz surgir complexidade e confusão.
Quanto mais diverso o ecossistema se tornar, mais importante será
considerar se nossas escolhas estão atuando como pontes ou barreiras.
Devemos sempre tentar fazer escolhas que construam pontes com nossos
colegas e comunidades e evitar as que criem barreiras que nos isolem e
nos tornem in exíveis. Há muito espaço para abrigar a diversidade de
escolhas que encontraremos. O desa o em cada situação será fazer
escolhas que encontrem um equilíbrio entre preferência pessoal e
acessibilidade da comunidade.
Esse desa o existe em todas as interações técnicas. Além da escolha da
ferramenta (uma habilidade “técnica”), ele também inclui a comunicação
(uma habilidade “comportamental”). O conteúdo, o estilo e o meio de
comunicação, para citar apenas algumas considerações, também agem
como pontes ou obstáculos para um público-alvo especí co.
Tornar-se bilíngue em Python e R é um passo em direção à construção de
pontes entre membros da comunidade mais ampla da ciência de dados.
Pré-requisitos
Para aproveitar ao máximo este livro, presumimos que o leitor conheça
pelo menos uma das principais linguagens de programação da ciência de
dados, Python e R. Um leitor que conhecer uma linguagem que se
aproxime delas, como Julia ou Ruby, também poderá tirar bom proveito.
Um conhecimento básico das áreas gerais do trabalho de ciência de
dados, como a manipulação de dados (data munging), a visualização de
dados e o machine learning, é bené co, mas não é obrigatório, para a
apreciação dos exemplos, dos cenários de uxo de trabalho e do estudo
de caso.
Precisamos conversar
A área da ciência de dados está em contínua evolução e esperamos que
este livro o ajude a navegar facilmente entre Python e R. Queremos muito
saber o que você pensa, portanto nos diga como seu trabalho mudou!
Você pode entrar em contato conosco (em inglês) por meio do site que
serve como acompanhamento do livro (https://www.moderndata.design).
Nele você encontrará conteúdo adicional atualizado e um prático resumo
de referência bilíngue de Python/R.
Agradecimentos
Os autores agradecem a contribuição de muitas pessoas que ajudaram a
tornar este livro possível.
Na O’Reilly, gostaríamos de agradecer à Michelle Smith, uma editora
sênior de aquisições de conteúdo com entusiasmo, conhecimento e visão
inigualáveis com quem tivemos a sorte de trabalhar. Agradecemos à
Angela Ru no, nossa editora de desenvolvimento de conteúdo, por nos
manter no caminho certo durante o processo de redação e por nos
motivar com uma parede repleta de heróis de ação e palavras
reconfortantes de encorajamento. Somos gratos à Katie Tozer, nossa
editora de produção, por sua paciência e pelo tratamento minucioso dado
ao nosso manuscrito. Queremos agradecer a Robert Romano e à equipe
de design da O’Reilly. Além de ajudarem no redesenho das guras, eles
também escolheram, por sugestão nossa, uma lula surpreendente,
imponente e muito impactante e colossal para a capa! Também
gostaríamos de agradecer a Chris Stone e à equipe de engenharia pela
ajuda técnica.
Queremos enviar um agradecimento especial para as incontáveis pessoas
que nunca são vistas e trabalham nos bastidores da O’Reilly. Apreciamos
o grande esforço necessário para que sejam disponibilizados conteúdos
relevantes e de excelência.
Também queremos agradecer a nossos revisores técnicos, que cederam
generosamente seu tempo e forneceram comentários esclarecedores
extraídos de sua experiência. Eric Pite e Ian Flores, da RStudio, nossos
colegas autores Noah Gift e George Mount, da O’Reilly, e o irrepreensível
autor Walter R. Paczkowski. Seus comentários foram bem recebidos e
melhoraram imensamente o livro.
Rick deseja agradecer aos seus alunos, tanto online quanto presenciais,
dos últimos 10 anos. Cada oportunidade de transmitir conhecimento e
informações reforçou a importância do ofício de ensinar e permitiu que
fossem feitas contribuições, mesmo que modestas, para o grandioso
avanço da ciência. Rick também agradece pelo dedicado suporte
administrativo que permite que ele mantenha um relacionamento ativo
com os principais cientistas em todo o mundo.
Para concluir, estendemos um agradecimento sincero não só aos
desenvolvedores de Python e R como também à ampla e interconectada
comunidade de desenvolvedores open source. Sua criatividade, dedicação
e paixão são surpreendentes. É difícil imaginar como seria o cenário da
ciência de dados sem os esforços coletivos de milhares de desenvolvedores
trabalhando em conjunto, cruzando todas as fronteiras e abrangendo
décadas. Grande parte do que incluímos neste livro não existiria sem suas
contribuições!
No começo
Rick J. Scavetta
Gostaríamos de iniciar com uma frase genial, como “Foi o melhor dos
tempos, foi o pior dos tempos…”, mas, na verdade, é o melhor dos tempos
– a ciência de dados está orescendo! Ao avançar, ela foi se fragmentando
em nichos, como ocorre com muitas disciplinas com o passar do tempo.
Essa maturidade é resultado de uma longa jornada que começou nos
primórdios da computação cientí ca. Acreditamos que conhecer as
histórias da origem de Python e R o ajudará a entender como elas diferem
no ambiente atual e, portanto, como aproveitá-las ao máximo.
Não queremos nos passar por historiadores da ciência, aquele seleto
grupo de acadêmicos que rastreiam as circunstâncias em que ocorreram
grandes descobertas e surgiram personalidades importantes. O que
podemos fazer é oferecer uma descrição dos momentos de destaque que
zeram surgir o Python e o R e de como isso nos levou à nossa situação
atual.
Origens do R
Sempre que penso no R, lembro-me da FUBU, uma empresa de streetwear
fundada nos idos de 1990. O nome é um acrônimo do qual gostei de
imediato: For Us, By Us (para nós, por nós). FUBU signi cava
comunidade; signi cava conhecer as necessidades e os desejos de seus
pares e se certi car de que eles estavam sendo bem atendidos. O R é
FUBU.1 Até o m deste capítulo, tenho certeza de que você também se
sentirá assim. A partir do momento em que entendemos que o R é FUBU,
tudo começa a fazer sentido.
Podemos encontrar as origens do R no agora lendário Bell Laboratories
em Nova Jersey. Em 1976, o desenvolvimento da linguagem de
programação estatística S estava sendo liderado por John Chambers. Um
ano depois, Chambers publicou Computational Methods for Data Analysis
(John Wiley & Sons) e seu colega John Tukey, também da Bell
Laboratories, publicou Exploratory Data Analysis (Addison-Wesley). Em
1983, Chambers et al. publicaram Graphical Methods for Data Analysis
(CRC Press). Esses livros forneceram a base para o desenvolvimento de
um sistema computacional que permitiria que um estatístico não só
explorasse, entendesse e analisasse seus dados, mas também comunicasse
seus resultados. Aqui temos uma equipe de estrelas do FUBU! Os
coautores do livro de Chambers foram os primos de Tukey, Paul A. Tuke e
William Cleveland. Os experimentos empíricos de Cleveland sobre
percepção, resumidos em dois livros esclarecedores, continuam até hoje a
embasar a área mais ampla da visualização de dados. Entre suas muitas
contribuições para a computação cientí ca e a estatística, Tukey
desenvolveu novas visualizações, como o geralmente mal compreendido
diagrama de caixa e bigodes (box and whiskers plot), e criou o método
LOESS (Locally Weighted Scatterplot Smoothing, Suavização de Grá co
de Dispersão Ponderada Localmente) para a suavização não paramétrica.
Começaremos com o S porque ele formou a base do que acabaria se
tornando o R. As poucas informações do parágrafo anterior explicam algo
sobre as bases do S – e do R. Em primeiro lugar, os estatísticos são
pessoas muito literais (daí S, de statisticians). Essa é uma característica
bastante útil. Em segundo lugar, eles queriam uma linguagem de
programação FUBU especí ca para a análise de dados. Não estavam
interessados em criar uma linguagem de programação generalista ou um
sistema operacional. Em terceiro lugar, esses livros iniciais sobre
estatística e visualização computacional são, resumindo, ótimos exemplos
de beleza pedagógica e exposição precisa.2 Eles envelheceram muito bem,
apesar da tecnologia obviamente datada. Eu diria que esses livros
plantaram a semente de como os estatísticos, e em particular a
comunidade R, lidariam com a comunicação técnica de maneira aberta,
clara e inclusiva. Acho que essa é uma característica marcante e
diferenciada da comunidade R que tem raízes profundas. Em quarto
lugar, a ênfase inicial dada a métodos grá cos mostra que o S já se
preocupava com o fornecimento de visualizações de dados exíveis e
e cientes, necessárias tanto para a compreensão dos dados quanto para a
comunicação dos resultados. Logo, o S tinha como objetivo realizar o que
fosse mais importante da maneira mais fácil possível, e de um modo
realmente FUBU.
A distribuição original do S era executada no Unix e estava disponível
gratuitamente. O S acabou sendo licenciado como uma implementação
chamada S-PLUS. Isso demandou outra implementação open source e
gratuita criada por Ross Ihaka e Robert Gentleman na Universidade de
Auckland em 1991. Eles chamaram essa implementação de R, com base
nas iniciais de seus nomes, como uma brincadeira com o nome S, e para
manter a tradição de nomear linguagens de programação usando uma
única letra. A primeira versão beta o cial estável do R v1.0.0 foi
disponibilizada em 29 de fevereiro de 2000. No período entre as duas
datas, ocorreram dois desenvolvimentos importantes. O CRAN
(Comprehensive R Archive Network) (https://oreil.ly/HIpY7), foi
estabelecido para hospedar e arquivar pacotes R em servidores
espelhados, e o R Core Team também foi estabelecido. Esse grupo de
voluntários (https://oreil.ly/Zjrvw) (que atualmente é composto de
20 membros) implementa o base-R, com a inclusão de documentos,
builds, testes e versões, mais a infraestrutura que torna tudo isso possível.
O interessante é que alguns dos membros originais continuam atuando,
entre eles John Chambers, Ross Ihaka e Robert Gentleman.
Muita coisa aconteceu desde o lançamento do R v1.0.0 em 2000, mas o
que contei até aqui deve lhe dar uma ideia do histórico único do R como
ferramenta FUBU de computação estatística. Antes de continuar com a
história do R, conheceremos a história do Python.
Origens do Python
Em 1991, enquanto Ross Ihaka e Robert Gentleman começavam a
trabalhar no que se tornaria o R, Guido van Rossum, um programador
holandês, lançou o Python. A perspectiva básica do Python é a de uma
pessoa que começou a resolver os problemas computacionais comuns
daquela época. Na verdade, van Rossum foi durante anos chamado
carinhosamente de BDFL (benevolent dictator for life, ditador
benevolente vitalício), um título ao qual ele renunciou quando deixou o
Python’s Steering Council em 2018.
Vimos que o S surgiu da necessidade de os estatísticos poderem executar a
análise de dados e o R devido à demanda por uma implementação open
source, mas, então, que problema foi resolvido pelo Python? Bem, não foi
o da análise de dados – isso veio muito depois. Quando o Python surgiu,
C e C++, duas linguagens de programação de baixo nível, eram
populares. O Python despontou lentamente como uma alternativa
interpretada de alto nível, principalmente depois que o Python v2 foi
lançado em 2000 (o mesmo ano em que o R v1.0.0 foi lançado). Python foi
criado com a nalidade explícita de ser, acima de tudo, uma linguagem de
programação amplamente adotada, fácil de usar e de aprender e com uma
sintaxe simples. E foi muito bem-sucedido nesse aspecto!
É por isso que, como você deve ter notado, ao contrário do R, Python é
visto em todos os lugares e é muito versátil. Ele pode ser visto no
desenvolvimento web, em jogos (gaming), na administração de sistemas,
em aplicações desktop, na ciência de dados e assim por diante. Na
verdade, o R pode ser usado não só na análise de dados, mas lembre-se,
ele é FUBU. Se o R é FUBU, o Python é um canivete suíço. Está em todos
os locais e todo mundo tem um, mas, ainda que forneça muitas
ferramentas, a maioria das pessoas usa apenas uma regularmente.
Embora os cientistas de dados que usam Python trabalhem em um
cenário amplo e variado, tendem a encontrar seu nicho e se especializar
nos pacotes e uxos de trabalho necessários para a execução de seu
trabalho em vez de explorar todas as facetas dessa linguagem generalista.
A ampla popularidade do Python dentro da ciência de dados não se deve
apenas aos recursos que ele fornece para essa área. Eu diria que o Python
fez sua entrada na ciência de dados parcialmente por causa dos recursos
que ele oferece como uma linguagem de uso geral. A nal, entrar aos
poucos já é meio caminho andado. Os analistas e cientistas de dados
achavam mais fácil compartilhar e implementar scripts com colegas
envolvidos na administração de sistemas e no desenvolvimento web
porque eles já sabiam como trabalhar com scripts Python. Isso
desempenhou um papel importante na ampla adoção do Python. Ele
conseguia se bene ciar da computação de alto desempenho e
implementar e cientemente algoritmos de deep learning (aprendizagem
profunda). O R era, e talvez ainda seja, uma linguagem de nicho,
semelhante a uma língua estrangeira que o universo mais amplo da
computação não entendeu.
Embora o Python v2 tenha sido lançado em 2000, a consolidação de um
pacote amplamente adotado para a manipulação de dados de array só
ocorreu em 2005, com o lançamento do NumPy. Nessa época, o SciPy, um
pacote que, desde 2001, fornecia algoritmos básicos para a ciência de
dados (relacionados à otimização, integração, equações diferenciais etc.),
começou a usar estruturas de dados do NumPy. O SciPy também fornece
estruturas de dados especializadas como as árvores k-dimensionais.
Quando o problema da existência de um pacote padrão para estruturas
de dados e algoritmos básicos foi resolvido, o Python começou sua
ascensão para a ampla adoção na computação cientí ca. Os pacotes de
baixo nível NumPy e SciPy formaram a base para pacotes de alto nível,
como o pandas em 2009, fornecendo ferramentas para a manipulação de
dados e para estruturas de dados como os dataframes. Isso também é
chamado de PyData stack e foi quando tudo começou realmente a
acontecer.
Considerações nais
Agora você já deve ter uma boa ideia de aonde chegamos em 2021 e de
como isso ocorreu. Na próxima parte, introduziremos cada grupo de
usuários a uma nova linguagem.
Uma última observação: os usuários do Python chamam a si mesmos de
Pythonistas, que é um nome muito legal! Não há um equivalente em R, e
seus usuários também não têm um representante tão legal no mundo
animal, mas é isso que acontece quando se tem uma linguagem de uma
única letra. Normalmente os usuários do R são chamados de… adivinhe…
useRs! (usuáRios!) (O ponto de exclamação é opcional). Na verdade, a
conferência anual o cial chama-se useR! (aqui o ponto de exclamação é
obrigatório), e a editora Springer tem uma série de livros muito boa e de
lançamento contínuo com o mesmo nome. Usaremos esses nomes de
agora em diante.
A Figura 1.1 fornece um resumo de alguns dos principais eventos que
destacamos neste capítulo, além de outros momentos importantes de
interesse.
Figura 1.1: Linha do tempo de momentos importantes do Python e do R para
a ciência de dados.
1 Bem, na verdade seria mais algo como For Statisticians, By Statisticians (para estatísticos, por
estatísticos), mas FSBS não soa tão bem.
2 Com a possível exceção de Computational Methods for Data Analysis, que admito não ter lido.
3 Acredito que já podemos rastrear esse relacionamento nos primórdios do R, como evidenciado
pela notação de fórmula e dos diversos conjuntos de dados internos. No entanto, faltava um
framework consistente e intuitivo.
4 Isso chegou até mesmo a levar alguns desenvolvedores proeminentes a se declararem contra o
eventual desenvolvimento do Python 4.0. Será interessante acompanhar como o Python vai se
desenvolver!
5 Isto é, usando a saída de uma função como a entrada de outra.
6 Os usuários do Python podem não estar familiarizados com o termo base. Ele indica apenas a
funcionalidade interna da linguagem sem nenhuma instalação de pacote adicional. O base-R
está equipado para a análise de dados. Em Python, por padrão o cientista de dados precisaria
importar a pilha PyData.
PARTE II
R para Pythonistas
Rick J. Scavetta
Bem-vindo, bravo Pythonista, ao mundo useR!1 Neste capítulo, vou
apresentá-lo aos principais recursos do R e tentarei esclarecer algumas
partes confusas que você encontrará durante o percurso. Logo, será útil
mencionar o que não vamos fazer.
Em primeiro lugar, não estamos escrevendo para o cientista de dados
leigo. Se você deseja aprender R a partir do zero, existem muitos recursos
excelentes disponíveis – na verdade, recursos demais para podermos
mencionar. Recomendamos que você os examine e selecione os que
atenderem às suas necessidades e estilo de aprendizagem. Aqui,
exibiremos tópicos e questões que podem confundir o iniciante sem
experiência. Faremos alguns desvios de percurso para explicar os tópicos
que esperamos que ajudem especi camente o Pythonista amigável a se
adaptar mais facilmente ao R.
Em segundo lugar, esse não é um dicionário bilíngue; você encontrará um
no Apêndice, mas sem contexto ele não é útil. Aqui, queremos conduzi-lo
por uma jornada de exploRação e compReensão. Queremos que você se
habitue ao R para começar a pensar em R, tornando-se bilíngue. Logo,
para ajudar na apresentação, podemos introduzir alguns itens em um
momento posterior, o que não faríamos se estivéssemos escrevendo a
narrativa para um iniciante. No entanto, esperamos que você volte a este
capítulo quando precisar se lembrar de como executar tarefas familiares
em uma nova linguagem.
Em terceiro lugar, esse não é um guia de nitivo. Após aprender a
linguagem R, você terá ótimos momentos explorando-a com mais
cuidado para fazê-la atender às suas necessidades especí cas conforme
elas forem surgindo. Como mencionamos na primeira parte do livro, a
comunidade R é diversi cada, amigável, acolhedora – e útil! Estamos
convencidos de que é uma das culturas menos “tech-bro”2 existentes. Para
conhecer melhor a comunidade, você pode seguir #rstats no Twitter
(https://oreil.ly/YOfeZ).
Trabalhando com o R
Para acompanhar os exercícios deste capítulo, você pode acessar o R
online usando o RStudio Cloud ou instalar o R e o RStudio localmente.
O RStudio Cloud é uma plataforma que dá acesso a uma instância R (por
meio de um IDE RStudio) que nos permite fazer o upload de nossos
próprios dados e compartilhar projetos. Abordaremos os dois métodos
nos próximos parágrafos.
Para usar o RStudio Cloud, crie uma conta (https://rstudio.cloud) e acesse
nosso projeto disponível publicamente (https://oreil.ly/21Sr2). Certi que-
se de salvar uma cópia do projeto em seu espaço de trabalho para ter sua
própria cópia; você verá o link no título.
Sua sessão do RStudio deve car parecida com a da Figura 2.1. Abra ch02-
r4py/r4py.R e pronto! Você já pode acompanhar todos os exemplos. Para
executar comandos, pressione Ctrl + Enter (ou Command-Enter).
Figura 2.1: Nosso projeto no RStudio Cloud.
Para executar o R localmente, você o encontrará disponível com a
distribuição Anaconda, se a estiver usando; caso contrário, poderá
instalá-lo diretamente. Primeiro, baixe e instale o R especí co do seu
sistema operacional (https://www.r-project.org). O R v4.0 foi lançado em
junho de 2020 e, ao contrário do Pythonv3.x, é compatível com versões
anteriores, com algumas exceções. É preciso que você esteja executando
pelo menos o R 4.0.0: “Taking O Again”. Cada versão recebeu um nome
inspirado pelos quadrinhos Peanuts (a tirinha e a franquia de lmes
clássica estrelada por Charlie Brown, Snoopy e companhia), o que
considero um toque pessoal interessante. Em seguida, instale o IDE
RStudio Desktop (https://rstudio.com).
Para concluir, de na o projeto no qual irá trabalhar. Isso é um pouco
diferente de quando usamos um ambiente virtual, o que discutiremos
posteriormente. Existem duas maneiras de criar um projeto com arquivos
preexistentes.
Em primeiro lugar, se você estiver usando o Git, cará feliz em saber que
o RStudio também é um cliente Git GUI básico. No RStudio, selecione
File > “New project” > Version Control > Git e insira a URL de
repositório https://github.com/moderndatadesign/PyR4MDS. O nome do
diretório do projeto usará o nome do repositório automaticamente.
Selecione onde deseja armazenar o repositório e clique em Create Project.
Em segundo lugar, se você não estiver usando o Git, poderá baixar e
descompactar o repositório a partir de
https://github.com/moderndatadesign/PyR4MDS. No RStudio, selecione
File > Existing Directory e navegue até o diretório baixado. Um novo
arquivo de projeto R, *.Rproj, será criado nesse diretório.
Sua sessão do RStudio deve car com a aparência da Figura 2.2. Abra
ch02-r4py/r4py.R e pronto! Você já pode acompanhar todos os exemplos.
Para executar comandos, pressione Ctrl + Enter (ou Command-Enter).
Projetos e pacotes
Poderíamos começar a explorar o R usando um conjunto de dados
interno e entrando diretamente no Tidyverse (introduzido no Capítulo 1),
mas pre ro parar, tomar fôlego e começar nossa história pelo início.
Começaremos lendo um arquivo CSV simples. Para fazer isso, usaremos
um conjunto de dados que já está disponível em R no pacote ggplot2.
Para o que temos em mente, estamos mais interessados em como fazê-lo
em R do que com a análise real. Forneci o conjunto de dados como um
arquivo no repositório do livro
(https://github.com/moderndatadesign/PyR4MDS).
Se você de nir seu projeto corretamente, tudo que terá de fazer é executar
o comando a seguir. Se esse comando não funcionar, não se preocupe,
voltaremos a ele em breve.
diamonds <- read.csv("ch02-r4py/data/diamonds.csv")
Como em Python, as aspas simples ('') e duplas ("") são intercambiáveis,
embora o uso de aspas duplas seja preferencial.
Você já deve ter importado o arquivo e ele está disponível como um
objeto em seu ambiente global, onde cam os objetos de nidos pelo
usuário. A primeira coisa que notará é que o painel de ambiente
(environment) do RStudio está exibindo o objeto, já fornecendo algumas
informações resumidas (Figura 2.3).
Embora o R use a OOP, quase sempre ele opera em segundo plano; logo,
você nunca verá aliases estranhos para pacotes como:
import readr as rr
Isso traz à mente outra função legada que você pode vir a encontrar.
De nitivamente você deve evitar attach() (e também sua
contrapartida detach()). Essa função permite anexar um objeto ao
ambiente global, de forma semelhante a como anexamos um pacote.
Logo, seria possível chamar elementos do objeto diretamente, sem
antes especi car o nome do objeto de maneira explícita, da mesma
forma que chamamos funções de um pacote sem precisar usar o
nome do pacote explicitamente. O motivo que fez esse recurso perder
o suporte foi que, se tivermos muitos objetos de dados para acessar,
nomes con itantes podem ser um problema (isto é, podem levar ao
mascaramento de objetos). Além disso, não é algo explícito.
Abordaremos outro problema do carregamento de pacotes antes de
continuar: você verá com frequência:
require(readr)
require() carregará um pacote instalado e também retornará
TRUE/FALSE dependendo do sucesso da operação. Isso é útil para
veri carmos se um pacote existe; logo, deve ser reservado para os casos
em que for necessário. Geralmente é melhor usar library().
Bem, leremos nosso conjunto de dados novamente, dessa vez usando
read_csv() para fazer algumas comparações simples entre os dois
métodos.
> diamonds_2 <- read_csv("R4Py/diamonds.csv")
Parsed with column specification:
cols(
carat = col_double(),
cut = col_character(),
color = col_character(),
clarity = col_character(),
depth = col_double(),
table = col_double(),
price = col_double(),
x = col_double(),
y = col_double(),
z = col_double()
)
Você deve ter notado que obtivemos uma descrição mais detalhada do
que ocorreu.
Como mencionamos anteriormente, as opções de design do Tidyverse
tendem a ser mais amigáveis para o usuário do que os processos mais
antigos que elas atualizam. Essa saída informa os nomes das colunas de
nossos dados tabulares e seus tipos (consulte a Tabela 2.2).
Observe também que a tendência atual em R é o uso de snake case,
underscores (“_”) entre as palavras e só letras minúsculas. Embora
normalmente a adoção de um guia de estilo para R seja baixa,
Advanced R, de Hadley Wickham (CRC Press), oferece boas sugestões. A
Google também tentou promover um guia de estilo para R
(https://oreil.ly/24XzZ), mas parece que a comunidade não é muito
rigorosa nesse aspecto. Isso contrasta com a estrita adoção do PEP 8 Style
Guide for Python Code, criado por Guido van Rossum e lançado quando
surgiu o Python.
class(diamonds_2)
[1] "spec_tbl_df" "tbl_df" "tbl" "data.frame"
str() é uma função clássica de pacote básico que fornece uma saída
simples. Sua saída é semelhante ao que você verá quando clicar na seta de
exibição ao lado do nome do objeto no painel de ambiente. A primeira
linha mostra a classe do objeto (que já vimos). S3 se refere ao sistema
OOP especí co que esse objeto usa, que nesse caso é o mais básico e
menos estrito.
Alternativamente, também podemos usar a função glimpse() do
Tidyverse, do pacote dplyr:
> library(dplyr)
> glimpse(my_tibble)
Rows: 2
Columns: 4
$ a <lgl> TRUE, FALSE
$ b <int> 1, 2
$ c <dbl> 3.14, 6.80
$ d <chr> "a", "b"
Observe que a Tabela 2.2 também exibe a abreviação num, que não
aparece na saída de glimpse(). Ela se refere à classe “numérica”,
indicando o tipo double (para números de ponto utuante com precisão
dupla) ou integer.
Os exemplos anteriores nos mostraram que um data.frame é uma
coleção bidimensional heterogênea de vetores unidimensionais
homogêneos, todos com o mesmo tamanho. Ainda veremos por que o R
exibe tantos cifrões (o que certamente não tem nenhuma relação com seu
salário!).
Listas
As listas são outra estrutura de dados comum, mas não são exatamente o
que esperaríamos de uma lista em Python; logo, a nomenclatura pode
confundir. Na verdade, já encontramos listas em nossa curta jornada pelo
universo do R. Estou me referindo ao fato de o data.frame ser uma classe
especí ca de tipo list. Sim, é isso mesmo que você leu.
> typeof(my_tibble)
[1] "list"
Aqui temos dois itens dos quais queremos que você se lembre.
Em primeiro lugar, você se lembra de que mencionamos que um data
frame é uma coleção de vetores de mesmo tamanho? Agora podemos ver
que isso signi ca apenas que ele é uma classe especial de tipo list, na
qual cada elemento é um vetor com o mesmo tamanho. Podemos acessar
um elemento nomeado dentro de uma lista usando a notação $:
> names(PlantGrowth)
[1] "weight" "group"
> PlantGrowth$weight
[1] 4.17 5.58 5.18 6.11 4.50 4.61 5.17 4.53 5.33 5.14 4.81 4.17 4.41 3.59
[15] 5.87 3.83 6.03 4.89 4.32 4.69 6.31 5.12 5.54 5.50 5.37 5.29 4.92 6.15
[29] 5.80 5.26
Você pode identi car facilmente um fator porque, tanto na saída de str()
(consulte “Listas”, na página 46) quanto na formatação simples dos
vetores, os níveis são declarados:
> PlantGrowth$group
[1] ctrl ctrl ctrl ctrl ctrl ctrl ctrl ctrl ctrl ctrl
[11] trt1 trt1 trt1 trt1 trt1 trt1 trt1 trt1 trt1 trt1
[21] trt2 trt2 trt2 trt2 trt2 trt2 trt2 trt2 trt2 trt2
Levels: ctrl trt1 trt2
Os níveis têm uma ordem; logo, D vem antes de E e assim por diante.
Esse código apenas pergunta quais de nossos diamantes são mais caros
que 18.000 dólares. Existem três elementos chave que sempre devemos
manter em mente aqui.
Em primeiro lugar, o tamanho do objeto menor, que nesse caso é o vetor
numérico não atribuído 18000 (com um elemento), será “reciclado” ao
longo de toda a extensão do vetor mais longo, nesse exemplo a coluna
price do data frame diamonds, com a notação $ (53.940 elementos). Em
Python chamamos isso de broadcasting, quando são usados arrays do
NumPy, e de vetorização como uma função distinta. Em R, chamamos os
dois casos de vetorização ou reciclagem de vetor.
Em segundo lugar, isso signi ca que o vetor da saída terá o mesmo
tamanho do vetor mais longo, nesse exemplo 53.940 elementos.
Em terceiro lugar, quando você encontrar um operador relacional ou
lógico, saberá que o vetor da saída sempre será um vetor lógico. (Lógico
como em TRUE/FALSE, e não como na lógica do Sr. Spock).
Se você quiser combinar perguntas, terá de combinar duas perguntas em
uma, como em quais seriam os diamantes mais caros e menores
(requintado, não?):
> diamonds$price > 18000 & diamonds$carat < 1.5
[1] FALSE FALSE FALSE FALSE FALSE FALSE
...
Observe que a ocorrência de todos os três elementos chave pode ser
con rmada. Quando apresentei os tipos de vetores atômicos, não
mencionei que o lógico também é de nido por 1 e 0. Isso signi ca que
podemos fazer cálculos com vetores lógicos, o que é muito conveniente.
Quantos diamantes pequenos e caros temos?
> sum(diamonds$price > 18000 & diamonds$carat < 1.5)
[1] 9
(Na verdade, isso não é su ciente.) Que proporção do meu conjunto de
dados eles representam? Apenas divida pelo número total de observações:
> sum(diamonds$price > 18000 & diamonds$carat < 1.5)/nrow(diamonds)
[1] 0.0001668521
i, j e k são três tipos de vetores diferentes que podem ser usados dentro
de []:
• Um vetor integer
• Um vetor lógico
• Um vetor de caracteres contendo nomes, se houver elementos
nomeados
Você deve conhecer isso pelo que temos em Python. No caso de vetores
integer e lógicos, eles podem ser vetores não atribuídos, ou ainda objetos
ou funções que gerem vetores integer ou lógicos. Os números não
precisam ser de tipo integer, embora números inteiros facilitem a situação.
Usar numeric/double faz o arredondamento para o próximo número
inteiro mais baixo, mas tente evitar usar números reais na indexação, a
menos que haja uma razão.
Começaremos com os inteiros. Faremos outro pequeno desvio aqui para
discutir o onipresente operador :, que não fará o que o seu cérebro
Pythonista acha que ele deveria fazer. Começaremos com um vetor de
caracteres interno, letters, que é semelhante a se tivéssemos a coluna de
um data frame, como em PlantGrowth$weight:
> letters[1] # O 1º elemento (a indexação começa em 1)
[1] "a"
Não deu certo, - signi ca excluir um elemento, e não contar para trás,
mas foi uma boa tentativa. Também podemos excluir um intervalo de
valores:
> letters[-(1:20)] # Exclui os elementos 1 a 20
[1] "u" "v" "w" "x" "y" "z"
Isso signi ca que você sempre precisará de um lhs (left hand side, lado
esquerdo) e de um rhs (right hand side, lado direito) ao usar :. É uma
pena, mas a linha a seguir não funcionará:
> letters[23:] # erro
Essa linha tem o formato de uma longa função aninhada que é muito
difícil de decifrar. Podemos pronunciar %>% como “e então” e, portanto,
ler o comando inteiro acima como “Pegue o conjunto de dados diamonds
e então ltre usando esses critérios e selecione apenas essas colunas”. Esse
recurso ajuda muito a ler e entender literalmente o código e é por isso que
dplyr é descrito como a gramática da análise de dados. Os objetos, como
os tibbles, são os substantivos, %>% é nossa pontuação, e as funções são os
verbos.
Embora geralmente o operador %>% seja usado para encadear funções do
Tidyverse, ele também pode ser empregado para desaninhar funções
aninhadas. Devido a esse uso ampliado, um operador forward pipe nativo,
“|>”, foi incluído no R v4.1 (lançado em 18 de maio de 2021, enquanto
nalizávamos este texto). Não está claro como os useRs o adotarão, dadas
a predominância de %>% e algumas pequenas diferenças entre os dois
operadores. Por enquanto, você pode continuar usando seguramente o
operador %>%.
Os cinco verbos mais importantes do dplyr estão listados na Tabela 2.4.
Tabela 2.4: Descrição das funções
Função Opera em Descrição
filter() linhas Usa um vetor lógico para reter apenas linhas TRUE
arrange() linhas Reordena as linhas de acordo com os valores de uma coluna especí ca
select() colunas Usa um nome ou uma função auxiliar para extrair apenas essas colunas
summarise() colunas Aplica funções de agregação a uma coluna
mutate() colunas Aplica funções de transformação a uma coluna
Reexecutando reiterações
Observe que não precisamos de nenhum loop nos exemplos anteriores.
Intuitivamente você poderia querer aplicar um loop for para calcular
funções de agregação ou transformação para cada região, mas não é
necessário. Evitar loops for é como um passatempo em R, e pode ser feito
no pacote básico com a família de funções apply.
Já que a vetorização é tão fundamental para o R, existe algo como um
concurso não o cial de quem consegue escrever menos loops for.
Podemos imaginar os useRs em um mural com os dizeres: “Dias desde o
último loop for:” como os encontrados em fábricas relacionados a
acidentes.
Isso signi ca que existem alguns métodos muito antigos para a reiteração
de tarefas e certos métodos mais novos que tornam o processo mais
conveniente.
Os métodos antigos dependem da família de funções apply, listadas na
Tabela 2.5. Exceto por apply(), todos são pronunciados com a primeira
letra e depois apply, ou seja, é “t apply” e não “tapply”.
Tabela 2.5: Família apply do pacote básico
Função Uso
apply() Aplica uma função a cada linha ou coluna de uma matriz ou data frame
lapply() Aplica uma função a cada elemento de uma lista
sapply() Simpli ca a saída de lapply()
mapply() Versão multivariável de sapply()
tapply() Aplica uma função aos valores de nidos por um índice
emapply() Aplica uma função aos valores de um ambiente
Esse código poderia ser lido como “pegue a coluna de peso do conjunto
de dados PlantGrowth, divida os valores de acordo com o rótulo da
coluna de grupo do conjunto de dados PlantGrowth, aplique a função de
média a cada grupo de valores e retorne um vetor nomeado”.
Percebe como será tedioso se você quiser adicionar mais funções? Os
vetores nomeados podem ser convenientes, mas não são uma maneira
comum de armazenar dados importantes.
Uma tentativa de simpli car esse processo foi implementada no plyr, o
precursor do dplyr. A palavra plyr deve ser pronunciada como plier
(alicate), da mesma maneira que a pequena ferramenta de mão
multifuncional. O pacote é usado desta forma:
library(plyr)
É uma ótima função, não é mesmo? Ela é muito antiga! Você ainda a verá
sendo usada. E por que não veria? Ao entendê-la, você verá que ela é
elegante e faz o que é necessário, ainda que só aplique uma única função.
Contudo, a tendência contínua de uso de um framework Tidyverse
uni cado, mais fácil de ler e possivelmente de aprender, signi ca que os
métodos antigos estão sendo colocados em segundo plano.
Essas funções existem desde os primórdios do R e intuitivamente re etem
o que os estatísticos fazem o tempo todo. Eles dividem dados em blocos,
de nidos por alguma propriedade (linhas, colunas, variáveis categóricas,
objetos), depois aplicam algum tipo de ação (diagramação, teste de
hipóteses, modelagem etc.) e, em seguida, combinam a saída de alguma
forma (usando um data frame, uma lista etc.). O processo costuma ser
chamado de dividir-aplicar-combinar. Perceber que esse processo se repetia
começou a deixar claro para a comunidade como eles deviam considerar
os dados e também como organizá-los. Foi dessa noção que nasceu a
ideia de dados “organizados” (tidy data).6
Como último exemplo das iterações, talvez você conheça a função map()
do Python. Uma função análoga pode ser encontrada no pacote purrr do
Tidyverse. Ela será conveniente se você quiser iterar pelas listas ou
elementos de um vetor, mas não faz parte do escopo deste livro.
Considerações nais
Em Python, geralmente ouvimos falar sobre a maneira Python de fazer as
coisas (“Pythônico”). Isso signi ca a sintaxe Python apropriada e o
melhor método de executar uma ação especí ca. Não há algo assim em R;
existem muitas maneiras de se fazer a mesma coisa e as pessoas usam
toda essa variedade! Além disso, elas costumam combinar dialetos.
Embora alguns dialetos sejam mais fáceis de ler do que outros, essa
hibridização pode di cultar o aprendizado da linguagem.
E também há os constantes ajustes de um Tidyverse em expansão.
Funções são marcadas como experimentais, em suspensão, em maturação,
estáveis, em questionamento, substituídas e arquivadas. Alie isso aos
relativamente descuidados padrões de gerenciamento de pacotes especí co
de projetos ou de uso de ambientes virtuais e podemos imaginar que haja
um nível cada vez maior de frustração.
O R celebrou o cialmente seu 20º aniversário em 2020, e suas raízes são
muito mais antigas. Mesmo assim, às vezes parece que ele está
vivenciando um crescimento repentino como o da adolescência. Está
tentando entender como cresceu tanto repentinamente e pode ser ao
mesmo tempo desajeitado e descolado. Combinar os diferentes dialetos
do R o ajudará a descobrir todo o seu potencial.
Rick J. Scavetta
Bem-vindo, bravo useR, ao maravilhoso mundo do Pythonista! Para
muitos useRs, esse admirável mundo novo pode parecer mais variado – e,
portanto, mais inconsistente e confuso – do que o ambiente com o qual
eles estão acostumados em R. No entanto, não se preocupe com a
diversidade – celebre-a! Neste capítulo, vou ajudá-lo a navegar pela rica e
diversa selva Python, realçando várias rotas ( uxos de trabalho) que seus
colegas usuários de Python podem ter seguido e que talvez você decida
explorar posteriormente. Entretanto, tenha certeza de que acabará
encontrando o caminho que servirá melhor a você e ao seu ambiente de
trabalho; ele mudará com o tempo e pode não ser o descrito aqui. Como
deve ser feito em qualquer boa caminhada, use essa rota como guia e não
como um livro de regras.
Abordarei os aspectos básicos dos quatro elementos que mencionei na
introdução desta parte: funções, objetos, expressões lógicas e indexação.
Contudo, começarei respondendo a três perguntas:
Pergunta 1
Que versão e que build (distribuição) usar? Existem algumas versões e
builds diferentes de Python para escolhermos, ao contrário do que
acontece com o R.
Pergunta 2
Que ferramentas usar? A ampla variedade de IDEs, editores de texto e
notebooks, além das várias maneiras de implementar ambientes
virtuais, adiciona mais opções à seleção.
Pergunta 3
De que forma a linguagem Python se compara à linguagem R? Habituar-
se a um mundo baseado na OOP, com várias classes, métodos, funções e
palavras-chave apresenta outra barreira à compreensão.
Abordarei cada uma dessas perguntas individualmente. Meu objetivo é
deixá-lo su cientemente confortável para ler e escrever código Python de
modo a poder continuar sua jornada bilíngue nas partes III e IV. Não
pretendo fornecer uma introdução completa e profunda do uso de Python
para a ciência de dados. Se quiser algo assim, leia os livros da O’Reilly,
Python para Análise de Dados, de Wes McKinney, e Python Data Science
Handbook, de Jake VanderPlas; este capítulo o ajudará a apreciar ainda
mais esses livros.
Se estiver ansioso para começar a usar Python, você pode pular para a
seção sobre notebooks, “Notebooks”, na página 76, e visitar o Notebook
do Google Colab (https://oreil.ly/hLi6i) referente à lição sobre Python, ou
acessar o script deste capítulo no repositório do nosso livro no GitHub
(https://github.com/moderndatadesign/PyR4MDS).
Versões e builds
Embora existam algumas distribuições diferentes do R, a maioria dos
useRs usa o R básico (vanilla R) que pode ser obtido em r-project.org
(https://www.r-project.org).1 Para Python, existem pelo menos quatro
builds (também chamadas de distribuições) para escolher. Em cada caso,
você também deve considerar a versão do Python.
Em primeiro lugar, você notará que provavelmente já possui uma versão
do Python instalada no sistema. Em minha máquina, executando o
macOS Big Sur (v11.1), consigo ver a versão do Python usando o comando
de terminal a seguir:
$ python --version
Python 2.7.16
Ferramentas padrão
Como ocorre com o R, existem muitas maneiras de acessar o Python.
Alguns métodos comuns são o uso da linha de comando, IDEs, editores
de texto e notebooks. Para simpli car, não me concentrarei na execução
do Python na linha de comando. Se você conhece a execução de scripts na
linha de comando, esse é um território familiar. Se não conhece, cruzará
essa ponte quando a alcançar.
Os IDEs incluem o JupyterLab, o Spyder, o PyCharm e nosso apreciado
RStudio. Entre os IDEs nativos da nuvem temos o AWS Cloud9. Essas são
todas variações do mesmo tema, e pelo que sei normalmente não são as
prediletas dos Pythonistas, embora exista uma tendência para o uso de
ferramentas baseadas em nuvem. Pode parecer estranho que os IDEs não
sejam tão populares. Por que não usar um IDE se existir um ótimo
disponível? Acho que há duas respostas. Em primeiro lugar, nenhum IDE
conseguiu se posicionar como a opção predominante entre os Pythonistas
como ocorreu com o RStudio entre os useRs. Em segundo lugar, já que os
casos de uso de Python são tão variados, incluindo ele ser executado na
própria linha de comando, codi car com IDEs não era tão interessante
para muitos Pythonistas, principalmente se tivessem experiência em
codi cação e se sentissem confortáveis sem um IDE. Para mim, isso
reforça um pouco uma narrativa que diz que o Python é ao mesmo tempo
mais difícil e melhor do que o R. Desculpe, mas as duas assertivas estão
incorretas! Todavia, você pode car tentado a começar a usar o Python
com um IDE de aparência amigável. Aqui, defendemos a ideia de que os
editores de texto podem ser mais úteis a longo prazo. Voltaremos ao
RStudio na última parte do livro quando unirmos Python e R no mesmo
script. Por enquanto, tente resistir ao impulso de adotar um IDE como
padrão e procure desenvolvimentos em plataformas de nuvem que
possam guiar tendências futuras.
Os editores de texto são a ferramenta mais comum e aparentemente
preferida para a composição de scripts em Python puro. Existem vários
editores de texto fantásticos para escolhermos, com sua popularidade
crescendo e diminuindo ano após ano. Sublime
(https://www.sublimetext.com), Atom (https://atom.io), Visual Studio Code
(VS Code) (https://code.visualstudio.com) e até mesmo os clássicos editores
Vim (https://www.vim.org) e Emacs (https://oreil.ly/pGjVX), entre muitos
outros, são frequentemente usados. No entanto, o VS Code, um editor
open source desenvolvido e fortemente suportado pela Microsoft,
emergiu nos últimos anos como a opção preferencial. Como um mercado
de extensões, esse editor fornece suporte forte e fácil para várias
linguagens, incluindo Python e R.4 Logo, nos concentraremos no
VS Code. Seu primeiro exercício será obter e instalar o VS Code.
Na primeira vez que você abrir o VS Code, será saudado com a tela de
boas-vindas, onde poderá escolher seu tema (light, no nosso caso) e
instalar a extensão da linguagem Python imediatamente, como mostrado
na Figura 3.1.
Instalação de pacotes
Até agora instalamos uma versão do Python e acessamos um espaço de
trabalho, como em um projeto R, de dentro do VS Code. Também
criamos um ambiente virtual, que já estamos prontos para preencher com
nossos pacotes de ciência de dados favoritos. Se você seguiu a rota do
Conda, usou comandos diferentes, mas também está pronto para
prosseguir com os pacotes de ciência de dados mais comuns pré-
instalados. Parece bom, mas você pode descobrir que, quando tiver de
colaborar com outros desenvolvedores Python, por exemplo, engenheiros
de dados ou administradores de sistemas, provavelmente eles não estarão
usando o Anaconda. Achamos que também é possível chegar à essência
do Python sem todos os penduricalhos que o Anaconda fornece. Logo,
seguimos a rota vanilla.
Antes de examinar os pacotes, aprenderemos a terminologia necessária.
Em R, uma biblioteca é uma coleção de pacotes individuais. O mesmo
ocorre em Python, mas o uso de biblioteca e pacote não é tão rígido. Por
exemplo, o pandas, o pacote que fornece a classe de objetos
pd.DataFrame, é chamado tanto de biblioteca quanto de pacote no
próprio site. Essa mistura dos termos é comum entre os Pythonistas; logo,
se você for rigoroso com nomes, não deixe que isso o confunda ou
incomode. No entanto, no caso dos módulos é importante prestar atenção.
Um pacote é uma coleção de módulos. É útil saber disso já que podemos
carregar um pacote inteiro ou apenas um módulo especí co. Portanto,
geralmente: biblioteca > pacote > módulo.
Em R, você instalaria os pacotes a partir do CRAN com a função
install.packages() de dentro do próprio R. Em Python, existem dois
equivalentes ao CRAN: o PyPI (Python Package Installer, ou Instalador de
Pacotes Python), no caso de uso do vanilla Python, e o Conda, para
quando for usado o Anaconda ou o Miniconda (também veremos
posteriormente como instalar pacotes com o Google Colab diretamente
no notebook online). Para instalar pacotes a partir do PyPI usando o
vanilla Python, você terá de executar um comando no terminal. Lembre-
se de que deixamos aberta no VS Code nossa janela de terminal ativa.
Execute o comando pip install matplotlib no terminal para instalar
o pacote matplotlib em seu ambiente virtual, como mostrado na
Figura 3.10. pip é o instalador de pacotes para Python, que tem várias
versões.
Os pacotes que você instalará em praticamente qualquer ambiente virtual
são o NumPy, o pandas, o matplotlib, o seaborn e o SciPy. Você não
precisará instalar todos sempre, já que as dependências dos pacotes se
encarregarão disso. Se eles já estiverem instalados, o pip dará essa
informação e não instalará nada. As mensagens de erro mais comuns que
você verá aparecerão quando a versão do seu pacote for incompatível com
sua versão do Python. Para resolver isso, você pode usar um kernel (o
back-end de execução) Python diferente em seu projeto ou especi car a
versão exata do pacote que deseja instalar. Como no R, só é necessário
instalar o pacote uma vez, mas você precisará importá-lo (isto é, inicializá-
lo) sempre que ativar seu ambiente. Parece conveniente a instalação do
pacote ocorrer no terminal, separada da importação no script. Você já
deve ter visto muitas funções install.packages() perdidas em
scripts R, o que incomoda um pouco.
Isso nos permitirá usar funções do pacote math. O pacote math já está
instalado, logo não precisamos usar pip, mas precisamos importar o
pacote.
Essa é a primeira vez que encontramos um aspecto comum e importante
da linguagem Python: as palavras-chave, que se comportam como as
palavras reservadas do R, mas são mais numerosas. Atualmente existem
35 palavras-chave em Python que podem ser divididas em grupos
distintos (consulte o Apêndice). Aqui import é uma palavra-chave de
importação. Como um useR acostumado com a programação funcional,
você usaria library(math) em R. Logo, poderia considerar as palavras-
chave como atalhos para as funções, o que em muitos casos elas são. Seria
semelhante aos operadores em R (por exemplo, <-, +, ==, & etc.), que na
verdade são apenas atalhos para as funções. Eles não são escritos no
formato clássico das funções, mas poderiam ser.
Resumindo, as palavras-chave são palavras reservadas que têm
signi cados muito especí cos. Nesse exemplo, import representa uma
função para a importação de todas as funções do pacote math. Muitas
palavras-chave agem dessa forma, mas não todas. Veremos alguns
exemplos em breve.
No entanto, agora que temos as funções do pacote math, tentaremos isto:
math.log(8, 2)
Aqui vemos que o . (ponto) tem um signi cado especí co: dentro do
pacote math, acesse a função log(). Os dois argumentos são o dígito e a
base. Logo, é possível ver por que o Tidyverse R tende a usar _ em vez da
notação com . (ponto) e por que a predominância de um . (ponto) sem
signi cado em muitas funções R frustra os usuários que vêm de
linguagens baseadas na OOP.
Em segundo lugar, podemos importar um pacote inteiro e fornecer para
ele um alias especí co, tipicamente padronizado:
import pandas as pd # Para data frame e manipulação
import numpy as np # Array e processamento numérico
import seaborn as sns # Diagramação de alto nível
Essa é a nossa segunda palavra-chave, as. Observe que ela não está
agindo como substituta de uma função a menos que nos lembremos de
que <- também é uma função. Se deixarmos nossa imaginação voar,
poderíamos considerar como sendo igual ao seguinte em R:
dp <- library(dplyr) # sem sentido, apenas uma ideia
Os useRs não fariam isso, mas esse é o comando análogo que chega mais
próximo do que eles fariam.6 A palavra-chave as é sempre usada com
import para fornecer um alias conveniente para o acesso às funções de
um pacote ou módulo.7 Logo, é uma maneira explícita de chamar a
função exata que queremos. Execute esta função para importar o
conjunto de dados para um trabalho futuro:
plant_growth = pd.read_csv('ch03-py4r/data/plant_growth.csv')
Examine os dados
É sempre boa prática examinarmos nossos dados antes de começar a
trabalhar com eles. Em R usaríamos algo como summary() e str(), ou
glimpse() se tivermos inicializado o dplyr. Vejamos como isso funciona
em Python.
plant_growth.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 30 entries, 0 to 29
Data columns (total 2 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 weight 30 non-null float64
1 group 30 non-null object
dtypes: float64(1), object(1)
memory usage: 608.0+ bytes
plant_growth.describe()
weight
count 30.000000
mean 5.073000
std 0.701192
min 3.590000
25% 4.550000
50% 5.155000
75% 5.530000
max 6.310000
plant_growth.head()
weight group
0 4.17 ctrl
1 5.58 ctrl
2 5.18 ctrl
3 6.11 ctrl
4 4.50 ctrl
(30, 2)
plant_growth.columns
Você deve conhecer os colchetes ([]) já que são usados no R; eles fazem a
indexação de acordo com o nome de uma coluna. Em seguida, o . pega
essa coluna individual e chama um método, .value_counts(), que nesse
caso conta o número de observações para cada valor.
E quanto a isto:
np.mean(plant_growth['weight'])
As tuplas são muito usadas quando uma função retorna vários valores.
Como exemplo, a função divmod() retorna o resultado de uma divisão de
inteiros e o resto:
>>> divmod(10, 3)
(3, 1)
Plotagem
Examinaremos algumas visualizações de dados de peso (weight) descrito
por group. Já que o pacote ggplot2 do R será recomendado para
visualizações de dados elegantes e exíveis na Parte III, deixei de fora os
diagramas dos comandos a seguir. No entanto, é útil vermos a abordagem
do seaborn. Aqui temos um diagrama de caixa:
sns.boxplot(x='group', y='weight', data=plant_growth)
plt.show()
# não exibido
Apenas os pontos:
sns.catplot(x="group", y="weight", data=plant_growth)
plt.show()
Estatística inferencial
Neste conjunto de dados, temos uma de nição especial por haver três
grupos e estarmos interessados em duas comparações especí cas de dois
grupos. Podemos fazer isso estabelecendo um modelo linear:
# alinha um modelo linear
# especifica o modelo
model = ols("weight ~ group", plant_growth)
# alinha o modelo
results = model.fit()
Considerações nais
Em R, houve uma convergência para práticas e uxos de trabalho comuns
desde aproximadamente 2016. Em Python, existe bem mais diversidade
para abraçarmos desde que começamos. Essa diversidade pode parecer
assustadora, mas é apenas um re exo do histórico da origem do Python e
dos casos de uso do mundo real.
Se você é um useR acostumado com o universo da programação
funcional, entender os métodos da OOP também pode parecer
assustador, mas, quando superar esse desa o, você poderá começar a
explorar o poder do Python onde ele realmente brilha, que é o tópico da
Parte III.
Boyan Angelov
Neste capítulo examinaremos ferramentas em Python e R para a
importação e o processamento de dados em vários formatos.
Abordaremos uma seleção de pacotes, comparando-os e realçando as
propriedades que os tornam e cazes. No m dessa investigação, você
poderá selecionar os pacotes con antemente. Cada seção ilustra os
recursos da ferramenta com um estudo de caso pequeno e especí co,
baseado nas tarefas que um cientista de dados encontra diariamente. Se
você estiver fazendo a transição de seu trabalho de uma linguagem para
outra ou apenas quiser descobrir como começar a usar rapidamente
pacotes especí cos de um contexto e com boa manutenção, este capítulo o
guiará.
Antes de começarmos, lembre-se de que o ecossistema open source está
sempre mudando. Novos desenvolvimentos, como os modelos
transformer (https://oreil.ly/PLaGE) e a XAI (explainable arti cial
intelligence, inteligência arti cial explicável) (https://oreil.ly/0sRHV),
parecem surgir quase toda semana. Geralmente eles têm como objetivo
diminuir a curva de aprendizagem e aumentar a produtividade do
desenvolvedor. Essa explosão de diversidade também se aplica aos pacotes
relacionados, resultando em um uxo quase constante de ferramentas
novas e (esperamos) melhores. Se você tiver um problema muito
especí co, provavelmente haverá um pacote já disponível para a sua
situação; logo, não é preciso reinventar a roda. A seleção de ferramentas
pode ser complexa, mas ao mesmo tempo essa diversidade de opções
pode melhorar a qualidade e a velocidade de seu trabalho de ciência de
dados.
Pode parecer que a seleção de pacotes deste capítulo tem uma visão
limitada; portanto, é essencial esclarecer nossos critérios de seleção. Que
qualidades devemos procurar em uma boa ferramenta?
Deve ser open source.
Existe uma grande quantidade de ferramentas comerciais úteis
disponíveis, mas temos certeza de que as ferramentas open source
apresentam uma vantagem maior. Elas tendem a ser mais fáceis de
estender, também facilitam entender como funcionam seus mecanismos
internos e são mais populares.
Deve ter todos os recursos (feature-complete).
O pacote deve incluir um conjunto abrangente de funções que ajudem o
usuário a executar seu trabalho sem precisar recorrer a outras
ferramentas.
Deve ter boa manutenção.
Uma das desvantagens do uso de um OSS (open source software,
software open source) é que às vezes os pacotes têm um ciclo de vida
curto e sua manutenção é abandonada (o chamado “abandonware”).
Queremos usar pacotes que tenham manutenção ativa para podermos
ter certeza de que estarão atualizados.
Começaremos com uma de nição. O que é um formato de dados?
Existem várias respostas disponíveis (https://oreil.ly/M67LQ). Possíveis
candidatos seriam o tipo de dado, o formato de gravação e o formato de
arquivo. O tipo de dado está relacionado aos dados armazenados em
bancos de dados ou aos tipos das linguagens de programação (por
exemplo, integer, oat ou string). O formato de gravação é como os dados
são armazenados em uma mídia física, como um CD ou DVD. E, para
concluir, o que estamos procurando, o formato do arquivo, isto é, como as
informações são preparadas para ns de computação.
Dada essa de nição, você ainda pode estar se perguntando por que
dediquei um capítulo inteiro apenas aos formatos de arquivo. Você pode
ter sido exposto a eles em outro contexto, como ao salvar um conjunto de
slides do PowerPoint com uma extensão .ppt ou .pptx (e querer saber qual
é melhor). O problema aqui vai muito além da compatibilidade básica da
ferramenta. A maneira como as informações são armazenadas in uencia
todas as etapas posteriores do processo de ciência de dados. Por exemplo,
se nosso objetivo nal fosse executar uma análise avançada e as
informações estivessem armazenadas em um formato de texto,
precisaríamos prestar atenção em fatores como a codi cação dos
caracteres (um problema conhecido, principalmente em Python).1 Para
esses dados serem processados de maneira e caz, também precisariam
passar por várias etapas, como a tokenização (https://oreil.ly/ek4s9) e a
remoção de palavras vazias (stop words) (https://oreil.ly/zojPz).2 Essas
mesmas etapas não são aplicáveis a dados de imagem, ainda que
tivéssemos o mesmo objetivo nal em mente, por exemplo, a classi cação.
Nesse caso, outras técnicas de processamento são mais adequadas, como
o redimensionamento e o escalonamento. Essas diferenças nos pipelines
de processamento de dados são mostradas na Figura 4.1. Resumindo: o
formato dos dados é o fator mais signi cativo que in uencia o que
podemos ou não fazer com eles.
data = pd.read_csv("dataset.csv")
Em segundo lugar, com o módulo interno csv:
import csv
Dados de imagem
As imagens trazem um conjunto de desa os único para os cientistas de
dados. Demonstraremos a metodologia ótima abordando o desa o do
processamento de imagens aéreas – uma área de importância crescente na
agricultura, na conservação da biodiversidade, no planejamento urbano, e
na pesquisa de mudanças climáticas. Nosso pequeno caso de uso utiliza
dados do Kaggle coletados para ajudar na detecção de piscinas e carros.
Para obter mais informações sobre o conjunto de dados, você pode usar a
URL da Tabela 4.2.
Como mencionamos no começo do capítulo, a nalidade de etapas
posteriores do processo in uencia muito o processamento dos dados. Já
que dados aéreos são usados com frequência no treinamento de
algoritmos de machine learning, daremos ênfase às tarefas preparatórias.
O pacote OpenCV (https://opencv.org) é uma das maneiras mais comuns
de trabalhar com dados de imagem em Python. Ele contém todas as
ferramentas necessárias para o carregamento, a manipulação e o
armazenamento de imagens. O “CV” do nome signi ca computer vision –
a área de machine learning que se dedica aos dados de imagem. Outra
ferramenta útil que usaremos é o scikit-image. Como seu nome sugere, ele
está intimamente relacionado com o scikit-learn (https://oreil.ly/ZCR55).7
Aqui estão as etapas de nossa tarefa (consulte a Tabela 4.2):
1. Redimensionar a imagem para um tamanho especí co.
2. Converter a imagem para preto e branco.
3. Aumentar os dados girando a imagem.
Para um algoritmo de ML aprender com sucesso a partir dos dados, a
entrada tem de ser limpa (data munging, manipulação de dados),
padronizada (escalonamento) e ltrada (engenharia de recursos).8
Suponhamos que você coletasse um conjunto de dados de imagens (por
exemplo, fazendo o scraping de dados do Google Images).9
Eles diferirão de alguma forma – como no tamanho e/ou na cor. As
etapas 1 e 2 de nossa lista de tarefas nos ajudarão a lidar com isso. A
etapa 3 é útil para aplicações de ML. O desempenho (isto é, a precisão da
classi cação, ou a AUC [área sob a curva]) dos algoritmos de ML depende
em grande parte da quantidade de dados de treinamento, que geralmente
ocorre em pequeno volume. Para resolver esse problema, sem recorrer à
obtenção de mais dados,10 os cientistas de dados descobriram que
manusear os dados já disponíveis, como girá-los e recortá-los, pode
introduzir novos pontos de dados. Esses novos pontos de dados podem
então ser usados para treinar o modelo novamente e melhorar o
desempenho. Esse processo é conhecido formalmente como aumento de
dados (data augmentation).11
Já falamos demais – vamos importar os dados! Veri que o código
completo no repositório (https://github.com/moderndatadesign/PyR4MDS)
do livro se quiser fazer o acompanhamento. Os resultados estão na
Figura 4.2.
import cv2❶
single_image = cv2.imread("img_01.jpg")
plt.imshow(single_image)
plt.show()
❶ Usar cv2 pode parecer confuso, já que o pacote se chama OpenCV.
cv2 é usado como uma abreviação. O mesmo padrão de nomeação é
utilizado para o scikit-image, em que a instrução de importação é
abreviada para skimage.
Em que tipo de objeto cv2 armazenou os dados? Podemos veri car com
type:
print(type(single_image))
numpy.ndarray
Há pela menos uma exceção a essa regra – o pacote EBImage, que faz
parte do BioConductor (https://bioconductor.org). Usando-o você pode ter
acesso à imagem em sua forma bruta de array e então utilizar
também outras ferramentas. A desvantagem é que ele faz parte de um
pacote especí co de uma área, e pode não ser fácil saber como
funcionaria em um pipeline CV padrão.
Observe que, na etapa anterior (na qual carregamos a imagem bruta em
Python), também usamos uma das ferramentas de diagramação mais
populares, o matplotlib (a visualização de dados será abordada no
Capítulo 5); logo, nos bene ciamos novamente desse padrão melhor de
design.
Dados de texto
Geralmente a análise de dados de texto é usada de maneira
intercambiável com o termo NLP (natural language processing,
processamento de linguagem natural). Essa, por sua vez, é uma subárea do
ML. Logo, não é de surpreender que ferramentas baseadas em Python
também a dominem. A natureza de uso inerentemente intensivo de
computação do trabalho com dados de texto é uma boa razão para isso.
Outra seria que lidar com conjuntos de dados maiores pode ser um
desa o mais difícil em R do que em Python (esse tópico será abordado
com mais detalhes no Capítulo 5).14 E trata-se de um problema de
big data. A quantidade de dados de texto tem proliferado nos últimos
anos com o surgimento de serviços nas grandes corporações de internet e
mídias sociais como o Twitter e o Facebook. Essas organizações também
têm investido pesadamente na tecnologia e em ferramentas open source
relacionadas, devido ao fato de que grande parte dos dados disponíveis
para elas está no formato de texto.
Como no caso dos dados de imagem, começaremos projetando uma
tarefa NLP padrão. Ela deve conter os elementos mais básicos de um
pipeline NLP. Para o conjunto de dados, selecionamos um de textos de
críticas de produtos da Amazon (Tabela 4.2) e temos de prepará-lo para
um caso de uso de análise avançado, como de classi cação de texto,
análise de sentimentos ou modelagem de tópicos. As etapas necessárias
para a conclusão são as seguintes:
1. Tokenizar os dados.
2. Remover palavras vazias.
3. Marcar as PoS (parts of speech, partes da fala).
Também examinaremos métodos mais avançados (como a incorporação
de palavras) no spaCy para demonstrar do que os pacotes Python são
capazes e, ao mesmo tempo, fornecer alguns exemplos de R para
comparação.
Quais seriam as ferramentas mais comuns em Python? Geralmente a
mais popular é chamada de canivete suíço do NLP – o NLTK (Natural
Language Toolkit).15 Ele contém uma boa seleção de ferramentas que
abrangem o pipeline inteiro. Também fornece uma excelente
documentação e uma curva de aprendizagem relativamente baixa para
sua API.
Para um cientista de dados, uma das primeiras etapas de um projeto é
examinar os dados brutos. Aqui está o exemplo de uma crítica, com seu
tipo de dado:
example_review = reviews["reviewText"].sample()
print(example_review)
print(type(example_review))
I just recently purchased her ''Paint The Sky With Stars''
CD and was so impressed that I bought 3 of her previously
released CD's and plan to buy all her music. She is
truely talented and her music is very unique with a
combination of modern classical and pop with a hint of
an Angelic tone. I still recommend you buy this CD. Anybody
who has an appreciation for music will certainly enjoy her music.
str
Essa parte é importante – os dados estão armazenados em um tipo de
dado básico em Python – str (string). Semelhante ao que ocorreu com os
dados de imagem que foram armazenados como um array
multidimensional do NumPy, várias ferramentas poderão ter acesso a ele.
Por exemplo, suponhamos que fôssemos usar uma ferramenta que
pesquisasse e substituísse e cientemente partes de uma string, como o
ashtext (https://oreil.ly/JyYW6). Nesse caso, poderíamos usá-la aqui sem
problemas de formatação e a necessidade de fazer a coerção do tipo de
dado.16
Agora podemos executar a primeira etapa de nosso pequeno estudo de
caso – a tokenização. Ela dividirá as críticas em componentes, como em
palavras ou frases:
sentences = nltk.sent_tokenize(example_review)
print(sentences)
["I just recently purchased her ''Paint The Sky With Stars''
CD and was so impressed that I bought 3 of her
previously released CD's and plan to buy all her music.",
'She is truely talented and her music is very unique with
a combination of modern classical and pop with a hint of an Angelic tone.',
'I still recommend you buy this CD.',
'Anybody who has an appreciation for music will certainly enjoy her music.']
Muito fácil! Para ns de ilustração, seria muito difícil tentar executar essa
tarefa relativamente simples em R, com algumas funções do pacote
tidytext?
tidy_reviews <- amazon_reviews %>%
unnest_tokens(word, reviewText) %>%
mutate(word = lemmatize_strings(word, dictionary = lexicon::hash_lemmas))
nlp = spacy.load("en_core_web_sm") ❶
doc = nlp(example_review) ❷
print(type(doc))
spacy.tokens.doc.Doc
Por que isso seria melhor do que o pandas? Bem, depois de conseguir
converter os dados brutos em um pd.DataFrame de série temporal, você
ainda encontrará um novo conceito – a indexação do data frame (consulte
a Figura 4.5). Para ser e ciente na manipulação dos dados, antes você
precisa entender como esse conceito funciona!
O conceito de indexação pode ser confuso, logo examinaremos agora qual
é a alternativa em R e se ela é melhor. Já existem algumas coisas úteis que
podemos fazer com o objeto de série temporal df_ts.
Prophet
Existe outro exemplo de pacote interessante para a análise de dados de
séries temporais. Ele foi desenvolvido simultaneamente tanto para R
quanto para Python (semelhante ao ocorrido com a ferramenta de ML
explicável lime): trata-se do pacote Prophet do Facebook
(https://oreil.ly/WNOyF). Esse exemplo pode nos ajudar a comparar as
diferenças no design de APIs. O Prophet é um pacote cuja principal
vantagem está na exibilidade de o usuário de uma área conseguir fazer
ajustes de acordo com suas necessidades especí cas, na facilidade de uso
da API e na ênfase dada à preparação para a produção. Esses fatores o
tornam uma boa opção para a prototipagem de trabalhos com séries
temporais e para o seu uso em um produto de dados. Façamos uma
veri cação; nossos dados foram armazenados como um pd.DataFrame
em df:
from fbprophet import Prophet
m = Prophet()
m.fit(df)❶
future = m.make_future_dataframe(periods=365) ❷
future.tail()
m <- prophet(df)
Dados espaciais
A análise de dados espaciais é uma das áreas mais promissoras do
machine learning moderno e tem uma rica história. Novas ferramentas
foram desenvolvidas nos últimos anos, mas por muito tempo o R levou
vantagem, apesar de alguns avanços recentes em Python. Como nas seções
anteriores, examinaremos um exemplo prático para ver os pacotes em
ação.
Aqui usamos a útil função extent para recortar (cortar) os dados raster –
só estamos interessados em uma subseção de todas as camadas
ambientais existentes ao redor dos dados de ocorrência. Usamos as
coordenadas de latitude e longitude para desenhar esse retângulo. Como
próxima etapa, para gerar um problema de classi cação, estamos criando
uma amostragem aleatória dos pontos de dados a partir dos dados raster
(as chamadas pseudoausências). Você poderia considerá-los os 0s de sua
tarefa de classi cação, e as ocorrências (observações) os 1s – a variável
alvo. Em seguida, convertemos as pseudoausências em SpatialPoints e,
para concluir, também extraímos seus dados climáticos. Na função
SpatialPoints, é possível ver que especi camos o sistema de projeção
geográ ca, um dos conceitos básicos da análise de dados espaciais.
Um dos problemas mais comuns do trabalho em ML são as correlações
dentro dos dados. A suposição básica que fazemos para considerar que
um conjunto de dados está correto é a de que as observações individuais
dos dados devem ser independentes umas das outras para obtermos
resultados estatísticos precisos. Esse problema está sempre presente nos
dados espaciais devido à sua natureza. Ele é chamado de autocorrelação
espacial. Existem vários pacotes disponíveis para a criação de amostragens
dos dados que tentam reduzir esse risco. Um deles é o ENMeval:
library(ENMeval)
check1 <- get.checkerboard1(occs, envs, bg, aggregation.factor=5)
Considerações nais
Neste capítulo examinamos os diferentes formatos de dados mais comuns
e os melhores pacotes para o seu processamento de modo a carem
prontos para tarefas avançadas. Em cada estudo de caso, demonstramos
um bom design de pacote e como isso pode tornar um cientista de dados
mais produtivo. Vimos que para tarefas mais direcionadas ao ML, como a
CV e o NLP, Python está fornecendo a melhor experiência de usuário e
uma curva de aprendizagem mais baixa. Por outro lado, para uma
previsão mais voltada para séries temporais e para a análise espacial, o R
leva vantagem. Essas opções de escolha são mostradas na Figura 4.9.
Figura 4.9: Árvore de decisão para a seleção de pacotes.
O que as melhores ferramentas têm em comum é um design de pacote
melhor (Figura 4.3). Você deve sempre usar a melhor ferramenta para a
tarefa e prestar atenção na complexidade, na documentação e no
desempenho das ferramentas que usar!
1 Para ver uma explicação mais detalhada sobre esse assunto, consulte o guia do RealPython.com.
2 Normalmente isso é chamado de linhagem de dados.
3 Quem mais não aprendeu o que if __name__ == "__main__" faz em Python?
4 Uma tabela com os dados, armazenados em um único arquivo.
5 Não devemos nos esquecer do readr, que foi discutido no Capítulo 2.
6 Mencionamos que os estatísticos são muito literais, lembra-se?
7 Essa consistência é um tópico comum nos capítulos da Parte IV e também é abordada no
Capítulo 5.
8 Lembre-se – entra lixo, sai lixo.
9 Usar código para percorrer o conteúdo de uma página web, baixando-o e armazenando-o em um
formato legível por máquinas.
10 A obtenção de mais dados pode ser cara, ou até mesmo impossível em alguns casos.
11 Se quiser aprender mais sobre o aumento de dados de imagens, examine esse tutorial.
12 Veri cação feita quando este texto foi escrito.
13 A pilha PyData está relacionada com o NumPy, SciPy, pandas, IPython e matplotlib e não deve
ser confundida com a conferência de mesmo nome.
14 A comunidade R também se apressou e melhorou as ferramentas recentemente, mas é possível
que ainda não tenha alcançado o nível dos equivalentes no Python.
15 Para saber mais sobre o NLTK, consulte Natural Language Processing with Python, de Steven
Bird, Ewan Klein e Edward Loper (O’Reilly), um dos livros mais acessíveis sobre o trabalho com
dados de texto.
16 A coerção de tipos de dados é a conversão de um tipo de dado em outro.
17 Essa é uma etapa comum no NLP. Alguns exemplos de palavras vazias são “the”, “a” e “this”.
Elas têm de ser removidas, já que raramente oferecem informações úteis para algoritmos de ML.
18 Processo de rotular palavras com as PoS às quais elas pertencem.
19 Converter texto em números para ingestão por um algoritmo de ML.
20 Como na tentativa de criar incorporações personalizadas. Consulte o blog do RStudio
(https://oreil.ly/waD3o) para obter mais informações.
21 Você pode ler mais sobre isso no blog do RStudio (https://oreil.ly/rUaWz).
22 Dados representando células, em que o valor da célula representa alguma informação.
23 Características ambientais determinadas pelos ecologistas para serem altamente preditivas das
distribuições de espécies, isto é, umidade e temperatura.
CAPÍTULO 5
Boyan Angelov
Uma fonte de frustração comum para os cientistas de dados é a discussão
de seu trabalho com colegas de áreas adjacentes. Vejamos o exemplo de
alguém que tem trabalhado principalmente no desenvolvimento de
modelos de ML, conversando sobre seu trabalho com um colega da
equipe de BI (business intelligence, inteligência empresarial), que dá
ênfase a relatórios. Geralmente, essa discussão deixa as duas partes
desconfortáveis devido a uma perceptível falta de conhecimento sobre
suas áreas de trabalho (sobre os uxos de trabalho associados) – apesar
de compartilharem uma função de mesmo nome. O pro ssional de ML
pode não saber o que é D3.js, gramática dos grá cos etc. Por outro lado, o
cientista de dados de BI pode se sentir inseguro por não saber como
construir uma API implantável. Os sentimentos que podem a orar de
uma situação desse tipo têm sido chamados de síndrome do impostor, na
qual surgem dúvidas sobre a competência do pro ssional. Essa situação é
um subproduto do grande volume de aplicações possíveis na ciência de
dados. Raramente uma pessoa tem o mesmo nível de familiaridade com
mais do que algumas subáreas. A exibilidade ainda é frequentemente
exigida nessa área em rápida evolução.
Essa complexidade é a razão da ênfase dada neste capítulo ao uxo de
trabalho. Abordaremos os principais uxos de trabalho da ciência de
dados e como os diferentes ecossistemas das linguagens os suportam.
Semelhante ao que ocorreu no Capítulo 4, no m do capítulo, você terá
tudo que é necessário para tomar decisões embasadas relacionadas aos
seus uxos de trabalho.
De nindo uxos de trabalho
Faremos uma pausa para de nir um uxo de trabalho:
Um uxo de trabalho é uma coleção completa de ferramentas e
frameworks para a execução de todas as tarefas requeridas pelas
competências de um cargo especí co.
Para esse exemplo, suponhamos que você fosse um engenheiro de ML.
Suas tarefas diárias poderiam incluir ferramentas para a obtenção de
dados, para o seu processamento e para o treinamento de um modelo
com os dados, e frameworks de implantação. Coletivamente, essas
ferramentas representam o uxo de trabalho do engenheiro de ML. Uma
visão geral dos uxos de trabalho de dados para essa e outras funções e
de suas ferramentas de suporte é apresentada na Tabela 5.1.
Tabela 5.1: Fluxos de trabalho comuns na ciência de dados e suas
ferramentas de apoio
Método Pacote Python Pacote R
Manipulação de dados (data munging)(a) pandas dplyr
EDA matplotlib, seaborn, pandas ggplot2, base R, Lea et
Machine learning scikit-learn mlr, tidymodels, caret
Deep learning Keras, TensorFlow, PyTorch Keras, TensorFlow, torch
Engenharia de dados(b) Flask, BentoML, FastAPI plumber
Relatórios Jupyter, Streamlit R Markdown, Shiny
(a) Data munging (ou wrangling) é um tópico fundamental na ciência de dados que já foi
abordado no Capítulo 2.
(b) A engenharia de dados vai muito além da implantação de modelos, mas decidimos nos
concentrar nesse subconjunto para ilustrar os recursos do Python.
Omitimos algumas áreas na esperança de que as listadas sejam as mais
comuns e críticas. Os uxos de trabalho selecionados estão relacionados
uns com os outros, como apresentado na Figura 5.1. Esse diagrama tem
uma aparência semelhante à do framework CRISP-DM
(https://oreil.ly/19361), que mostra todas as etapas signi cativas de um
projeto de ciência de dados típico. Cada etapa do diagrama tem um uxo
de trabalho separado associado a ela, geralmente atribuído a uma pessoa
ou a uma equipe.
Agora que de nimos um uxo de trabalho, quais são as propriedades
de nidoras de um que seja “bom”? Podemos criar uma lista de veri cação
com os três principais fatores a serem considerados:
1. É estabelecido. Ele foi amplamente adotado pela comunidade (e
também por diferentes áreas de aplicação, como a visão
computacional ou o processamento de linguagem natural).
2. É suportado por um ecossistema e uma comunidade open source
com boa manutenção. Um uxo de trabalho que dependa
pesadamente de aplicações de código-fonte fechado (closed-source) e
comerciais (como o MATLAB) não é considerado aceitável.
3. É adequado à sobreposição de tarefas da função. Os melhores uxos
de trabalho são semelhantes às peças do Lego – seu design modular e
extensibilidade podem suportar diversas pilhas de tecnologia.
Com o cenário geral e as de nições fora do caminho, podemos nos
aprofundar nos diferentes uxos de trabalho e em como eles são
suportados em R e Python!
Visualizações estáticas
Você já deve estar familiarizado com os recursos do base-R relacionados à
DV que vimos no Capítulo 4, principalmente os de diagramação de séries
temporais. Aqui daremos um passo à frente e discutiremos um dos
pacotes R mais famosos – o ggplot2. Ele é uma das principais razões para
os Pythonistas quererem mudar para o R.2 O que torna o ggplot2 tão
bem-sucedido no trabalho com a EDA é que ele é baseado em uma
metodologia bem planejada – a gramática dos grá cos, que foi
desenvolvida por L. Wilkinson. O pacote ggplot2 foi desenvolvido por
Hadley Wickham.3
O que é a gramática dos grá cos? O artigo original
(https://oreil.ly/BFQQc) que a inspirou chama-se “A Layered Grammar of
Graphics” (Uma gramática dos grá cos em camadas) e a palavra “layered”
é a chave. Tudo que vemos em um diagrama contribui para a formação de
uma pilha ou sistema maior. Por exemplo, os eixos e as grades formam
uma camada separada em comparação com as linhas, barras e pontos.
Esses últimos elementos constituem a camada de dados. A pilha completa
de camadas forma o resultado – um ggplot completo. Esse padrão de
design modular permite grande exibilidade e fornece uma nova maneira
de pensarmos em visualização de dados. A lógica existente por trás da
gramática dos grá cos é ilustrada pela Figura 5.2.
Figura 5.2: A gramática dos grá cos baseada em camadas.
Para ilustrar os diferentes procedimentos de um uxo de trabalho comum
da EDA, usaremos o conjunto de dados starwars (disponível no pacote
dplyr).4 Esse conjunto de dados contém informações sobre os personagens
do lme Guerra nas Estrelas, como seu gênero, altura e espécie. Vejamos
então!
library(ggplot2)
library(dplyr)
data("starwars") ❶
❶ ] Esse código tornará o conjunto de dados visível no ambiente do
RStudio, mas isso não é obrigatório.
Como primeira etapa, criaremos um diagrama básico:
ggplot(starwars, aes(hair_color)) +
geom_bar()
Ele representa gra camente as contagens da variável de cor do cabelo.
Aqui, vemos um operador familiar, +, usado de maneira não
convencional. Usamos + no ggplot2 para adicionar camadas acima umas
das outras. Vamos nos basear nisso para um caso mais complexo. Observe
que omitimos uma etapa de ltragem do código (há um valor discrepante
– Jabba the Hutt):5
ggplot(starwars, aes(x = height, y = mass, fill = gender)) + ❶
geom_point(shape = 21, size = 5) + ❷
theme_light() + ❸
geom_smooth(method = "lm") +❹
labs(x = "Height (cm)", y = "Weight (cm)",
title = "StarWars profiles ",
subtitle = "Mass vs Height Comparison",
caption = "Source: The Star Wars API")❺
❶ Especi ca que dados e características usar.
❷ Seleciona um diagrama de pontos (o mais adequado para dados
contínuos).
❸ Usa um tema (theme) interno – uma coleção de estilos de camada
especí cos.
❹ Ajusta um modelo linear e mostra os resultados como uma camada
no diagrama.
❺ Adiciona rótulos para o título e os eixos.
Os resultados dessa operação de diagramação são mostrados na
Figura 5.3. Com apenas algumas linhas de código, criamos um belo
diagrama, que pode ser estendido ainda mais.
Agora que abordamos as visualizações estáticas, veremos como torná-las
mais interessantes adicionando interatividade!
Figura 5.3: Diagrama avançado do ggplot2.
Visualizações interativas
A interatividade pode ser de grande ajuda nos diagramas exploratórios.
Dois excelentes pacotes do R se destacam: Lea et
(https://rstudio.github.io/lea et) e plotly (https://plotly.com).
Machine Learning
Atualmente, a ciência de dados é quase um sinônimo de machine
learning (ML). Embora existam muitos uxos de trabalho diferentes
necessários em um projeto de ciência de dados (Figura 5.1), geralmente o
ML é que chama a atenção dos aspirantes a cientistas de dados. Isso
ocorre em parte devido a uma disseminação cada vez maior nos últimos
anos provocada pela disponibilidade de grandes quantidades de dados e
de recursos computacionais melhores (como CPUs e GPus melhores), e
pela necessidade de previsões e automação nas empresas modernas.
Quando essa área surgiu, ela tinha um nome diferente – aprendizagem
estatística (statistical learning). Como já mencionado, historicamente a
estatística é a principal área atendida pelo R. Logo, existiam ferramentas
boas disponíveis desde o início para o trabalho com ML nessa linguagem.
No entanto, ultimamente isso mudou e na maioria das vezes as
ferramentas do Python superam às de seu concorrente estatístico.
Se rastreássemos o sucesso do ecossistema de ML do Python,
chegaríamos a um pacote especí co: o scikit-learn (https://oreil.ly/ZCR55).
Desde suas primeiras versões, a equipe de desenvolvimento básico se
dedicou a projetar uma API acessível e fácil de usar. Eles a
complementaram com uma das documentações mais completas e
acessíveis disponíveis no universo open source. Além de ser uma
documentação de referência, ela também contém ótimos tutoriais sobre
várias aplicações de ML especí cas modernas como o trabalho com dados
de texto (https://oreil.ly/ZXsrG). O scikit-learn dá acesso direto a quase
todos os algoritmos de ML comuns.7
Examinaremos provas de por que o scikit-learn é tão bom para ML. Em
primeiro lugar, podemos demonstrar as importações de modelos:
from sklearn.ensemble import RandomForestClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.linear_model import LinearRegression
visualizer = ResidualsPlot(regr)
visualizer.fit(X_train, y_train)
visualizer.score(X_test, y_test)
visualizer.show()
Engenharia de dados
Apesar dos avanços obtidos nas ferramentas de ML nos últimos anos, a
taxa de conclusão desses projetos nas empresas permanece baixa. Uma
razão frequentemente associada a isso é a falta de suporte à DE (data
engineering, engenharia de dados). Para aplicar ML e análise avançada, as
empresas precisam da base infraestrutural fornecida pelos engenheiros de
dados, incluindo os bancos de dados, os pipelines de processamento de
dados, teste e ferramentas de implantação. É claro que isso forma um
cargo diferente – o engenheiro de dados. Mesmo assim, os cientistas de
dados precisam interagir com essas tecnologias (e às vezes implementá-
las) para assegurar que os projetos de ciência de dados sejam concluídos
com sucesso.
Embora a DE seja uma área imensa, nos concentraremos em um
subconjunto nesta seção. Selecionamos a implantação de modelos, já que
ela é o uxo de trabalho de DE mais comum do qual um cientista de
dados pode ter de participar. Então, o que é implantação de ML? Quase
sempre, isso signi ca criar uma API (application programming interface,
interface de programação de aplicações) e torná-la disponível para outras
aplicações, internamente ou externamente (para os clientes, chama-se
“expor” uma API, para ser “consumida”). Normalmente os modelos de
ML são implantados por meio de uma interface REST (representational
state transfer, transferência representacional de estado).10
A implantação de modelos de ML, em comparação com os outros tópicos
deste capítulo, requer interação com muitas tecnologias diferentes não
diretamente relacionadas à ciência de dados. Elas incluem frameworks
web, CSS, HTML, JavaScript, servidores de nuvem, balanceadores de
carga e outros componentes. Logo, não é de surpreender que as
ferramentas Python sejam predominantes aqui – como mencionamos,
trata-se de uma ótima linguagem aglutinadora.11
# serialização do modelo
outfile = open("models/regr.pkl", "wb")
pickle.dump(regr, outfile)
outfile.close()
app = Flask(__name__) ❷
infile = open("models/regr.pkl", "rb") ❸
regr = pickle.load(infile)
infile.close()
@app.route('/')❹
def predict(methods=["GET"]):
payload = request.json["data"]
input_data = np.array(literal_eval(payload)).reshape(1, -1)
prediction = regr.predict(input_data) ❺
return jsonify({
"prediction": round(float(prediction), 3) ❻
})
if __name__ == '__main__':
app.run(debug=True)
❶ Usamos essa função para especi car que o objeto string payload é na
verdade um dicionário.
❷ Aqui criamos um objeto que contém a aplicação.
❸ Nessas linhas carregamos o modelo serializado.
❹ Este decorador Python cria um endpoint.
❺ Nesta etapa, o modelo serializado é usado para inferência.
❻ Os resultados da inferência são retornados em um formato JSON.
Esse código será adicionado a um arquivo app.py. Quando você executar
esse script, a linha de comando exibirá uma URL local. Poderemos então
usar uma ferramenta como o Postman para consultá-la.14 Examine a
Figura 5.8 para ver como essa consulta funciona. E aí está – construímos
uma API de ML!
Relatórios
Qualquer cientista de dados sabe (talvez até mais do que gostaria) como a
comunicação é vital para seu trabalho diário. Ela também costuma ser
uma habilidade subestimada; logo, nunca é demais enfatizar sua
importância. Bem, o que seria mais importante do que um dos produtos
essenciais de um projeto de ciência de dados – relatar seus resultados?
Existem vários métodos de apresentação de relatórios disponíveis. O caso
de uso mais típico para um cientista de dados é a criação de um
documento, ou de um conjunto de slides, contendo os resultados da
análise que ele executou em um conjunto de dados. Geralmente se trata
de uma coleção de visualizações com um texto associado e uma narrativa
consistente (isto é, percorrendo os diferentes estágios do ciclo de vida de
um projeto – importação, limpeza e visualização dos dados). Há outras
situações em que o relatório tem de ser exibido com frequência e
atualizado em tempo real, caso em que ele é chamado de painel. E, para
concluir, alguns relatórios permitem que o usuário nal os examine mais
interativamente. Veremos esses três tipos de relatórios nas próximas
subseções.
Relatório estático
A popularização da linguagem de marcação (markdown) ajudou os
cientistas de dados a se concentrarem em escrever código e a pensarem em
tarefas relacionadas em vez de precisarem se preocupar com a ferramenta
propriamente dita. Uma versão dessa linguagem, o RMD (R Markdown),
é amplamente empregada na comunidade R. Isso permite o uso do
conceito de programação literária, em que o código é combinado à análise.
O IDE RStudio fornece ainda mais funcionalidades com ferramentas
como os R Notebooks (https://oreil.ly/3STa2). Veja como é fácil escrever
um relatório RMD:
# Analisando Guerra nas Estrelas
First we start by importing the data.
```{r}
library(dplyr)
data(starwars)
```
Relatório interativo
E se quiséssemos deixar que os destinatários de nossos relatórios também
zessem algo? Se permitirmos o uso de alguma interatividade, nossos
usuários nais poderão responder a perguntas por conta própria sem
precisar que alteremos o código e geremos novamente os grá cos. Existem
várias ferramentas disponíveis,15 mas a maioria delas é ofuscada pela
facilidade de uso e os recursos do pacote shiny do R.16
Usar essa ferramenta requer uma maneira um pouco diferente de escrever
código R, mas você criará aplicações fantásticas quando se acostumar
com ela. Percorreremos um exemplo básico, porém prático. As aplicações
shiny são compostas de dois elementos fundamentais: a UI (user
interface, interface de usuário) e a lógica do servidor. Geralmente eles
cam separados em dois arquivos. Para simpli car, usaremos o layout de
arquivo único e usaremos duas funções para a aplicação:
library(shiny)
ui <- fluidPage( ❶
titlePanel("StarWars Characters"),
sidebarLayout(
sidebarPanel(
numericInput("height", "Minimum Height:", 0, min = 1, max = 1000),
❷
numericInput("weight", "Minimum Weight:", 0, min = 1, max = 1000),
hr(),
helpText("Data from dplyr package.")
),
mainPanel(
plotOutput("distPlot") ❸
)
)
)
Considerações nais
Neste capítulo, percorremos os uxos de trabalho essenciais de um
projeto de ciência de dados em R e Python. Em termos de EDA e de
relatórios, o R pode ser coroado rei. Pacotes como o ggplot2 não têm
concorrentes na comunidade da ciência de dados, e o shiny permite o uso
de maneiras novas e fascinantes de apresentação de resultados de ciência
de dados para stakeholders e colegas. Nos universos do ML e da DE, a
natureza aglutinadora do Python fornece ótimas opções, permitindo que
os cientistas de dados modernos se concentrem no trabalho, e não nas
ferramentas.
1 É um pouco injusto apresentar o matplotlib como a única alternativa viável do Python. O pacote
seaborn (https://seaborn.pydata.org) também permite a criação de belos diagramas rapidamente,
mas mesmo assim não chega ao nível dos recursos do ggplot. Versões mais novas do pandas
também têm recursos de diagramação; logo, é preciso prestar atenção nisso.
2 Foram feitas tentativas de recriar esse pacote em Python, como a do ggplot
(https://oreil.ly/z4AoA), mas até agora elas não empolgaram a comunidade.
3 Ele criou vários outros pacotes, e em certos aspectos alterou quase sozinho a maneira de as
pessoas usarem o R em um contexto moderno. Consulte o Capítulo 2 e The Grammar of
Graphics, de Leland Wilkinson et. al. (Springer), para obter mais informações sobre seus pacotes.
4 Mais informações sobre o conjunto de dados estão disponíveis na Documentação de Pacotes R
(https://oreil.ly/JXsJg).
5 Sabia que seu nome real é Jabba Desilijic Tiure?
6 Examine a documentação o cial para ver diferentes estilos de mapa.
7 Uma visão geral deles está disponível no scikit-learn.
8 Para os leitores iniciantes em ML, a aprendizagem supervisionada está relacionada a tarefas de
previsão em que um alvo está disponível (o rótulo), em comparação com a aprendizagem não
supervisionada na qual ele inexiste, e a tarefa de previsão se dá na descoberta de grupos nos
dados.
9 Para ver a complexidade das arquiteturas de ML, consulte o documento MLOps do Google.
10 Para saber mais sobre o que é REST, consulte a página da Wikipedia (https://oreil.ly/OPaFE).
11 A alternativa do R para o Flask é o plumber. O IDE RStudio fornece uma interface amigável
para o uso dessa ferramenta, mas, mesmo assim, ela ainda ca para trás nas opções e na adoção
pela comunidade de ML.
12 Para sermos breves, não nos aprofundaremos na instalação de ambientes virtuais aqui. Pedimos
ao leitor dedicado que se informe sobre as ferramentas virtualenv (https://oreil.ly/oqn0Y) e renv
(https://oreil.ly/7szIG), abordadas no Capítulo 3.
13 O conjunto de dados é “Boston Housing”, disponível no scikit-learn (https://oreil.ly/xpTI6).
14 Se você é uma pessoa mais acostumada à linha de comando, tente usar o curl.
15 Existe uma ferramenta nova e avançada em Python, chamada Streamlit
(https://www.streamlit.io), mas ela ainda não se popularizou ou foi adotada.
16 Para se maravilhar com o que é possível fazer no shiny, examine a galeria de casos de uso no site
do RStudio (https://oreil.ly/DVbDd).
PARTE IV
Rick J. Scavetta
A interoperabilidade, a possibilidade de diferentes linguagens de
programação operarem em conjunto, é um pilar da computação. O ideal é
que os objetos possam ser compartilhados diretamente entre as duas
linguagens. Como era de se esperar, isso pode ser problemático por várias
razões, como o uso da memória e estruturas de armazenamento de dados
incompatíveis, para citar apenas duas. Embora tenham sido feitas muitas
tentativas de se implementar essa abordagem de maneira menos
traumática entre Python e R, só nos últimos anos é que um kit
razoavelmente funcional foi nalizado. Discutirei isso em
“Interoperabilidade”, na página 139. No entanto, seria útil antes voltarmos
ao básico. Além de nos dar um contexto para apreciarmos a
interoperabilidade sem problemas posteriormente, essa decisão fornecerá
uma solução básica que talvez já atenda às suas necessidades. Contudo, se
você já quiser começar a lidar com a interoperabilidade, pode pular a
próxima seção.
Falsa operabilidade
O tipo mais básico de interoperabilidade, às vezes chamada de cross-talk,
na verdade é uma falsa operabilidade. Executamos scripts prede nidos
entre linguagens, passando informações entre elas usando arquivos como
intermediários. Imagine a situação a seguir, que diagramamos na Figura
6.1.
Figura 6.1: Exemplo de cross-talk para facilitar a interoperabilidade.
Em R, após fazer algum trabalho necessário em um objeto, por exemplo,
PlantGrowth, executaríamos:
# (As interessantes e complicadas etapas anteriores foram omitidas)
Observe que essa função faz apenas uma sugestão e não resulta em erro se
a build desejada não for encontrada, a menos que o argumento required
seja con gurado com TRUE.
Antes de continuar, queremos estabelecer um ambiente virtual. Se você
estiver no Windows, terá de usar um ambiente conda, que veremos em
breve. Caso contrário, use o comando a seguir para criar um ambiente
virtual chamado modern_data:
virtualenv_create("modern_data")
A última etapa é ativar nosso ambiente virtual. Essa parece ser uma área
que está em rápido desenvolvimento. Diferentes mensagens de erro, ou
nenhuma, serão produzidas dependendo de suas versões do reticulate e
do RStudio, tornando-os mais difíceis de depurar. Pela minha experiência,
a melhor opção é (i) certi car-se de que todos os seus pacotes R, assim
como o RStudio, estejam atualizados e (ii) reiniciar o R antes de ativar seu
ambiente virtual. Você pode fazer isso no menu Session > Restart R do
RStudio, com o atalho de teclado Shift-Command/Ctrl + F10, ou
executando o comando .rs.restartR(). Também pode fechar e reiniciar
literalmente o RStudio. Isso assegurará que não haja nenhuma build
Python em uso ativo e poderemos estabelecer uma a partir do zero. Logo,
temos um script R para instalação, onde criaremos um ambiente virtual e
instalaremos os pacotes, e outro com nossa análise real, onde
carregaremos o reticulate e ativaremos nosso ambiente virtual.
library(reticulate)
use_virtualenv("modern_data", required = TRUE)
Aprofundando-se
Já criamos um ambiente virtual, instalamos alguns pacotes nele,
reiniciamos o R e ativamos o ambiente virtual. Essas etapas são
abordadas nos scripts 0 - Setup.R e 1 - Activate.R. No restante desta
seção discutirei maneiras de passar informações entre R e Python, o que
resumi na Tabela 6.4.
Tabela 6.4: Interoperabilidade fornecida pelo reticulate
Arquivo Descrição
2 - Passing objects.Rmd Passa objetos entre R e Python em um documento R Markdown
3 - Using functions.Rmd Chama Python em um documento R Markdown
4 - Calling scripts.Rmd Chama Python usando como fonte um script Python
5 - Interactive mode.R Chama Python usando um console REPL Python
6 - Interactive document.Rmd Chama Python com entrada dinâmica em um documento interativo
iris = load_iris()
iris.data[:6]
```
# carrega os dados:
iris = datasets.load_iris()
# Treina o modelo chamando o método fit nos dados de destino, usando os nomes
de destino
clf.fit(iris.data, iris.target_names[iris.target])
clf = SVC()
clf.fit(iris.data, iris.target_names[iris.target])
```
Nos dois últimos blocos, podemos usar funções do pacote shiny para
produzir uma interface de usuário. Ela será composta tanto da entrada
quanto da saída.
Em primeiro lugar, a entrada. Produzimos um controle deslizante (slider)
para cada um dos quatro recursos usando a função sliderInput() como
mostrado a seguir para sl. Os controles deslizantes de sw, pl e pw são
semelhantes e podem ser encontrados no script do estudo de caso.
sliderInput("sl", label = "Sepal length:",
min = 4.3, max = 7.9, value = 4.5, step = 0.1)
Considerações nais
Neste capítulo, abordamos os componentes básicos do pacote reticulate,
progredindo da instalação essencial aos aspectos básicos e nalmente a
uma implementação simples, porém poderosa, que demonstrou os pontos
fortes do R, do Python e do reticulate. Usando esse conhecimento,
passaremos para um estudo de caso maior no último capítulo.
1 Lembre-se de que rhs é o right-hand side e lhs é o left-hand side na chamada de operadores, nesse
caso <.
2 Nessas tabelas estamos diferenciando funções e objetos. Lembre-se de que as funções são apenas
objetos, mas não precisamos nos preocupar com esses detalhes no momento.
3 Consulte o Apêndice para ver um resumo das estruturas de dados.
CAPÍTULO 7
Rick J. Scavetta
Boyan Angelov
Neste último capítulo, nosso objetivo é apresentar um estudo de caso que
forneça uma amostra de todos os conceitos e ferramentas que exibimos
no decorrer deste livro. Embora a ciência de dados ofereça uma enorme
diversidade de métodos e aplicações, normalmente usamos apenas um kit
de ferramentas básico em nosso trabalho diário. Logo, é improvável que
você venha a fazer uso de todas as ferramentas apresentadas no livro (ou
nesse estudo de caso). No entanto, isso não é problema! Esperamos que
você dê atenção às partes do estudo de caso que forem mais relevantes
para o seu trabalho e que se sinta inspirado a ser um cientista de dados
bilíngue e moderno.
dim(fires)
g
Mapeando OWNER_CODE na estética colorida (Figura 7.2), podemos ver a
forte correlação em alguns estados. Podemos prever que isso terá um
efeito signi cativo sobre o desempenho do nosso modelo.
Figura 7.2: Representando os tamanhos de incêndios individuais.
No fragmento de código anterior, atribuímos o diagrama ao objeto g. Isso
não é obrigatório, mas foi o que zemos nesse caso para demonstrar o
poder do método baseado em camadas do ggplot2. Podemos adicionar
uma camada facet_wrap() a esse diagrama e dividi-lo em 13 facetas, ou
pequenos múltiplos, uma para cada tipo de STAT_CAUSE_DESCR (Figura
7.3):
g +
facet_wrap(facets = vars(STAT_CAUSE_DESCR), nrow = 4)
Figura 7.3: Dividindo o diagrama de incêndios em facetas, baseadas na causa
do incêndio.
Isso nos permite saber que algumas causas são abundantes enquanto
outras são raras, uma observação que veremos novamente em breve de
maneira diferente. Também podemos começar a avaliar qualquer
associação mais forte entre, por exemplo, região, código do proprietário e
causa de um incêndio.
Voltando ao conjunto de dados em sua totalidade, uma maneira fácil de
obter uma visão geral abrangente seria usando um pairs plot (diagrama
de pares), às vezes chamado de splom (ou scatter plot matrix se for
composto puramente de dados numéricos). O pacote GGally fornece uma
excelente função, ggpairs(), que produz uma matriz de diagramas
(Figura 7.4).6 Cada diagrama bivariado em pares é mostrado como
diagramas de densidade univariada ou histogramas na diagonal. No
triângulo superior, a correlação entre características contínuas está
disponível:
library(GGally)
fires %>%
ggpairs()
leaflet() %>%
addTiles() %>%
addMarkers(lng = df$LONGITUDE, lat = df$LATITUDE,
clusterOptions = markerClusterOptions()
)
Machine Learning
Já temos alguma ideia dos fatores que podem in uenciar a causa de um
incêndio. Examinaremos a construção de um modelo de machine
learning com o uso do scikit-learn em Python.7
Achamos que é melhor executar o ML em Python como vimos no
Capítulo 5. Usaremos um algoritmo de oresta aleatória. Há várias razões
para essa escolha:
1. É um algoritmo estabelecido.
2. É relativamente fácil de entender.
3. Não requer escalonamento de características antes do treinamento.
Existem outras razões para acharmos o algoritmo bom, como por
trabalhar bem com dados ausentes e ter explicabilidade imediata.
Engenharia de características
Agora trataremos das características do conjunto de dados que podem ser
informativas para um analista de dados, mas que na melhor das hipóteses
serão inúteis para o treinamento do modelo, e na pior das hipóteses
podem reduzir sua precisão. Isso se chama adicionar ruído ao conjunto de
dados, e queremos evitar esse problema. Essa é a nalidade da engenharia
de características. Selecionaremos apenas as características das quais
precisamos, como especi cado na Tabela 7.1. Também usamos convenções
padrão do ML ao armazenar as características em X e o alvo em y:
features = ["OWNER_CODE", "DISCOVERY_DOY", "FIRE_SIZE", "LATITUDE",
"LONGITUDE"]
X = df[features]
y = df["STAT_CAUSE_DESCR"]
Treinamento do modelo
Para aplicar o classi cador de oresta aleatória, criaremos uma instância
de RandomForestClassifier. Como no Capítulo 5, usamos o paradigma
fit/predict e armazenamos os valores previstos em preds:
clf = RandomForestClassifier()
clf.fit(X_train, y_train)
preds = clf.predict(X_test)
Previsão e UI
Após o estabelecimento de um modelo Python, é prática geral testá-lo
com entradas ctícias. Isso nos permitirá veri car se nosso modelo pode
manipular os dados de entrada corretos e é prática padrão na engenharia
de características antes de conectá-lo a entradas reais do usuário. Para
fazer isso, criaremos cinco sliderInputs para as cinco características de
nosso modelo. Aqui, embutimos os valores mínimo e máximo em código
para simpli car, mas é claro que eles poderiam ser dinâmicos:
sliderInput("OWNER_CODE", "Owner code:",
min = 1, max = 15, value = 1)
sliderInput("DISCOVERY_DOY", "Day of the year:",
min = 1, max = 365, value = 36)
sliderInput("FIRE_SIZE", "Number of bins (log10):",
min = -4, max = 6, value = 1)
sliderInput("LATITUDE", "Latitude:",
min = 17.965571, max = 48.9992, value = 30)
sliderInput("LONGITUDE", "Longitude:",
min = -124.6615, max = -65.321389, value = 30)
clf$predict(r_to_py(input_df))
})
Considerações nais
Nesse estudo de caso, demonstramos como você pode aproveitar o
melhor de dois mundos e combinar as excelentes ferramentas que os
cientistas de dados modernos têm à sua disposição para criar experiências
de usuário notáveis, que encantem visualmente e baseiem a tomada de
decisões. Esse é um exemplo básico desse sistema elegante, e temos
certeza de que, ao mostrarmos o que é possível fazer, vocês – nossos
leitores – criarão os produtos de ciência de dados do futuro!
1 Short, Karen C. 2017. Spatial wild re occurrence data for the United States, 1992-2015,
FPA_FOD_20170508. 4th Edition. Fort Collins, CO: Forest Service Research Data Archive.
https://doi.org/10.2737/RDS-2013-0009.4.
2 Deixaremos o desenvolvimento completo de um modelo de classi cação robusto para os leitores
motivados. Na verdade, você também pode car interessado em uma regressão que preveja o
tamanho nal do incêndio em acres. Os leitores curiosos notarão que alguns notebooks
interessantes estão disponíveis no Kaggle para ajudá-los a começar.
3 Isso está longe de retratar o desenvolvimento, a hospedagem e a implantação de modelos de ML
robustos, o que, de qualquer forma, não é o objetivo deste livro.
4 Alguns leitores podem não estar familiarizados com essa linguagem. Normalmente ela é usada
para especi car opções de con guração como código, como nesse caso.
5 Essa parte também pode ser executada apropriadamente dentro do R com o uso de pacotes
como o dbplyr ou do painel Connections do RStudio.
6 Esse pacote é usado para estender a funcionalidade do ggplot2 para conjuntos de dados
transformados.
7 Essa não é uma exposição completa de todos os métodos ou otimizações possíveis, já que
estamos dando ênfase à construção de um uxo de trabalho bilíngue, e não explorando técnicas
de machine learning detalhadamente. Os leitores podem consultar a documentação o cial do
scikit-learn para ver uma orientação adicional, na seção habilmente chamada de “Choosing the
right estimator” (Escolhendo o estimador certo) (https://oreil.ly/yVysu).
APÊNDICE
O dicionário a seguir tem como objetivo ser usado como uma referência
rápida para a conversão de comandos entre Python e R. Visite o
repositório do livro (https://github.com/moderndatadesign/PyR4MDS) para
acessar outros recursos.
Correções e acréscimos são bem-vindos. Entre em contato com o Rick no
LinkedIn (https://linkedin.com/in/rick-scavetta/) ou faça um comentário no
repositório. Para acessar um resumo baixável, visite o site do livro
(https://moderndata.design).
Exceto por algumas expressões de linha de comando para inserção no
terminal, que contêm uma observação explícita, as expressões foram
fornecidas em R ou Python.
Gerenciamento de pacotes
Tabela A.1: Instalando um único pacote
Operadores de atribuição
Tabela A.5: Operadores de atribuição típicos em Ra
Operador Direção Ambiente Nome Comentário
<- RHS Atual Operador de atribuição Preferido; comum e não ambíguo
para (direcionado para a
LHS esquerda)
= RHS Atual Operador de atribuição Menos adequado; comum, mas é facilmente confundido com ==
para (direcionado para a (equivalência) e = (atribuição a argumento de função); sem
LHS esquerda) superatribuição como resultado
Operador Direção Ambiente Nome Comentário
-> LHS Atual Operador de atribuição Menos adequado; incomum, facilmente ignorado, e inesperado.
para (direcionado para a Geralmente usado no m de uma longa cadeia de funções do
RHS direita) dplyr/tidyverse; melhor usar %<%.
a
RHS signi ca right-hand side (lado direito) e LHS é left-hand side (lado esquerdo).
Tipos
Tabela A.10: Os quatro tipos de vetor atômico de nidos pelo usuário mais
comuns em R
Abreviação do data Abreviação do
Tipo Descrição Exemplo
frame tibble
Lógico logi <lgl> Dados binários TRUE/FALSE, T/F,
1/0
Integer int <int> Número inteiros de –∞, ∞ 7, 9, 2, –4
Double num <dbl> Números reais de –∞, ∞ 3.14, 2.78, 6.45
Caractere chr <chr> Todos os caracteres alfanuméricos, incluindo os "Apple", "Dog"
espaços em branco
Tabela A.11: Os quatro tipos de nidos pelo usuário mais comuns em Python
Tipo Abreviação Descrição Exemplo
Boolean bool Dados binários True/False
Integer int Números inteiros de –∞, ∞ 7, 9, 2, –4
Float float Número reais de –∞, ∞ 3.14, 2.78, 6.45
String str Todos os caracteres alfanuméricos, incluindo os espaços em branco "Apple", "Dog"
Operadores aritméticos
Tabela A.12: Operadores aritméticos comuns
Descrição Operador R Operador Python
Adição + +
Descrição Operador R Operador Python
Subtração – –
Multiplicação * *
Divisão ( oat) / /
Exponenciação ^ ou ** **
Divisão de inteiros (piso) %/% //
Módulo %% %
Atributos
Tabela A.13: Atributos de classe
Palavras-chave
Tabela A.14: Palavras reservadas e palavras-chave
Funções e métodos
Tabela A.15: De nindo funções nomeadas
# Definição básica # Definição simples
myFunc <- function (x, ...) { def my_func(x):
x * 10 return(x * 10)
}
my_func(4)
myFunc(4)
## 40
## [1] 40
# Múltiplos argumentos nomeados, passados como
# Múltiplos argumentos não uma tupla
nomeados def my_func(*x):
myFunc <- function (...) { return(x[2])
sum(...)
} my_func(100, 40, 60)
myFunc(100,40,60) ## 60
## x: 40
## y: 100
print("x: ",numb["x"])
print("y: ",numb["y"])
'Exemplo de função
que recebe múltiplos argumentos desconhecidos.'
Estilo e convenções de nomeação
Geralmente o estilo em R é de nido de maneira menos restrita do que em
Python. No entanto, consulte o Advanced R style guide
(https://oreil.ly/BOf3M), de Hadley Wickham (CRC Press), ou o guia de
estilo R do Google (https://oreil.ly/ZyXjb) para ver sugestões.
Para Python, consulte o guia de estilo PEP 8 (https://oreil.ly/UqWqs).
Tabela A.16: Estilo e convenções de nomeação em R e Python
Indentação e Nomeando
Indentação e espaçamento Nomeando um script
espaçamento um script
Geralmente o espaço em branco está Atualmente a tendência é O espaço em branco, principalmente a Tipo:
relacionado a estilo e não tem efeito sobre a usar snake case minúsculo: indentação, faz parte da execução em Funções e
execução. Adicione um espaço ao redor dos underscores (“_”) entre as Python. Use quatro espaços em vez de variáveis
operadores e use tabulação ou indentação em palavras e somente letras tabulação (isso pode ser de nido em Estilo: Snake
linhas sucessivas de comandos longos. minúsculas. Exemplo: seu editor de texto). case
my_data <- 1:6 minúsculo
Exemplo:
func,
my_func,
var,
my_var,
x
# Vetores # Listas
cities_R <- c("Munich", "Paris", cities = ['Munich', 'Paris',
"Amsterdam") 'Amsterdam']
dist_R <- c(584, 1054, 653) dist = [584, 1054, 653]
Tabela A.23: Pares chave-valor unidimensionais heterogêneos (listas em R,
dicionários em Python)
Data Frames
Tabela A.24: Data frames em Python
# classe pd.DataFrame
import pandas as pd
# De um dicionário, yy
yy_df = pd.DataFrame(yy)
yy_df
## city dist pop area country
## 0 Munich 584 1484226 310.43 DE
## 1 Paris 1054 2175601 105.40 FR
## 2 Amsterdam 653 1558755 219.32 NL
# De nomes
# de listas
list_names = ['city', 'dist', 'pop', 'area', 'country']
# zip_dict = dict(zip_list)
# zip_df = pd.DataFrame(zip_dict)
# zip_df
# zip_df = pd.DataFrame(zip_list)
# zip_df
## , , 1 ## array([[[ 1, 2],
## ## [ 3, 4]],
## [,1] [,2] ##
## [1,] 1 3 ## [[ 10, 20],
## [2,] 2 4 ## [ 30, 40]],
## ##
## , , 2 ## [[100, 200],
## ## [300, 400]]])
## [,1] [,2]
## [1,] 10 30 arr.sum(axis=0)
## [2,] 20 40
## ## array([[111, 222],
## , , 3 ## [333, 444]])
arr.sum(axis=1)
##
## [,1] [,2]
## array([[ 4, 6],
## [1,] 100 300
## [ 40, 60],
## [2,] 200 400
## [400, 600]])
rowSums(arr_r, dims = 2)
arr.sum(axis=2)
## [,1] [,2]
## array([[ 3, 7],
## [1,] 111 333
## [ 30, 70],
## [2,] 222 444
## [300, 700]])
rowSums(arr_r, dims = 1)
colSums(arr_r, dims = 1)
colSums(arr_r, dims = 2)
cities_df
Expressões lógicas
Tabela A.27: Operadores relacionais
Descrição Operador R Operador Python
Equivalência == ==
Não equivalência != !=
Maior que (ou igual a) > (>=) > (>=)
Menor que (ou igual a) < (<=) < (<=)
Negação !x not()
## [1] FALSE FALSE FALSE FALSE ## array([ True, False, False, False,
FALSE True])
TRUE FALSE FALSE FALSE FALSE
xx != 6
## [1] TRUE TRUE TRUE TRUE TRUE
FALSE TRUE TRUE TRUE TRUE
xx >= 6
xx < 6
## [0, 1, 2, 5]
## [3, 4]
## False
Indexação
Tabela A.32: Procurando objetos idênticos(a)
Dimensões Uso Descrição Dimensões Uso Descrição
1 x[index] Isola conteúdos, 1 x[index] Isola
mantém contêiner conteúdos,
mantém
contêiner
1 x[-index] Extrai um conteúdo, 1 x[-index] Isola
descarta contêiner conteúdos
na direção
inversa,
mantém
contêiner
1 x[[index]] Isola conteúdos, 1 x[index_1:index_2] Fatia
remove item,
mantém contêiner
2 x[row_index, Isola conteúdos, 1 x[index_1:index_2:stride] Fatia com
col_index] mantém contêiner um
intervalo
2 x[col_index] Atalho para colunas 1 x[index_1:index_2:-1] Fatia com
inversão
2 x[[index]] Extrai um conteúdo, 2 x.loc[index_1:index_2] Localização
descarta contêiner
n x[row_index, Isola conteúdos, 2 x.iloc[index_1: Índice
col_index, mantém contêiner index_2:stride]
dim_index]
(a)
Em que index, row_index, col_index e dim_index são vetores de tipo inteiro, de caracteres ou
lógico.
xx[[4]] ## 'Toronto'
## $Paris cities[1:2]
## dist pop area country
## 1 1054 2175601 105.4 FR ## ['Santiago']
cities[:2]
## ['Toronto', 'Santiago']
## dist
## 1 584
## 2 1054
## 3 653
cities_df[,2] # vetor
cities_df[[2]] # vetor
## dist pop
## 1 584 1484226
## 2 1054 2175601
## 3 653 1558755
cities_df[,2:3] # data frame
## dist pop
## 1 584 1484226
## 2 1054 2175601
## 3 653 1558755
## # Um tibble: 3 x 1
## dist
## <dbl>
## 1 584
## 2 1054
## 3 653
## # Um tibble: 3 x 1
## dist
## <dbl>
## 1 584
## 2 1054
## 3 653
cities_tbl[[2]] # vetor
## # Um tibble: 3 x 2
## dist pop
## <dbl> <dbl>
## 1 584 1484226
## 2 1054 2175601
## 3 653 1558755
## # Um tibble: 3 x 2
## dist pop
## <dbl> <dbl>
## 1 584 1484226
## 2 1054 2175601
## 3 653 1558755
df
df[1:]
# posição
df.iloc[0, 1]
## 584
df.iat[0, 1]
## 584
# Rótulo
df.loc[1:, 'city']
## 1 Paris
## 2 Amsterdam
## Name: city, dtype: object
data = {'Country': ['Belgium', 'India', 'Brazil'],
'Capital': ['Brussels', 'New Delhi', 'Brasilia'],
'Population': [11190846, 1303171035, 207847528]}
df_2
df[1:]
# df.iloc([0], [0])
cities_array[1,2,2] arr[1,:,1]
cities_array[1,2,] arr[1,1,:]
cities_array[,2,1]
## [1] 5 6 7 8
Sobre os autores