Introdução à programação em R
Upcoming SlideShare
Loading in...5
×
 

Introdução à programação em R

on

  • 1,771 views

Introdução à Programação em R, Luís Torgo, Universidade do Porto, 2006

Introdução à Programação em R, Luís Torgo, Universidade do Porto, 2006

Statistics

Views

Total Views
1,771
Views on SlideShare
834
Embed Views
937

Actions

Likes
1
Downloads
14
Comments
0

18 Embeds 937

http://mbarrosconsultoria.blogspot.com.br 798
http://mbarrosconsultoria.blogspot.com 46
http://feeds.feedburner.com 38
http://mbarrosconsultoria.blogspot.pt 28
http://mbarrosconsultoria.blogspot.ru 6
http://mbarrosconsultoria.blogspot.co.uk 4
http://mbarrosconsultoria.blogspot.fr 3
http://mbarrosconsultoria.blogspot.ro 2
http://www.mbarrosconsultoria.blogspot.com 2
http://mbarrosconsultoria.blogspot.mx 2
https://www.google.com.br 1
http://mbarrosconsultoria.blogspot.nl 1
http://conversation.ecairn.com 1
http://mbarrosconsultoria.blogspot.it 1
http://mbarrosconsultoria.blogspot.de 1
http://mbarrosconsultoria.blogspot.sg 1
http://mbarrosconsultoria.blogspot.jp 1
http://mbarrosconsultoria.blogspot.hu 1
More...

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Introdução à programação em R Introdução à programação em R Document Transcript

    • Faculdade de Economia Universidade do PortoIntrodu¸˜o ` Programa¸˜o em R ca a ca Lu´ Torgo ıs ltorgo@liacc.up.pt Grupo de Matem´tica e Inform´tica a a Outubro de 2006
    • © L. Torgo, 2006. A licence is granted for personal study and classroom use. Redistri-bution in any other form is prohibited.© ´ L. Torgo, 2006. E concedida licen¸a de utiliza¸˜o deste documento para uso pessoal c cae para ensino. A re-distribui¸ao em qualquer outro tipo de formato ´ proibida. c˜ e
    • Conte´ do u1 Introdu¸˜o ao Ambiente ca R 7 1.1 Instala¸˜o do R . . . . ca . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 1.2 Come¸ar a usar o R . c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 1.3 Ajuda sobre o R . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 1.4 “Packages” do R . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92 Fundamentos da Linguagem R 11 2.1 Os objectos do R . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 2.2 Vectores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 2.3 Opera¸˜es com Vectores . . . co . . . . . . . . . . . . . . . . . . . . . . . . . 14 2.4 Factores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 2.5 Sequˆncias . . . . . . . . . . . e . . . . . . . . . . . . . . . . . . . . . . . . . 18 2.6 Indexa¸˜o . . . . . . . . . . . ca . . . . . . . . . . . . . . . . . . . . . . . . . 20 2.7 Matrizes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 2.8 Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 2.9 Listas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 2.10 Data Frames . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 2.11 S´ries Temporais . . . . . . . e . . . . . . . . . . . . . . . . . . . . . . . . . 31 2.11.1 S´ries Regulares . . . e . . . . . . . . . . . . . . . . . . . . . . . . . 31 2.11.2 S´ries Irregulares . . . e . . . . . . . . . . . . . . . . . . . . . . . . . 363 Programa¸˜o em R ca 45 3.1 Interac¸˜o com o Utilizador . . . . . . . ca . . . . . . . . . . . . . . . . . . . 45 3.2 Estruturas de Controlo da Linguagem R . . . . . . . . . . . . . . . . . . . 46 3.2.1 Instru¸˜es Condicionais . . . . . co . . . . . . . . . . . . . . . . . . . 46 3.2.2 Instru¸˜es Iterativas . . . . . . . co . . . . . . . . . . . . . . . . . . . 48 3.2.3 Evitando ciclos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 3.3 Fun¸˜es . . . . . . . . . . . . . . . . . . co . . . . . . . . . . . . . . . . . . . 52 3.3.1 Criar fun¸˜es . . . . . . . . . . . co . . . . . . . . . . . . . . . . . . . 52 3.3.2 Ambientes e “scope” de vari´veis a . . . . . . . . . . . . . . . . . . . 53 3.3.3 Argumentos de fun¸˜es . . . . . co . . . . . . . . . . . . . . . . . . . 54 3.3.4 Lazy evaluation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 3.3.5 Algumas fun¸˜es uteis . . . . . . co ´ . . . . . . . . . . . . . . . . . . . 56 3.4 Objectos, Classes e M´todos . . . . . . . e . . . . . . . . . . . . . . . . . . . 58 3.5 Depura¸˜o de Programas em R . . . . . ca . . . . . . . . . . . . . . . . . . . 604 Manipula¸˜o de Dados ca 63 4.1 Carregar dados para o R . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63 4.1.1 De ficheiros de texto . . . . . . . . . . . . . . . . . . . . . . . . . . 63 4.1.2 Da Internet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 4.1.3 Do Excel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65 4.1.4 De bases de dados . . . . . . . . . . . . . . . . . . . . . . . . . . . 65 4.2 Sumariza¸˜o de dados . . . . . . . . . . . . . . . . ca . . . . . . . . . . . . . 67 4.3 F´rmulas . . . . . . . . . . . . . . . . . . . . . . . o . . . . . . . . . . . . . 70 4.4 Visualiza¸˜o de dados . . . . . . . . . . . . . . . . ca . . . . . . . . . . . . . 71 4.4.1 Gr´ficos Univariados . . . . . . . . . . . . . a . . . . . . . . . . . . . 73 4.4.2 Gr´ficos de 3 Vari´veis . . . . . . . . . . . . a a . . . . . . . . . . . . . 74 4.4.3 Gr´ficos Multivariados . . . . . . . . . . . . a . . . . . . . . . . . . . 78 4.4.4 Gr´ficos Condicionados . . . . . . . . . . . a . . . . . . . . . . . . . 81 4.4.5 Interac¸˜o com Gr´ficos . . . . . . . . . . . ca a . . . . . . . . . . . . . 83 4.4.6 Adicionar Informa¸˜o a Gr´ficos Existentes ca a . . . . . . . . . . . . . 84
    • 4.4.7 Parˆmetros de Gr´ficos . . . . . . . . . . . . . . . . . . . . . . . . a a 90 4.4.8 a a ´ Dividir a Janela de Gr´ficos em V´rias Areas . . . . . . . . . . . . 91Referˆncias e 95´Indice 97
    • Pref´cio aEste documento tem como objectivo principal fornecer uma introdu¸˜o ` programa¸˜o ca a causando a linguagem R. A escolha desta linguagem como ve´ ıculo para aprender a pro-gramar prende-se com os objectivos do curso em que esta disciplina se insere. Uma vezque este curso tem a an´lise de dados e o data mining como um dos assuntos centrais, ao R sendo tamb´m um ambiente de an´lise explorat´ria de dados, permite uma melhor e a oarticula¸˜o com outras disciplinas. ca A escolha do R tem ainda outros motivos relacionados com o facto de este ser umsoftware gratuito e de c´digo aberto. Estas caracter´ o ısticas, em conjunto com as suasreconhecidas qualidades, fazem dele uma ferramenta quase ideal para aprender a progra-mar dentro dum contexto de an´lise de dados e sistemas de apoio ` decis˜o. Ao usarem a a auma ferramenta deste g´nero como plataforma de implementa¸˜o dos conceitos apren- e cadidos, os alunos poder˜o facilmente, pelo seu car´cter gratuito, levar o que aprenderam a apara o cen´rio profissional em que se enquadram ou venham a enquadrar. Al´m disso, a eas suas caracter´ ısticas de c´digo aberto ir˜o facilitar a eventual necessidade de adaptar o aalgum dos muitos m´todos dispon´ e ıveis no R, para assim melhor os adequarem aos seusinteresses/objectivos.
    • 71 Introdu¸˜o ao Ambiente R caO R (R Development Core Team, 2006) ´ ao mesmo tempo uma linguagem de programa- e O que ´ o R? eca¸˜o e um ambiente para computa¸˜o estat´ ca ıstica e gr´ficos. Trata-se de uma linguagem de aprograma¸˜o especializada em computa¸˜o com dados. Uma das suas principais caracte- ca car´ ısticas ´ o seu car´cter gratuito e a sua disponibilidade para uma gama bastante variada e ade sistemas operativos. Neste documento iremos concentrar a nossa aten¸˜o na vers˜o ca aWindows, mas basicamente tudo o que aqui ´ descrito tamb´m se aplica `s outras vers˜es, e e a odadas as muito reduzidas diferen¸as entre as vers˜es para as diversas plataformas. c o Apesar do seu car´cter gratuito o R ´ uma ferramenta bastante poderosa com boas a ecapacidades ao n´ ıvel da programa¸˜o e um conjunto bastante vasto (e em constante cacrescimento) de packages que acrescentam bastantes potencialidades ` j´ poderosa vers˜o a a abase do R. O R ´ uma variante da linguagem S com a qual John Chambers (Chambers, 1998) eganhou o prestigiado pr´mio de software da organiza¸˜o ACM. e ca1.1 Instala¸˜o do R caEmbora o R esteja instalado no sistema inform´tico da FEP, dado o seu car´cter gra- a atuito, os alunos poder˜o instalar este software nos seus computadores em casa. Para isso anecessitar˜o simplesmente de ligar o computador ` Internet e seguir os passos que des- a acrevemos em seguida. Caso n˜o pretenda realizar a instala¸˜o do R no seu computador, a capoder´ avan¸ar para a pr´xima sec¸˜o. a c o ca Para instalar o R os alunos dever˜o come¸ar por ligar o seu computador ` Internet. a c aAp´s esta liga¸˜o dever´ ser feito o download do R a partir do site desta aplica¸˜o, o ca a ca Download do Rhttp://www.r-project.org. Neste site dever´ ser seguido o link com o nome CRAN ano menu dispon´ ` esquerda. Depois de escolher um dos muitos locais espalhados pelo ıvel amundo para fazer o download, dever´ seguir o link Windows (95 and later) dispon´ a ıvelna sec¸˜o Precompiled Binary Distributions. No ´cran seguinte, deve “entrar” na pasta ca ebase e fazer o download do ficheiro R-2.3.1-win32.exe1 . Uma vez efectuado o download do ficheiro mencionado acima, dever´ proceder-se ` a ainstala¸˜o do R , bastando para isso executar o ficheiro (carregando duas vezes em cima ca Instala¸˜o do R cadele no Explorer). De notar que em vers˜es mais recentes do Windows esta instala¸˜o o capoder´ ter de ser feita pelo utilizador Administrador, por quest˜es de permiss˜es. a o o1.2 Come¸ar a usar o R cPara se executar o R basta usar ou o ´ıcone que normalmente est´ dispon´ no desktop a ıvel Iniciar o Rdo Windows, ou ent˜o usar o respectivo item no menu “Start”2 . a A execu¸˜o do R faz aparecer a janela desta aplica¸˜o de que se pode ver um exemplo ca cana Figura 1. ` A parte os menus que iremos explorar mais tarde, esta janela apresenta o prompt a ´do R (> ), com o cursor ` sua frente. E aqui que vamos introduzir os comandos que O prompt do Rpretendemos que o R execute. Podemos come¸ar por ver um pequeno exemplo do tipo de cinterac¸˜o que vamos ter com o R, escrevendo o seguinte comando no prompt e carregando caem seguida na tecla Enter (esta ´ a forma de mandar o R executar o comando que e Executar comandosacabamos de escrever),> R.versionplatform i386-pc-mingw32arch i386os mingw32system i386, mingw32status 1 O nome do ficheiro poder´ variar em vers˜es posteriores do R. Na altura da escrita deste texto a a overs˜o do R dispon´ a ıvel era a 2.3.1 e da´ o nome do ficheiro. ı 2 Na FEP o R est´ dispon´ a ıvel seguindo o percurso de menus: Start->Programs->Aplications->R.
    • 8 1 ¸˜ INTRODUCAO AO AMBIENTE R Figura 1: O ambiente R. major 2 minor 3.1 year 2006 month 06 day 01 svn rev 38247 language R version.string Version 2.3.1 (2006-06-01) O comando R.version ao ser executado fez aparecer uma s´rie de informa¸˜o sobre e ca a vers˜o do R bem como sobre o computador onde o R est´ a ser executado. a aTerminar o R Para terminar a execu¸˜o do R basta executar o seguinte comando, ca > q() Ao executar este comando ir´ aparecer uma caixa de di´logo como a apresentada na a aContinuar o Figura 2. Se respondermos Yes a esta pergunta o R vai guardar a informa¸˜o contida na catrabalho mais tarde mem´ria do computador num ficheiro, de modo a que da pr´xima vez que executarmos o o o R no local onde esse ficheiro ´ guardado, ele vai permitir-nos continuar o nosso trabalho e exactamente de onde o estamos a abandonar ao executar o comando q(). A informa¸˜o ca guardada consiste basicamente na hist´ria de comandos que executamos nesta sess˜o que o a agora terminamos, bem como os objectos que criamos na nossa sess˜o. O resultado ser´ a a que o R vai criar 2 ficheiros: um chamado .Rhistory contendo a lista dos comandos que executamos, e outro chamado .RData contendo os objectos criados na sess˜o. Gravar a a sess˜o s´ ter´ interesse se de facto pretendermos continuar o que est´vamos a fazer mais a o a a tarde. Na maior parte das vezes vamos escolher a op¸˜o No que ir´ abandonar o R sem ca a guardar o estado em que est´vamos. Os ficheiros com o estado da sess˜o s˜o sempre a a a gravados no direct´rio actual onde o R est´ a funcionar. Para saber o direct´rio actual o a o do R basta fazer no prompt, > getwd() Em resposta a este comando o R ir´ apresentar no ´cran o direct´rio actual. Para o a e oAlterar o direct´rio o alterar poder-se-´ ou usar a op¸˜o Change dir... do menu File, ou ent˜o usar a fun¸˜o a ca a caactual setwd() conforme ilustrado no exemplo seguinte, > setwd(U:My DocumentsAulasR) Note a utiliza¸˜o de dois caracteres , em vez do unico caracter como ´ costume em ca ´ e ambientes Windows3 . 3 Acrescente-se a t´ ıtulo de curiosidade que poder´ ser usado em vez destes dois caracteres um unico a ´ caracter “/”.
    • 1.3 Ajuda sobre o R 9 Figura 2: Abandonar o R.1.3 Ajuda sobre o RO R tem um sistema de ajuda bastante elaborado que lhe permitir´ obter muita informa- aca¸˜o extra sobre a linguagem, bem como muitos outros aspectos que lhe est˜o associados. a Obter ajuda no R Nas vers˜es Windows do R, a forma mais f´cil de obter ajuda ´ atrav´s da utiliza¸˜o o a e e cado menu Help dispon´ ıvel na janela da aplica¸˜o R. Atrav´s deste menu ´ poss´ ca e e ıvel porexemplo, escolher a op¸˜o Html help o que far´ lan¸ar um browser onde poder´ tirar ca a c apartido de uma s´rie de manuais e outros tipo de ajuda dispon´ e ıveis no R. No entanto, se pretende simplesmente obter ajuda sobre uma fun¸˜o em particular cado R, a forma mais simples ser´ provavelmente usar a fun¸˜o help(), a ca> help(sqrt) Este comando ir´ fazer aparecer uma pequena janela com todo um conjunto de infor- ama¸˜es uteis sobre a fun¸˜o escolhida, que vai da simples descri¸˜o dos seus argumentos co ´ ca caat´ exemplos de utiliza¸˜o, bem como fun¸˜es relacionadas. Em alternativa, poder´ e ca co aintroduzir antes “? sqrt”, produzindo exactamente o mesmo efeito. Quando n˜o sabemos o nome concreto da fun¸˜o sobre a qual preciamos de ajuda, a capodemos usar como alternativas as fun¸oes apropos() e help.search(). Genericamente, c˜ambas produzem uma lista das fun¸˜es do R que contˆm referˆncias ao texto que incluimos co e ecomo argumento destas fun¸˜es. Experimente por exemplo fazer, apropos(’model’), ou cohelp.search(’model’). Para d´vidas mais complexas poder´ ainda consultar a muita documenta¸˜o gratuita u a cadispon´ ıvel no site do R (www.r-project.org), ou a mailing list de apoio dispon´ ıvel nomesmo site. Se optar por esta ultima alternativa recomenda-se que antes de colocar ´qualquer pergunta fa¸a uma procura pelos arquivos da lista para evitar colocar quest˜es c oj´ respondidas, o que nem sempre ´ bem recebido pelas pessoas que se voluntariam para a eajudar. Finalmente uma alternativa poderosa que junta v´rias destas formas de ajuda do R a´ utilizar no R a fun¸˜o RSiteSearch(). Esta fun¸˜o faz lan¸ar um browser que ir´e ca ca c amostrar o resultado da procura da “string” que passar como argumento ` fun¸˜o. O a caresultado da procura envolve toda a ajuda de todas as fun¸˜es do R, ajuda nas mailing colists, bem como em outros documentos. Por exemplo, se pretendo saber o que existenestes locais sobre redes neuronais, poderia fazer a seguinte procura,> RSiteSearch(neural networks)1.4 “Packages” do RUma instala¸˜o do R vem j´ com um conjunto de packages instaladas. Estas packages n˜o ca a as˜o mais do que agrega¸˜es de fun¸˜es que foram criadas por algu´m que as disponibilizou a co co ea` comunidade de forma gratu´ Qualquer pessoa pode criar as suas packages e submetˆ- ıta. elas ao portal do R para que sejam consideradas na lista de packages dispon´ ıveis a´ı.Quando se executa o R s´ algumas fun¸˜es est˜o dispon´ o co a ıveis de imediato. Essas s˜oaas fun¸˜es inclu´ co ıdas nas packages que foram julgadas mais importantes ou de uso maiscomum e que s˜o automaticamente carregadas quando se executa o R. Em qualquer aaltura poderemos “carregar” uma package que contenha fun¸˜es extra que necessitemos copara o nosso trabalho. Para tal ser poss´ ıvel a package dever´ estar instalada no nosso acomputador. Se tal n˜o fˆr o caso teremos que fazer o download da mesma e instal´-la. a o aEste processo ´ simples, desde que o seu computador esteja ligado ` Internet. e a
    • 10 1 ¸˜ INTRODUCAO AO AMBIENTE R Para instalar uma nova package podemos usar a fun¸˜o install.packages(), que ca Instalar novas leva como argumento o nome da package a instalar4 . Depois de indicado um reposit´rio o packages de onde fazer o download da package o R ir´ encarregar-se de todo o processo, inclusiv´ a e da sua instala¸˜o no seu computador. caUsar packages Para utilizar packages que estejam dispon´ ıveis no seu sistema basta usar a fun¸˜o ca library(), por exemplo, library(rpart) Esta instru¸˜o faz com que a partir de agora passem a estar dispon´ ca ıveis para utiliza¸˜o, ca todos os objectos (fun¸˜es, dados, etc.) definidos nessa package. Cada package instalada co tem uma ajuda espec´ ıfica que pode ser obtida no sistema de ajuda HTML do R que foi descrito na Sec¸˜o 1.3. ca 4 Na realidade podemos instalar v´rias indicando um vector (c.f. Sec¸˜o 2.2) com nomes de packages. a ca
    • 112 Fundamentos da Linguagem R2.1 Os objectos do RO R ´ uma linguagem baseada em objectos. Isto quer dizer que tudo o que n´s vamos e ousar no R est´ guardado na mem´ria do computador sob a forma de um objecto. Todos a oos objectos em R tˆm um nome associado e podem armazenar diferentes tipos de coisas e Objectos do R(n´meros, texto, vectores, matrizes, express˜es, chamadas a fun¸˜es, etc.). u o co Para armazenar algo num objecto usamos o operador de atribui¸˜o. Este operador ca Operador deconsiste num sinal < seguido por um sinal -, como se vˆ no exemplo apresentado em se- e atribui¸˜o caguida, em que guardamos o n´mero 4.5 no objecto que resolvemos chamar taxa.de.juro, u> taxa.de.juro <- 4.5 Para ver o conte´do de um objecto (o que est´ guardado na mem´ria sob um deter- u a o Ver o conte´ do de uminado nome) basta digitar o nome do objecto no prompt do R, carregando em seguida um objectoem Enter. Como resposta o R mostra-nos o conte´do do objecto que lhe indicamos. uPor exemplo, suponhamos que queremos confirmar o conte´do do objecto taxa.de.juro, u> taxa.de.juro[1] 4.5 O estranho [1] que aparece antes do n´mero guardado em taxa.de.juro, tem o usignificado “esta linha est´ a mostrar o conte´do de taxa.de.juro a come¸ar no elemento a u cnº 1 do objecto”. O significado disto tornar-se-´ mais ´bvio quando virmos objectos que a opodem armazenar mais do que um elemento, como por exemplo um vector contendo 100n´meros. u A opera¸˜o de atribui¸˜o ´ destrutiva no sentido que ao atribuir um novo valor a um ca ca eobjecto j´ existente, vamos perder o conte´do que ele estava a armazenar anteriormente. a u> taxa.de.juro <- 3.9> taxa.de.juro[1] 3.9 Tamb´m podemos atribuir express˜es num´ricas a objectos. O resultado de tal ope- e o e Express˜es ora¸˜o ´ o de que o resultado do c´lculo da express˜o ´ colocado no objecto, e n˜o a ca e a a e a num´ricas eexpress˜o propriamente dita, a> z <- 5> w <- z^2> w[1] 25> i <- (z * 2 + 45)/2> i[1] 27.5 Sempre que pretendemos atribuir o resultado de uma express˜o a um objecto e em aseguida ver o seu conte´do (como nos exemplos acima), podemos em alternativa usar a useguinte sintaxe que nos poupa algum tempo,> (w <- z^2)[1] 25
    • 12 2 FUNDAMENTOS DA LINGUAGEM R Na realidade n˜o ´ necess´rio atribuir o resultado das express˜es a objectos. Isto s´ a e a o o far´ sentido se pretendermos usar o resultado do c´lculo mais tarde, por exemplo noutra a a express˜o. Se pretendermos saber simplesmente o resultado do c´lculo, podemos usar o a a R como uma esp´cie de calculadora, e O R como uma calculadora > (34 + 90)/12.5 [1] 9.92 Sempre que criamos um novo objecto usando a instru¸˜o de atribui¸˜o, ele ir´ ficar na ca ca a mem´ria do computador. Como esta ´ limitada, poderemos apagar os objectos sempre o eListar os objectos que n˜o precisarmos mais deles. Podemos ver quais os objectos actualmente na mem´ria a oem mem´ria o do computador usando as fun¸˜es ls() ou objects(). Se j´ n˜o necessitamos de algum co a a dos objectos podemos ent˜o apag´-lo com a fun¸˜o rm() como nos exemplos apresentados a a ca em seguida, > ls() [1] "i" "taxa.de.juro" "w" "z" > rm(taxa.de.juro) > rm(z, w) > objects() [1] "i"Nomes v´lidos a O nome dos objectos pode ser formado por qualquer letra mai´scula ou min´scula, u u os d´ ıgitos 0 a 9 (excepto no in´ do nome), e tamb´m o ponto final “.”. Os nomes dos ıcio e objectos em R s˜o sens´ a ıveis `s letras mai´sculas / min´sculas. Isto quer dizer que Cor a u u e cor s˜o dois objectos diferentes para o R. Note tamb´m que n˜o pode usar espa¸os a e a c nos nomes dos objectos. Por exemplo, se pretende ter um objecto que guarda uma determinada taxa de cˆmbio, poderia sentir-se tentado(a) a escolher o nome taxa de a cˆmbio para o objecto, o que iria gerar um erro do R, a > taxa de c^mbio <- 0.05 a Error: syntax error Em alternativa poderia usar o seguinte nome que j´ seria v´lido, a a > taxa.de.c^mbio <- 0.05 a 2.2 VectoresO que ´ um vector e O objecto mais b´sico do R para guardar dados ´ o vector. Um vector ´ uma estrutura a e e de dados que permite armazenar um conjunto de valores do mesmo tipo (por exemplo n´meros) sob um mesmo nome. Esses elementos podem depois ser acedidos individu- u almente usando um esquema de indexa¸˜o que iremos descrever mais ` frente. Este ca a tipo de estrutura de dados ´ bastante util quando pretendemos armazenar v´rias coisas e ´ a relacionadas na mem´ria do computador. Por exemplo, suponhamos que pretendemos o guardar os lucros obtidos pela nossa empresa ao longo dos 12 meses do ano anterior. Em vez de termos 12 objectos diferentes, cada um guardando o lucro em cada mˆs, uma e vez que s˜o n´meros relacionados uns com os outros, faz mais sentido guard´-los todos a u a numa mesma estrutura de dados, que neste caso ser´ um vector com 12 n´meros. Em R, a u mesmo quando atribu´ ımos um unico n´mero a um objecto (por exemplo fazendo x <- ´ u 45), estamos de facto a criar um vector de n´meros com um unico elemento. u ´Modo e tamanho Todos os vectores em R tˆm um modo e um tamanho. O modo determina o tipo de edos vectores valores guardado no vector. Em R podemos ter vectores com modo character, logical, numeric e complex. Ou seja, podemos ter vectores para armazenar os seguintes tipos de dados at´micos: conjuntos de caracteres, valores l´gicos (F ou T ou FALSE ou o o
    • 2.2 Vectores 13TRUE)5 , n´meros inteiros ou reais, e n´meros complexos. O tamanho de um vector ´ u u eo n´mero de elementos que ele cont´m, e pode ser obtido com a fun¸˜o length(). u e ca Na maioria das situa¸˜es vamos criar vectores com mais do que um elemento. Para co Criar vectoresisso precisamos de usar a fun¸˜o c() para indicar ao R os elementos que formam o vector caseparando-os por v´ırgulas,> v <- c(4, 7, 23.5, 76.2, 80)> v[1] 4.0 7.0 23.5 76.2 80.0> length(v)[1] 5> mode(v)[1] "numeric" Todos os elementos de um vector tˆm que ser do mesmo tipo (modo). Caso tentemos ecriar um vector com elementos de tipo diferente o R vai for¸´-los a ser do mesmo tipo, ca Coer¸˜o de tipos caalterando-os. Vejamos um exemplo disso,> v <- c(4, 7, 23.5, 76.2, 80, "rrt")> v[1] "4" "7" "23.5" "76.2" "80" "rrt" Porque um dos elementos do vector era do tipo caracter, o R passou todos os outros(que eram n´meros) para o tipo caracter, gerando assim um vector de conjuntos de ucaracteres (strings). Isto quer dizer que por exemplo o primeiro elemento desse vector ´ ea string “4” e n˜o o n´mero 4, o que tem como consequˆncia, por exemplo, n˜o podermos a u e ausar este elemento numa express˜o num´rica. a e As strings em R s˜o conjuntos de caracteres englobados por aspas ou plicas, a> w <- c("rrt", "ola", "isto e uma string")> w[1] "rrt" "ola" "isto e uma string" Todos os vectores podem ter um elemento especial que ´ o NA. Este valor representa e Valoresum valor desconhecido. Por exemplo, se temos os lucros trimestrais de uma empresa desconhecidosguardados num vector, mas por alguma raz˜o desconhecemos o seu valor no terceiro atrimestre, poder´ ıamos usar a seguinte instru¸˜o para criar esse vector, ca> lucros <- c(234000, 245000, NA, 124500)> lucros[1] 234000 245000 NA 124500 Como j´ foi mencionado anteriormente, os elementos de um vector podem ser acedidos aatrav´s de um ´ e ındice. Na sua forma mais simples este ´ ındice ´ um n´mero indicando o e u Aceder a umelemento que pretendemos aceder. Esse n´mero ´ colocado entre parˆntesis rectos a u e e elementoseguir ao nome do vector,> lucros[2][1] 245000
    • 14 2 FUNDAMENTOS DA LINGUAGEM R Usando esta forma de aceder aos elementos individuais de um vector podemos alterar Alterar um elemen o conte´do de um elemento particular de um vector, u > lucros[3] <- 45000 > lucros [1] 234000 245000 45000 124500Vectores vazios O R permite-nos criar vectores vazios usando a fun¸˜o vector(), ca > k <- vector()Alterar tamanho de O tamanho de um vector j´ existente pode ser alterado atribuindo mais elementos a aum vector ´ ındices at´ agora inexistentes, e > k[3] <- 45 > k [1] NA NA 45 Repare que os dois primeiros elementos do vector k, que anteriormente era um vector vazio, ficaram com o valor NA ao colocarmos o valor 45 no terceiro elemento. Para diminuirmos o tamanho de um vector podemos usar a instru¸˜o de atribui¸˜o. ca ca Por exemplo, > v <- c(45, 243, 78, 343, 445, 645, 2, 44, 56, 77) > v [1] 45 243 78 343 445 645 2 44 56 77 > v <- c(v[5], v[7]) > v [1] 445 2 Atrav´s do uso de formas de indexa¸˜o mais poderosas que iremos explorar na Sec- e ca c˜o 2.6 vamos conseguir eliminar mais facilmente elementos particulares de um vector. ¸a 2.3 Opera¸oes com Vectores c˜ Um dos aspectos mais poderosos da linguagem R ´ a possibilidade de “vectorizar” a eOpera¸˜es com co maioria das suas fun¸˜es. Isto quer dizer que a maioria das fun¸˜es dispon´ co co ıveis no R ,vectores ao serem aplicadas a um vector, produzem como resultado um vector de resultados, que ´ obtido aplicando a fun¸˜o a cada um dos elementos do vector. Vejamos um exemplo e ca com a fun¸˜o sqrt() que serve para calcular ra´ ca ızes quadradas, > v <- c(4, 7, 23.5, 76.2, 80) > x <- sqrt(v) > x [1] 2.000000 2.645751 4.847680 8.729261 8.944272 Ao atribuir a x o resultado da aplica¸˜o da fun¸˜o ao vector v, estamos de facto a ca ca criar um vector com as ra´ ızes quadradas dos n´meros contidos em v. u Esta caracter´ ıstica do R pode ser usada para levar a cabo opera¸˜es aritm´ticas en- co e volvendo vectores, > v1 <- c(4, 6, 87) > v2 <- c(34, 32.4, 12) > v1 + v2
    • 2.4 Factores 15 [1] 38.0 38.4 99.0 O que acontece se tentamos realizar opera¸˜es envolvendo vectores de tamanho dife- cogra da reciclagem rente? O R vai usar um regra de reciclagem dos valores do vector mais curto at´ este e atingir o tamanho do maior. Por exemplo, > v1 <- c(4, 6, 8, 24) > v2 <- c(10, 2) > v1 + v2 [1] 14 8 18 26 ´ E como se o vector c(10,2) fosse de facto c(10,2,10,2). Se os tamanhos n˜o s˜o a a m´ltiplos um do outro, o R imprime um aviso no ´cran, u e > v1 <- c(4, 6, 8, 24) > v2 <- c(10, 2, 4) > v1 + v2 [1] 14 8 12 34 Repare-se que um aviso n˜o ´ um erro, o que quer dizer que a opera¸˜o foi levada a a e ca cabo. Como foi mencionado anteriormente, um n´mero ´ de facto armazenado em R como u e um vector de tamanho 1. Isto d´ bastante jeito para opera¸˜es como a seguinte, a co > v1 <- c(4, 6, 8, 24) > 2 * v1 [1] 8 12 16 48 Repare que o n´mero 2 (de facto o vector c(2)!) foi reciclado at´ atingir o tamanho u e do vector v1, tendo como resultado a multiplica¸˜o dos elementos todos deste vector ca por 2. Como veremos mais tarde esta regra de reciclagem tamb´m se aplica a outros e objectos, como por exemplo matrizes. 2.4 Factores Os factores proporcionam uma forma f´cil e compacta de lidar com dados categ´ricos a o (ou nominais). Este tipo de dados podem ser vistos como vari´veis que podem tomar a Vari´veis nominais a como valores poss´ ıveis um conjunto finito de etiquetas (por exemplo uma vari´vel que a (factores) armazene o estado civil de uma pessoa). Os factores tˆm associados a eles um conjunto e de n´ıveis que s˜o os valores poss´ a ıveis que podem tomar. Como veremos mais tarde v´rias a fun¸˜es do R (por exemplo fun¸˜es ligadas ` visualiza¸˜o de dados) tiram partido do co co a ca facto de guardarmos informa¸˜o categ´rica como factores em vez de usarmos strings. ca o Vejamos como criar factores em R. Suponhamos que pretendemos guardar o sexo de Criar factores 10 indiv´ıduos num vector, > s <- c("f", "m", "m", "m", "f", "m", "f", "m", "f", "f") > s [1] "f" "m" "m" "m" "f" "m" "f" "m" "f" "f" Ao transformarmos um vector de caracteres num factor, o R vai dar-nos a possibilidade de fazer coisas como por exemplo contar quantas vezes ocorre cada valor desse factor. Podemos transformar um vector de caracteres num factor da seguinte forma, 5 Como o R ´ sens´ e ıvel `s letras mai´sculas / min´sculas, True, por exemplo, n˜o ´ um valor l´gico a u u a e o v´lido. a
    • 16 2 FUNDAMENTOS DA LINGUAGEM R > s <- factor(s) > s [1] f m m m f m f m f f Levels: f m Repare que s deixou de ser um vector de caracteres6 . Neste pequeno exemplo, o nosso factor tem dois n´ıveis, ’f’ e ’m’. Suponha agora que temos 4 novos indiv´ ıduos cujo sexo tamb´m pretendemos armaze- e nar. Imagine que por coincidˆncia todos pertencem ao sexo masculino. Se pretendemos e que o factor resultante mantenha os 2 n´ ıveis poss´ ıveis para o sexo de um indiv´ ıduo teremos que fazer, > outro.s <- factor(c("m", "m", "m", "m"), levels = c("f", "m")) > outro.s [1] m m m m Levels: f m Sem o parˆmetro extra, indicando os n´ a ıveis a usar, a fun¸˜o factor() iria dar origem ca a um factor com um unico n´ (’m’), uma vez que este ´ o unico valor que ocorre no ´ ıvel e ´ vector de caracteres que estamos a transformar num factor. Conforme mencionado anteriormente, uma das vantagens de transformar um vector de caracteres num factor, ´ a possibilidade de usar fun¸˜es espec´ e co ıficas para lidar comContar ocorrˆncias e factores. Uma dessas fun¸˜es permite-nos contar o n´mero de ocorrˆncias de cada valor co u e (n´ ıvel), > table(s) s f m 5 5 > table(outro.s) outro.s f m 0 4Tabula¸˜es cruzadas co A fun¸˜o table() tamb´m pode ser usada para fazer tabula¸˜es cruzadas de dois ca e co factores, desde que estes tenham o mesmo tamanho. Imaginemos que temos um outro vector com a gama de idades dos indiv´ ıduos cujo sexo est´ armazenado em s. Podemos a fazer uma tabula¸˜o cruzada da idade e do sexo dos 10 indiv´ ca ıduos, da seguinte forma, > idade <- factor(c("adulto", "adulto", "jovem", "jovem", "adulto", + "adulto", "adulto", "jovem", "adulto", "jovem")) > s [1] f m m m f m f m f f Levels: f m > idade [1] adulto adulto jovem jovem adulto adulto adulto jovem adulto jovem Levels: adulto jovem > table(idade, s) 6 De facto, s ´ um tipo especial de vector de n´ meros, uma vez que internamente, o R guarda os factores e u como vectores de n´meros, com tantos valores quantos os n´ u ıveis do factor. Isto pode ser confirmado fazendo mode(s).
    • 2.4 Factores 17 sidade f m adulto 4 2 jovem 1 3 Isto quer dizer que existem 4 indiv´ ıduos que s˜o adultos do sexo feminino, 2 que s˜o a ahomens adultos, etc. Repare como introduzimos a primeira instru¸˜o. Como era muito grande, mudamos cade linha. Uma vez que o R descobre que a instru¸˜o ainda n˜o est´ terminada, apresenta ca a a Comandosa linha seguinte com o prompt de continua¸˜o, que ´ um sinal mais (+). ca e espalhados por Tamb´m ´ poss´ obter facilmente frequˆncias marginais e relativas. Por exemplo, e e ıvel e v´rias linhas apara saber o n´mero total de adultos e jovens far´ u ıamos, Frequˆncias e marginais e relativas> tabela.cruzada <- table(idade, s)> margin.table(tabela.cruzada, 1)idadeadulto jovem 6 4 Para obter a mesma informa¸˜o relativamente ao sexo dos indiv´ ca ıduos, bastaria mudaro n´mero 1, que indica que pretendemos os totais por linha (a primeira dimens˜o do u aobjecto) da tabela cruzada, para um 2, para obtermos os totais por coluna da tabelacruzada,> margin.table(tabela.cruzada, 2)sf m5 5 Relativamente a frequˆncias relativas, podemos usar a fun¸˜o prop.table(), de cujo e causo apresentamos alguns exemplos,> prop.table(tabela.cruzada, 1) sidade f m adulto 0.6666667 0.3333333 jovem 0.2500000 0.7500000> prop.table(tabela.cruzada, 2) sidade f m adulto 0.8 0.4 jovem 0.2 0.6> prop.table(tabela.cruzada) sidade f m adulto 0.4 0.2 jovem 0.1 0.3 No primeiro exemplo, as propor¸˜es s˜o calculadas em rela¸˜o ao total por linha. co a caAssim, o n´mero 0.6666667 ´ o resultado de dividir 4 (o n´mero de adultos femininos), u e upor 6 (o n´mero total de adultos). No segundo exemplo, as propor¸˜es s˜o relativamente u co aaos totais por coluna, enquanto que no terceiro exemplo s˜o relativas ao n´mero total a ude indiv´ıduos (isto ´, ficamos a saber que o n´mero de adultos masculinos representa e u20% do total dos indiv´ ıduos). Caso pretendˆssemos, obter os n´mero em percentagem, e upoder´ıamos simplesmente multiplicar as chamadas `s fun¸˜es pelo n´mero 1007 , a co u 7 Refira-se a t´ ıtulo de curiosidade que isto ´ mais um exemplo da regra de reciclagem. e
    • 18 2 FUNDAMENTOS DA LINGUAGEM R > 100 * prop.table(tabela.cruzada) s idade f m adulto 40 20 jovem 10 30 2.5 Sequˆncias eGerar sequˆncias de e Podem-se gerar sequˆncias em R de v´rias formas. Por exemplo, imaginemos que pre- e ainteiros tendemos criar um vector com os n´mero de 1 a 1000. Em vez de os escrevermos todos, u podemos usar, > x <- 1:1000 o que cria um vector com os n´mero inteiros de 1 a 1000. u Devemos ter algum cuidado com a precedˆncia do operador “:”, que ´ usado para e e gerar sequˆncias, em rela¸˜o aos operadores aritm´ticos. O exemplo seguinte ilustra os e ca e perigos que corremos, > 10:15 - 1 [1] 9 10 11 12 13 14 > 10:(15 - 1) [1] 10 11 12 13 14 Repare o que aconteceu no primeiro exemplo. Devido ao operador “:” ter maior precedˆncia do que o “-”, o R gerou um vector com os n´meros de 10 a 15 e depois e u subtraiu a esse vector o n´mero 1. Devido ` regra da reciclagem isto correspondeu a u a subtrair 1 a todos os elementos do vector, levando ao resultado que vemos acima. J´ no a segundo exemplo, usamos os parˆntesis para indicar ao R que o que pretendemos ´ um e e vector contendo os n´meros desde 10 at´ ao resultado da opera¸˜o 15-1, i.e. 14. u e caSequˆncias e O operador “:” tamb´m pode ser usado para gerar sequˆncias descendentes, e edescendentes > 5:0 [1] 5 4 3 2 1 0Sequˆncias de reais e Para gerar sequˆncias com n´meros reais podemos usar a fun¸˜o seq(), e u ca > seq(-4, 1, 0.5) [1] -4.0 -3.5 -3.0 -2.5 -2.0 -1.5 -1.0 -0.5 0.0 0.5 1.0 No exemplo acima geramos uma sequˆncia formada pelos n´meros a come¸ar em e u c -4 at´ 1 de 0.5 em 0.5. Esta fun¸˜o tem v´rias outras possibilidades para explicitar e ca a a sequˆncia que pretendemos. Alguns exemplos s˜o dados a baixo. Poder´ tamb´m e a a e explorar as potencialidades de ajuda do R, digitando o comando ? seq que mostra o help relativamente ` fun¸˜o seq. a ca > seq(from = 1, to = 5, length = 4) [1] 1.000000 2.333333 3.666667 5.000000 > seq(from = 1, to = 5, length = 2) [1] 1 5 > seq(length = 10, from = -2, by = 0.2)
    • 2.5 Sequˆncias e 19 [1] -2.0 -1.8 -1.6 -1.4 -1.2 -1.0 -0.8 -0.6 -0.4 -0.2 Repare que existe uma diferen¸a subtil na forma como usamos as fun¸˜o seq() nos c ca exemplos acima. De facto, em vez de indicarmos os valores dos argumentos da fun-omes dos ca ¸˜o (como por exemplo em seq(-4,1,0.5), indicamos o nome dos argumentos seguidogumentos de um sinal igual e o valor com o qual pretendemos chamar a fun¸˜o. As duas for- ca mas s˜o equivalentes, no entanto a chamada por nome tem vantagens de legibilidade a e tamb´m quando a fun¸˜o tem muitos argumentos permite-nos desrespeitar a sua or- e ca dem, ou seja, relativamente aos exemplos anteriores obter´ ıamos o mesmo resultado com seq(length=4,from=1,to=5). Iremos analisar com mais detalhe esta quest˜o quando a estudarmos o uso e cria¸˜o de fun¸˜es em R na Sec¸˜o 3.3.1. ca co ca Uma outra fun¸˜o bastante util para gerar sequˆncias ´ a fun¸˜o rep(), ca ´ e e ca Sequˆncias repetidas e > rep(5, 10) [1] 5 5 5 5 5 5 5 5 5 5 > rep("sim", 3) [1] "sim" "sim" "sim" > rep(1:3, 2) [1] 1 2 3 1 2 3 A fun¸˜o gl() pode ser usada para gerar sequˆncias envolvendo factores. A sintaxe ca e Sequˆncias com e desta fun¸˜o ´ gl(k,n), em que k ´ o n´mero de n´ ca e e u ıveis do factor e n o n´mero de u factores repeti¸˜es de cada n´ co ıvel. Vejamos dois exemplos, > gl(3, 5) [1] 1 1 1 1 1 2 2 2 2 2 3 3 3 3 3 Levels: 1 2 3 > gl(2, 5, labels = c("nao", "sim")) [1] nao nao nao nao nao sim sim sim sim sim Levels: nao sim Finalmente, o R tem uma s´rie de fun¸˜es para gerar sequˆncias aleat´rias de acordo Sequˆncias e co e o e com uma s´rie de fun¸˜es de distribui¸˜o de probabilidade. Essas fun¸˜es tˆm a forma ge- aleat´rias e co ca co e o n´rica rfunc(n, par1, par2, ...), em que n ´ o n´mero de dados a gerar, e par1, par2, ... e e u s˜o valores de alguns parˆmetros que a fun¸˜o espec´ a a ca ıfica a ser usada possa precisar. Por exemplo, se pretendemos 10 n´meros gerados aleatoriamente de acordo com uma distri- u bui¸˜o normal de m´dia 0 e desvio padr˜o unit´rio, podemos fazer, ca e a a > rnorm(10) [1] 0.6068968 1.2468432 1.8680112 1.3694861 -2.7365075 -0.8887380 [7] 0.2129164 0.8129556 -0.1786157 0.7735804 Se preferirmos 10 n´meros provenientes de uma distribui¸˜o normal com m´dia 10 e u ca e desvio padr˜o 3, far´ a ıamos > rnorm(10, mean = 10, sd = 3) [1] 11.224101 12.993983 9.577280 8.083312 7.553354 13.085718 8.347373 [8] 8.388759 11.020737 4.095438 De igual modo para obter 5 n´meros obtidos de forma aleat´ria de uma distribui¸˜o u o ca t de Student com 10 graus de liberdade, fazemos
    • 20 2 FUNDAMENTOS DA LINGUAGEM R > rt(5, df = 10) [1] 1.1357666 -2.7568824 0.7445925 -0.3963767 1.2472630 O R tem muitas mais fun¸˜es para outras distribui¸˜es de probabilidade, bem como co co fun¸˜es semelhantes para obter a densidade de probabilidade, as densidades acumuladas co e os quartis das distribui¸˜es. No entanto, a explora¸˜o exaustiva destas fun¸˜es sai co ca co fora do ˆmbito desta cadeira, podendo o aluno por exemplo obter mais informa¸˜o no a ca livro Dalgaard (2002), ou ent˜o consultando a ajuda das fun¸˜es que cont´m exemplos e a co e referˆncias a fun¸˜es relacionadas. e co 2.6 Indexa¸˜o ca Na Sec¸˜o 2.2 j´ vimos exemplos de como extrair um elemento de um vector indicando a ca a sua posi¸˜o entre parˆntesis rectos. O R tamb´m nos permite usar vectores dentro desses ca e eVectores de ´ ındices parˆntesis rectos. Estes vectores chamam-se vectores de ´ e ındices. Existem v´rios tipos de aVector de ´ ındices vectores de ´ ındices. Os vectores de ´ ındices booleanos extraem de um vector os elementosl´gicos o correspondentes a posi¸˜es verdadeiras. Vejamos um exemplo concreto, co > x <- c(0, -3, 4, -1, 45, 90, -5) > x [1] 0 -3 4 -1 45 90 -5 > x > 0 [1] FALSE FALSE TRUE FALSE TRUE TRUE FALSE > y <- x > 0 A terceira instru¸˜o do c´digo mostrado acima ´ uma condi¸˜o l´gica envolvendo ca o e ca o o vector x. Esta condi¸˜o ´ uma compara¸˜o com o valor zero. Devido ` regra de ca e ca a reciclagem, o resultado desta compara¸˜o ´ um vector de valores l´gicos resultantes de ca e o fazer a compara¸˜o para cada elemento do vector x. Na instru¸˜o seguinte guardamos ca ca este vector l´gico no objecto y. Usando este vector como um vector de ´ o ındices, podemos obter os elementos de x que s˜o maiores do que zero, da seguinte forma, a > x[y] [1] 4 45 90 Como os elementos de y que s˜o verdadeiros (true) s˜o o 3º, 5º e o 6º, isto corres- a a ponde a extrair esses elementos de x, que ´ o resultado que obtemos com a instru¸˜o e ca mostrada acima. Poder´ ıamos obter um resultado igual, evitando criar um novo vector, fazendo > x[x > 0] [1] 4 45 90 Tirando partido da gama de operadores l´gicos dispon´ o ıveis no R, podemos construir vectores de indexa¸˜o l´gicos mais complexos, ca o > x[x <= -2 | x > 5] [1] -3 45 90 -5 > x[x > 40 & x < 100] [1] 45 90
    • 2.6 Indexa¸˜o ca 21peradores l´gicos o O operador “|” corresponde ao OU (disjun¸˜o) l´gico, enquanto o operador “&” ´ o ca o e E (conjun¸˜o) l´gica. Isto quer dizer que a primeira instru¸˜o d´ como resultado os ca o ca a elementos de x que s˜o menores ou iguais a -2, ou maiores do que 5. O segundo exemplo, a por sua vez, mostra-nos os elementos de x que s˜o maiores do que 40 e menores do que a 100. Note que existem duas variantes destes dois operadores l´gicos com um modo de o funcionamento ligeiramente diferente. Eles s˜o os operadores “||” e “&&”. Ambos fazem a as mesmas opera¸˜es que os anteriores, o OU e o E l´gicos. A diferen¸a reside no facto co o c de os operadores anteriores fazerem essas opera¸˜es de forma vectorial, ou seja elemento co a elemento quando os operandos contˆm mais do que um elemento, o que permite por e exemplo aplicar as opera¸˜es sobre conjuntos de n´meros, como nos exemplos mostrados co u em cima. Ou seja estes operadores produzem um conjunto de resultados (valores T ou F). J´ as variantes com dois s´ a ımbolos, s´ fazem a opera¸˜o sobre o primeiro elemento, ou o ca seja procedem da esquerda para a direita, produzindo um unico resultado. Estas ultimas ´ ´ variantes s˜o essencialmente usadas em instru¸˜es de controlo da execu¸˜o de programas, a co ca como iremos ver na Sec¸˜o 3.2.1. ca O R tamb´m nos permite usar um vector de n´meros inteiros como ´ e u ındice de um Vector de ´ ındices outro vector. Os n´meros desse vector de ´ u ındices correspondem aos elementos a extrair num´ricos e do outro vector, > (v <- c("a", "b", "c", "d", "e", "f", "g", "h", "i", "j")) [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" > v[c(4, 6)] [1] "d" "f" > v[1:3] [1] "a" "b" "c" Podemos ainda usar um vector com n´meros negativos, o que nos permite indicar u ´ Indices negativos quais os elementos a n˜o obter como resultado da indexa¸˜o, a ca > v[-1] [1] "b" "c" "d" "e" "f" "g" "h" "i" "j" > v[-c(4, 6)] [1] "a" "b" "c" "e" "g" "h" "i" "j" > v[-(1:3)] [1] "d" "e" "f" "g" "h" "i" "j" Note bem a importˆncia dos parˆntesis no ultimo exemplo, devido ` precedˆncia do a e ´ a e operador “:” j´ mencionada na Sec¸˜o 2.5. a ca Um vector tamb´m pode ser indexado por um vector de strings tirando partido do e ´ Indices com nomes facto de o R permitir dar nomes aos elementos de um vector atrav´s na fun¸˜o names(). e ca Vectores com os elementos com nomes s˜o por vezes prefer´ a ıveis pois as suas “posi¸˜es” co s˜o mais facilmente memoriz´veis. Suponhamos que t´ a a ınhamos um vector com as taxas de infla¸˜o de 5 pa´ ca ıses europeus. Poder´ıamos criar um vector com nomes da seguinte Dar nomes a forma, elementos de vectores > tx.infl <- c(2.5, 2, 2.1, 2.3, 1.9) > names(tx.infl) <- c("Portugal", "Fran¸a", "Espanha", "It´lia", c a + "Alemanha") > tx.infl
    • 22 2 FUNDAMENTOS DA LINGUAGEM R Portugal Fran¸a c Espanha It´lia Alemanha a 2.5 2.0 2.1 2.3 1.9 Os elementos do vector tx.infl podem agora ser acedidos usando os seus nomes, > tx.infl["Portugal"] Portugal 2.5 > tx.infl[c("Espanha", "Alemanha")] Espanha Alemanha 2.1 1.9´Indices vazios Finalmente, os ´ ındices podem ser vazios, o que tem o significado que todos os elemen- tos s˜o seleccionados. Por exemplo, se pretendemos preencher todas as posi¸˜es de um a co vector com zeros podemos fazer x[] <- 0. De notar, que isto ´ diferente de fazer x <- e 0, que teria como efeito atribuir ao vector x um vector com um unico elemento (zero), ´ enquanto que a primeira alternativa, assumindo que o vector x j´ existia, iria substituir a todos os seus elementos por zero. Tente ambas as alternativas. 2.7 Matrizes Por vezes poderemos estar interessados em armazenar a nossa informa¸˜o em estruturas caO que ´ uma matriz e de dados com mais do que uma dimens˜o, como ´ o caso dos vectores. As matrizes arran- a e jam a informa¸˜o em duas dimens˜es. Em R, as matrizes n˜o s˜o mais do que vectores ca o a a com uma propriedade especial que ´ a dimens˜o. Vejamos um exemplo. Suponhamos que e a temos doze n´meros correspondentes `s vendas trimestrais durante o ultimo ano, em trˆs u a ´ eCriar uma matriz lojas. As instru¸˜es seguintes permitem “organizar” esses n´meros como uma matriz, co u > vendas <- c(45, 23, 66, 77, 33, 44, 56, 12, 78, 23, 78, 90) > vendas [1] 45 23 66 77 33 44 56 12 78 23 78 90 > dim(vendas) <- c(3, 4) > vendas [,1] [,2] [,3] [,4] [1,] 45 77 56 23 [2,] 23 33 12 78 [3,] 66 44 78 90 Repare como os n´meros foram “espalhados” por uma matriz com 3 linhas e 4 colunas, u que foi a dimens˜o que atribu´ a ımos ao vector vendas atrav´s da fun¸˜o dim(). Na e ca realidade seria mais simples criar a matriz usando uma fun¸˜o espec´ ca ıfica para isso, > vendas <- matrix(c(45, 23, 66, 77, 33, 44, 56, 12, 78, 23, 78, + 90), 3, 4) Como eventualmente ter´ reparado os n´meros foram “espalhados” pela matriz por a u coluna, i.e. primeiro foi preenchida a primeira coluna, depois a segunda, etc. Caso n˜o a seja isto o que pretendemos, poderemos preencher a matriz por linhas da seguinte forma, > vendas <- matrix(c(45, 23, 66, 77, 33, 44, 56, 12, 78, 23, 78, + 90), 3, 4, byrow = T) > vendas
    • 2.7 Matrizes 23 [,1] [,2] [,3] [,4][1,] 45 23 66 77[2,] 33 44 56 12[3,] 78 23 78 90 Nas matrizes tamb´m ´ poss´ dar nomes aos elementos para tornar a leitura da in- e e ıvelforma¸˜o mais leg´ ca ıvel. Vejamos como fazer isso para a nossa matriz de vendas trimestraisnas 3 lojas, Dar nomes `s linhas a e colunas> rownames(vendas) <- c("loja1", "loja2", "loja3")> colnames(vendas) <- c("1.trim", "2.trim", "3.trim", "4.trim")> vendas 1.trim 2.trim 3.trim 4.trimloja1 45 23 66 77loja2 33 44 56 12loja3 78 23 78 90 Como a visualiza¸˜o das matrizes sugere, podemos aceder aos elementos individuais ca Aceder aosdas matrizes usando um esquema de indexa¸˜o semelhante ao dos vectores, mas desta ca elementos da matrizvez com dois ´ ındices (as dimens˜es da matriz), o> vendas[2, 2][1] 44 Ou ent˜o, tirando partido dos nomes, a> vendas["loja2", "2.trim"][1] 44 De igual modo, podemos tirar partido dos esquemas de indexa¸˜o discutidos na Sec- ca¸˜o 2.6 para seleccionar elementos das matrizes, como mostram os seguintes exemplos,ca> vendas[-2, 2]loja1 loja3 23 23> vendas[1, -c(2, 4)]1.trim 3.trim 45 66 Podemos mesmo omitir uma das dimens˜es das matrizes para deste modo obter todos oos elementos da mesma (um ´ ındice vazio),> vendas[1, ]1.trim 2.trim 3.trim 4.trim 45 23 66 77> vendas[, "4.trim"]loja1 loja2 loja3 77 12 90 As fun¸˜es cbind() e rbind() podem ser usadas para juntar dois ou mais vectores coou matrizes, por colunas ou por linhas, respectivamente. Os seguintes exemplos ilustramo seu uso,
    • 24 2 FUNDAMENTOS DA LINGUAGEM R > m1 <- matrix(c(45, 23, 66, 77, 33, 44, 56, 12, 78, 23), 2, 5) > m1 [,1] [,2] [,3] [,4] [,5] [1,] 45 66 33 56 78 [2,] 23 77 44 12 23 > cbind(c(4, 76), m1[, 4]) [,1] [,2] [1,] 4 56 [2,] 76 12 > m2 <- matrix(rep(10, 50), 10, 5) > m2 [,1] [,2] [,3] [,4] [,5] [1,] 10 10 10 10 10 [2,] 10 10 10 10 10 [3,] 10 10 10 10 10 [4,] 10 10 10 10 10 [5,] 10 10 10 10 10 [6,] 10 10 10 10 10 [7,] 10 10 10 10 10 [8,] 10 10 10 10 10 [9,] 10 10 10 10 10 [10,] 10 10 10 10 10 > m3 <- rbind(m1[1, ], m2[5, ]) > m3 [,1] [,2] [,3] [,4] [,5] [1,] 45 66 33 56 78 [2,] 10 10 10 10 10 As regras aritm´ticas e de reciclagem que estudamos anteriormente, tamb´m se apli- e eReciclagem com cam `s matrizes. Vejamos uns pequenos exemplos, amatrizes > m <- matrix(c(45, 23, 66, 77, 33, 44, 56, 12, 78, 23), 2, 5) > m [,1] [,2] [,3] [,4] [,5] [1,] 45 66 33 56 78 [2,] 23 77 44 12 23 > m * 3 [,1] [,2] [,3] [,4] [,5] [1,] 135 198 99 168 234 [2,] 69 231 132 36 69 > m1 <- matrix(c(45, 23, 66, 77, 33, 44), 2, 3) > m1 [,1] [,2] [,3] [1,] 45 66 33 [2,] 23 77 44 > m2 <- matrix(c(12, 65, 32, 7, 4, 78), 2, 3) > m2
    • 2.7 Matrizes 25 [,1] [,2] [,3][1,] 12 32 4[2,] 65 7 78> m1 + m2 [,1] [,2] [,3][1,] 57 98 37[2,] 88 84 122 A aplica¸˜o das opera¸˜es a matrizes (como no exemplo “> m*3” apresentado acima), ca cofunciona elemento a elemento como no caso dos vectores. Isto significa que se um ope-rando ´ menor ele ´ reciclado at´ perfazer o tamanho do maior. No entanto, o R tamb´m e e e epossui operadores especiais para as usuais opera¸˜es da ´lgebra matricial. Por exemplo co aa multiplica¸˜o de duas matrizes pode ser feita da seguinte forma, ca Multiplica¸˜o ca matricial> m1 <- matrix(c(45, 23, 66, 77, 33, 44), 2, 3)> m1 [,1] [,2] [,3][1,] 45 66 33[2,] 23 77 44> m2 <- matrix(c(5, 3, 466, 54.5, 3.2, -34), 3, 2)> m2 [,1] [,2][1,] 5 54.5[2,] 3 3.2[3,] 466 -34.0> m1 %*% m2 [,1] [,2][1,] 15801 1541.7[2,] 20850 3.9 Atente no operador especial (%*%) para simbolizar que se trata da multiplica¸˜o ma- catricial e n˜o a usual multiplica¸˜o. A multiplica¸˜o matricial tem, como ´ sabido, regras a ca ca eespeciais no que concerne, por exemplo, ` dimens˜o das matrizes envolvidas, pelo que a an˜o poder´ ser usada com quaisquer matrizes. a a Ainda no contexto da ´lgebra matricial, o R tem muitas outras fun¸˜es, como por a coexemplo a fun¸˜o t() para obter a transposta de uma matriz quadrada, ca Transposta de uma matriz> t(m1) [,1] [,2][1,] 45 23[2,] 66 77[3,] 33 44ou a fun¸˜o det() para calcular o determinante de uma matriz, ca Determinante de uma matriz> m <- matrix(c(34, -23, 43, 5), 2, 2)> det(m)[1] 1159 ´ E tamb´m poss´ usar a fun¸˜o solve() para obter a inversa de uma matriz, e ıvel ca Inversa de uma matriz
    • 26 2 FUNDAMENTOS DA LINGUAGEM R > solve(m) [,1] [,2] [1,] 0.004314064 -0.03710095 [2,] 0.019844694 0.02933563 Finalmente, esta mesma fun¸˜o pode ser usada para resolver sistemas de equa¸˜es ca coResolver sistemas de lineares. Imaginemos o seguinte sistema de equa¸˜es, coequa¸˜es co −4x + 0.3y = 12.3 54.3x − 4y = 45 Podemos resolvˆ-lo em R da seguinte forma, e > coefs <- matrix(c(-4, 0.3, 54.3, -4), 2, 2, byrow = T) > ys <- c(12.3, 45) > solve(coefs, ys) [1] 216.2069 2923.7586 2.8 Arrays Os arrays s˜o extens˜es das matrizes para mais do que duas dimens˜es. Isto significa a o o que podem ter v´rios ´ a ` ındices. A parte esta pequena diferen¸a, eles podem ser usados c da mesma forma do que as matrizes. De modo semelhante ` fun¸˜o matrix, existe uma a caCriar arrays fun¸˜o array() para facilitar a cria¸˜o de arrays. Segue-se um pequeno exemplo, ca ca > a <- array(1:50, dim = c(2, 5, 5)) > a , , 1 [,1] [,2] [,3] [,4] [,5] [1,] 1 3 5 7 9 [2,] 2 4 6 8 10 , , 2 [,1] [,2] [,3] [,4] [,5] [1,] 11 13 15 17 19 [2,] 12 14 16 18 20 , , 3 [,1] [,2] [,3] [,4] [,5] [1,] 21 23 25 27 29 [2,] 22 24 26 28 30 , , 4 [,1] [,2] [,3] [,4] [,5] [1,] 31 33 35 37 39 [2,] 32 34 36 38 40 , , 5 [,1] [,2] [,3] [,4] [,5] [1,] 41 43 45 47 49 [2,] 42 44 46 48 50Indexar arrays Os esquemas usuais de indexa¸˜o que vimos para vectores e matrizes, podem tamb´m ca e ser aplicados aos arrays.
    • 2.9 Listas 272.9 ListasUma lista ´ uma colec¸˜o ordenada de objectos conhecidos como os componentes da e ca O que ´ uma lista elista. Esses componentes n˜o necessitam de ser do mesmo tipo, modo ou tamanho. Os acomponentes de uma lista em R s˜o sempre numerados e podem tamb´m ter um nome a eassociados a eles. Vejamos um pequeno exemplo de cria¸˜o de uma lista em R, ca Criar uma lista> estudante <- list(nro = 34453, nome = "Carlos Silva", notas = c(14.3,+ 12, 15, 19)) O objecto estudante ´ uma lista formada por trˆs componentes. Um ´ um n´mero e e e ue tem o nome nro, outro ´ uma string e tem o nome nome, e o terceiro componente ´ e eum vector de n´meros com o nome notas. u Podemos extrair componentes espec´ıficos de uma lista atrav´s da seguinte sintaxe, e Extrair componentes de uma lista> estudante[[1]][1] 34453> estudante[[3]][1] 14.3 12.0 15.0 19.0 Como certamente ter´ reparado, usamos parˆntesis rectos duplos. Se, por exem- a eplo, tiv´ssemos indicado estudante[1], ter´ e ıamos obtido um resultado diferente. Nesteultimo caso ter´´ ıamos uma sub-lista formada pelo primeiro componente da lista estu-dante. Pelo contr´rio, estudante[[1]] obt´m o conte´do do primeiro componente da a e ulista estudante, que neste caso ´ um n´mero, e logo n˜o ´ uma lista. e u a e No caso de listas com componentes com nomes, como o caso da lista estudante,podemos extrair os componentes da lista usando uma forma alternativa,> estudante$nro[1] 34453 Podemos ver todo o conte´do da lista (como ali´s de qualquer objecto no R), escre- u a Mostrar conte´ do uvendo o seu nome, da lista> estudante$nro[1] 34453$nome[1] "Carlos Silva"$notas[1] 14.3 12.0 15.0 19.0 Os nomes dos componentes de uma lista s˜o de facto uma propriedade da lista e aportanto podemos manipul´-los como fizemos com os nomes dos elementos de um vector, a> names(estudante)[1] "nro" "nome" "notas"> names(estudante) <- c("n´mero", "nome", "notas") u> estudante
    • 28 2 FUNDAMENTOS DA LINGUAGEM R $n´mero u [1] 34453 $nome [1] "Carlos Silva" $notas [1] 14.3 12.0 15.0 19.0Extender listas As listas podem ser extendidas acrescentando-lhes novos componentes, > estudante$pais <- c("Ana Castro", "Miguel Silva") > estudante $n´mero u [1] 34453 $nome [1] "Carlos Silva" $notas [1] 14.3 12.0 15.0 19.0 $pais [1] "Ana Castro" "Miguel Silva"N´ mero de u Podemos saber quantos componentes tem uma lista usando a fun¸˜o length(), cacomponentes deuma lista > length(estudante) [1] 4Juntar listas Podemos juntar duas ou mais listas numa s´ usando a fun¸˜o c(), o ca > resto <- list(idade = 19, sexo = "masculino") > estudante <- c(estudante, resto) > estudante $n´mero u [1] 34453 $nome [1] "Carlos Silva" $notas [1] 14.3 12.0 15.0 19.0 $pais [1] "Ana Castro" "Miguel Silva" $idade [1] 19 $sexo [1] "masculino"
    • 2.10 Data Frames 29 2.10 Data Frames Um data frame ´ um objecto do R que ´ normalmente usado para guardar tabelas de e eque ´ um data e dados de um problema qualquer. Na sua forma, um data frame, ´ muito semelhante a eme uma matriz, mas as suas colunas tˆm nomes e podem conter dados de tipo diferente, e contr´riamente a uma matriz. Um data frame pode ser visto como uma tabela de uma a base de dados, em que cada linha corresponde a um registo (linha) da tabela. Cada coluna corresponde `s propriedades (campos) a serem armazenadas para cada registo da a tabela. Podemos criar um data frame da seguinte forma, Criar um data frame > notas.inform <- data.frame(nros = c(2355, 3456, 2334, 5456), + turma = c("tp1", "tp1", "tp2", "tp3"), notas = c(10.3, 9.3, + 14.2, 15)) > notas.inform nros turma notas 1 2355 tp1 10.3 2 3456 tp1 9.3 3 2334 tp2 14.2 4 5456 tp3 15.0 Os elementos de um data frame podem ser acedidos como uma matriz, Aceder aos elementos de um > notas.inform[2, 2] data frame [1] tp1 Levels: tp1 tp2 tp3 Atente no facto que a fun¸˜o data.frame() transformou a coluna turma num factor. ca Isto ´ feito sempre que os elementos de uma coluna sejam todos do tipo string, como ´ o e e caso. Os esquemas de indexa¸˜o descritos na Sec¸˜o 2.6 tamb´m podem ser usados com ca ca e Indexar data frames os data frames. Adicionalmente, as colunas dos data frames podem ser acedidas na sua totalidade usando o seu nome, > notas.inform$nros [1] 2355 3456 2334 5456 Usando os esquemas de indexa¸˜o envolvendo condi¸˜es l´gicas, que foram descritos ca co o na Sec¸˜o 2.6, podemos fazer consultas mais complexas aos dados guardados num data ca frame. Prosseguindo a analogia com tabelas de bases de dados, os exemplos seguintes podem ser visto como queries a uma tabela, > notas.inform[notas.inform$notas > 10, ] nros turma notas 1 2355 tp1 10.3 3 2334 tp2 14.2 4 5456 tp3 15.0 > notas.inform[notas.inform$notas > 14, "nros"] [1] 2334 5456 > notas.inform[notas.inform$turma == "tp1", c("nros", "notas")] nros notas 1 2355 10.3 2 3456 9.3
    • 30 2 FUNDAMENTOS DA LINGUAGEM R As consultas a data frames apresentadas acima, podem ser simplificadas atrav´s do e uso da fun¸˜o attach(). Sem entrar em detalhes t´cnicos, podemos dizer que esta ca e As fun¸˜es attach( co fun¸˜o nos permite aceder directamente aos valores nas colunas de um data frame sem ca e detach() para isso necessitarmos de colocar o nome deste atr´s do nome da coluna, como foi feito a nos exemplos acima. Vejamos como isto funciona, > attach(notas.inform) The following object(s) are masked from notas.inform ( position 4 ) : notas nros turma > notas.inform[notas > 14, ] nros turma notas 3 2334 tp2 14.2 4 5456 tp3 15.0 > turma [1] tp1 tp1 tp2 tp3 Levels: tp1 tp2 tp3 O efeito da fun¸˜o attach() ´ o mesmo que se obteria se cri´ssemos uns objectos com ca e a o nome das colunas, contendo os dados das mesmas (por exemplo fazendo “> notas <- notas.inform$notas”). A fun¸˜o detach() tem o efeito inverso, e deve ser executada ca quando j´ n˜o precisamos mais deste acesso “directo” `s colunas, a a a > detach(notas.inform) > turma Error: Object "turma" not found Repare que se a seguir a fazermos o detach tentarmos usar os nomes das colunas, como o fizemos anteriormente, vamos gerar um erro, como se vˆ no exemplo acima. eAcrescentar colunas ´ E poss´ acrescentar novas colunas a um data frame, ıvela um data frame > notas.inform$resultado <- c("aprovado", "oral", "aprovado", "aprovado") > notas.inform nros turma notas resultado 1 2355 tp1 10.3 aprovado 2 3456 tp1 9.3 oral 3 2334 tp2 14.2 aprovado 4 5456 tp3 15.0 aprovado A unica restri¸˜o a este tipo de acrescentos ´ a de que a nova coluna dever´ ter tantos ´ ca e aN´ mero de linhas e u elementos quantas as linhas do data frame. Podemos saber o n´mero de linhas e colunas ucolunas de um data frame da seguinte forma, > nrow(notas.inform) [1] 4 > ncol(notas.inform) [1] 4 Como veremos em sec¸˜es posteriores deste texto de apoio, na maioria dos casos co n˜o iremos escrever os dados a guardar num data frame “` m˜o” usando a fun¸˜o a a a ca data.frame(), como fizemos anteriormente. De facto, na maioria das situa¸˜es iremos co buscar os nossos dados ou a uma base de dados, ou a um ficheiro de texto, ou mesmo a uma fonte de dados dispon´ na Internet. De qualquer modo, sempre que pretendemos ıvelIntroduzir dados introduzir n´s pr´prios os dados podemos usar um interface tipo folha de c´lculo que o o o anum data frame R possui, para facilitar a nossa tarefa. Vejamos como,
    • 2.11 S´ries Temporais e 31> outras.notas <- data.frame()> outras.notas <- edit(outras.notas) A primeira instru¸˜o serve para dizer ao R que o objecto outras.notas ´ um data ca eframe (vazio de dados, neste momento). A segunda instru¸˜o invoca o referido interface catipo folha de c´lculo com esse objecto, e coloca o resultado da nossa edi¸˜o nesse mesmo a caobjecto, ou seja as altera¸˜es que fizermos na folha de c´lculo ser˜o armazenadas no co a aobjecto outras.notas. O interface da fun¸˜o edit() permite-nos acrescentar facilmente cavalores nas colunas do data frame bastando para isso clicar em cima de uma c´lula eecome¸ar a escrever o seu valor, bem como dar nomes `s colunas do data frame, clicando c aem cima do seu nome. Experimente.2.11 S´ries Temporais eExistem in´meras aplica¸˜es onde os dados que s˜o recolhidos est˜o etiquetados pelo u co a atempo. Quer isto dizer que existe uma ordem temporal entre as diferentes observa¸˜es code uma ou mais vari´veis. Estes tipos de dados s˜o normalmente conhecidos como s´ries a a etemporais. Uma s´rie temporal (univariada) ´ um conjunto de observa¸˜es de uma vari´vel Y ao e e co a O que ´ uma s´rie e elongo do tempo, y1 , y2 , . . . , yt−1 , yt . Conforme seria previs´ o R tem v´rias facilidades ıvel a temporal?para lidar com este tipo de dados. Na nossa exposi¸˜o vamos distinguir dois tipos de cas´ries: regulares e irregulares. Este tipo de s´ries v˜o ser armazenados em objectos de e e adiferente tipo em R, conforme vamos ver.2.11.1 S´ries Regulares eNuma s´rie temporal regular todas as observa¸˜es est˜o igualmente espa¸adas no tempo. e co a c S´ries regulares eQuer isto dizer que a diferen¸a temporal entre quaisquer duas observa¸˜es ´ sempre a c co emesma. Para este tipo de dados o R disponibiliza os objectos da classe ts ou mts, para s´ries emultivariadas. Este tipo de objectos permite guardar dados referentes a s´ries temporais eregulares. Vejamos exemplos da cria¸˜o deste tipo de objectos: ca Criar s´ries e regulares> ts(rnorm(10), start = 1990, frequency = 1)Time Series:Start = 1990End = 1999Frequency = 1 [1] -0.007145366 0.286113853 -0.178509296 1.110593387 -0.537384054 [6] 0.235266885 -0.347034238 0.186546117 -0.560699688 -0.939207908> ts(rnorm(10), frequency = 4, start = c(1959, 2)) Qtr1 Qtr2 Qtr3 Qtr41959 -0.06177427 -0.39010380 0.523288841960 -0.52024659 0.79999330 0.11223208 1.086452981961 2.64958972 0.27428917 1.44606713> ts(rnorm(10), frequency = 12, start = c(1959, 2)) Feb Mar Apr May Jun Jul1959 1.86124434 -1.21152214 -1.25001426 -0.65898372 0.87284088 -1.32159856 Aug Sep Oct Nov1959 -1.82540080 -0.02475364 1.51389043 -1.20735747 Como vemos, a fun¸˜o principal para criar este tipo de objectos ´ a fun¸˜o ts(). Esta ca e cafun¸˜o recebe no primeiro argumento as observa¸˜es da s´rie e depois tem um conjunto de ca co eargumentos que podem ser usados para explicitar os intervalos de tempo regulares a que
    • 32 2 FUNDAMENTOS DA LINGUAGEM R se observaram esses valores. Assim no primeiro exemplo, indicamos que o primeiro valor ´ observado no tempo 1990 e que entre cada unidade de tempo (i.e. 1990, 1991, 1992, e etc., uma vez que ´ assumido um incremento de 1 entre as unidades de tempo) a vari´vel e a ´ amostrada uma unica vez. J´ no segundo exemplo, indicamos que a s´rie come¸a no e ´ a e c segundo per´ıodo de amostragem da unidade de tempo 1959, e que a s´rie ´ amostrada e e 4 vezes entre cada unidade. Isto leva o R a interpretar esta s´rie como uma s´rie de e e valores trimestrais, o que por sua vez determina a escolha de uma forma adequada para representar esta s´rie. No ultimo exemplo, indicamos que a s´rie ´ amostrada 12 vezes e ´ e e entre cada unidade de tempo o que leva o R a assumir amostragens mensais entre cada ano, e mais uma vez determina uma maneira adequada de a representar.S´ries multivariadas e No caso de s´ries multivariadas podemos cri´-las de igual forma: e a > (m <- ts(matrix(rnorm(30), 10, 3), start = c(1961, 6), frequency = 12)) Series 1 Series 2 Series 3 Jun 1961 -0.59624245 1.0808275 0.5293899 Jul 1961 0.29513818 -0.9746566 -0.7295948 Aug 1961 0.61927156 -0.1127870 1.2087357 Sep 1961 -0.04721077 1.0725438 1.1728149 Oct 1961 -1.20085735 0.1319664 0.4304150 Nov 1961 -0.85436753 0.3550235 -0.9931418 Dec 1961 -1.21451369 -1.6505330 -1.1396180 Jan 1962 -0.44169035 0.4167947 0.6371993 Feb 1962 0.91459593 0.1500598 -0.6730498 Mar 1962 -0.36624088 -0.2471749 0.6283073 Repare como foram “tratadas” de maneira diferente, em termos de apresenta¸˜o, pelo ca R.Gr´ficos de s´ries a e Relativamente ` representa¸˜o gr´fica das s´ries temporais, podemos usar de igual a ca a e modo a muitos objectos, a fun¸˜o plot(), como vemos no seguinte exemplo, ca > k <- ts(rnorm(100), frequency = 4, start = c(1959, 2)) > plot(k) que produz o gr´fico apresentado na Figura 3. a 2 1 0 k −1 −2 1960 1965 1970 1975 1980 Time Figura 3: Gr´fico de uma s´rie temporal univariada. a e No caso de o objecto em cause ser uma s´rie multivariada a fun¸˜o plot() produz e ca gr´ficos separados para cada s´rie como vemos na Figura 4. a e > m <- ts(matrix(rnorm(300), 100, 3), start = c(1961, 6), frequency = 12) > plot(m)
    • 2.11 S´ries Temporais e 33 m 2 1 Series 1 0 −1 −2 2 1 Series 2 0 −1 −2 2 1 Series 3 0 −1 −2 1962 1964 1966 1968 Time Figura 4: Gr´fico de uma s´rie temporal multivariada. a e Atrav´s do parˆmetro “plot.type” podemos indicar que pretendemos um s´ gr´fico e a o acom todas as s´ries, e> m <- ts(matrix(rnorm(300), 100, 3), start = c(1961, 6), frequency = 12)> plot(m, plot.type = "single", col = 1:3)> legend("topright", legend = colnames(m), col = 1:3, lty = 1)o que leva ao gr´fico na Figura 5. a Series 1 Series 2 2 Series 3 1 0 m −1 −2 −3 1962 1964 1966 1968 Time Figura 5: Gr´fico unico de uma s´rie temporal multivariada. a ´ e Existem uma s´rie de fun¸˜es para manipular os objectos criados pela fun¸ao ts() e co cque podem ter grande utilidade. Vejamos alguns exemplos, Algumas fun¸˜es co uteis ´> x <- ts(rnorm(10), frequency = 4, start = c(1959, 2))> start(x)[1] 1959 2> end(x)
    • 34 2 FUNDAMENTOS DA LINGUAGEM R [1] 1961 3 > window(x, start = c(1959, 5)) Qtr1 Qtr2 Qtr3 Qtr4 1960 0.96364972 -1.42112904 -0.64183730 -0.24208549 1961 1.39783879 0.24219084 -0.05084689 > window(x, end = c(1959, 7)) Qtr1 Qtr2 Qtr3 Qtr4 1959 0.9245848 -0.0970050 0.8055003 1960 0.9636497 -1.4211290 -0.6418373 > window(x, start = c(1959, 4), end = c(1959, 9)) Qtr1 Qtr2 Qtr3Qtr4 1959 0.8055003 1960 0.9636497 -1.4211290 -0.6418373 -0.2420855 1961 1.3978388 A fun¸˜o start() permite-nos obter a etiqueta temporal do in´ da s´rie, enquanto ca ıcio e que a fun¸˜o end() faz o contr´rio. Quanto ` fun¸˜o window(), ela permite-nos extra´ ca a a ca ır uma janela temporal da s´rie, explicitando o in´ e ıcio e o fim dessa janela, ou omitindo um desses tempos o que faz com que seja assumido o in´ ıcio ou o final de toda a s´rie, eLags e diferen¸as c respectivamente. > (x <- ts(rnorm(10), frequency = 4, start = c(1959, 2))) Qtr1 Qtr2 Qtr3 Qtr4 1959 -0.53646433 -0.67589743 -0.43825372 1960 0.60812619 0.26228902 -0.03652399 0.43490010 1961 1.47686955 -1.24983261 1.44151984 > lag(x) Qtr1 Qtr2 Qtr3 Qtr4 1959 -0.53646433 -0.67589743 -0.43825372 0.60812619 1960 0.26228902 -0.03652399 0.43490010 1.47686955 1961 -1.24983261 1.44151984 > lag(x, 4) Qtr1 Qtr2 Qtr3 Qtr4 1958 -0.53646433 -0.67589743 -0.43825372 1959 0.60812619 0.26228902 -0.03652399 0.43490010 1960 1.47686955 -1.24983261 1.44151984 > diff(x) Qtr1 Qtr2 Qtr3 Qtr4 1959 -0.1394331 0.2376437 1960 1.0463799 -0.3458372 -0.2988130 0.4714241 1961 1.0419695 -2.7267022 2.6913525 > diff(x, differences = 2) Qtr1 Qtr2 Qtr3 Qtr4 1959 0.37707682 1960 0.80873619 -1.39221706 0.04702415 0.77023710 1961 0.57054536 -3.76867161 5.41805462
    • 2.11 S´ries Temporais e 35> diff(x, lag = 2) Qtr1 Qtr2 Qtr3 Qtr41959 0.098210611960 1.28402362 0.70054274 -0.64465017 0.172611081961 1.51339354 -1.68473271 -0.03534971 A fun¸˜o lag() permite-nos fazer um “shift” da s´rie para tr´s (por defeito) ou para a ca e afrente x unidades de tempo (o segundo argumento da fun¸˜o). Quanto ` fun¸˜o diff() ca a caela permite-nos calcular diferen¸as de v´ria ordem (parˆmetro “differences”) entre valores c a asucessivos, ou mesmo valores distanciados mais unidades de tempo (parˆmetro “lag”). a Por vezes estamos interessados em juntar v´rias s´ries num s´ objecto, isto ´ numa a e o e Juntar s´ries numa es´rie multivariada. A maior dificuldade desta tarefa decorre da possibilidade de n˜o e a s´ ohaver total concordˆncia das etiquetas temporais das s´ries que pretendemos juntar. Ao a eutlizarmos objectos da classe ts o R vai encarregar-se de resolver este problema por n´s! oVejamos um exemplo:> (x <- ts(rnorm(10), frequency = 4, start = c(1959, 2))) Qtr1 Qtr2 Qtr3 Qtr41959 1.01532292 1.50409802 -0.594152891960 0.28531497 0.45710867 0.28391136 0.166227121961 0.03461353 -0.72061564 0.08729295> (y <- ts(rnorm(10), frequency = 4, start = c(1960, 1))) Qtr1 Qtr2 Qtr3 Qtr41960 -0.041664330 -0.058680340 -1.360239359 0.8971746041961 0.008411543 0.279581887 -0.478224920 -0.3702008001962 1.162627682 0.134785203> cbind(x, y) x y1959 Q2 1.01532292 NA1959 Q3 1.50409802 NA1959 Q4 -0.59415289 NA1960 Q1 0.28531497 -0.0416643301960 Q2 0.45710867 -0.0586803401960 Q3 0.28391136 -1.3602393591960 Q4 0.16622712 0.8971746041961 Q1 0.03461353 0.0084115431961 Q2 -0.72061564 0.2795818871961 Q3 0.08729295 -0.4782249201961 Q4 NA -0.3702008001962 Q1 NA 1.1626276821962 Q2 NA 0.134785203 A fun¸˜o cbind(), quando aplicada a s´ries temporais vai fazer uma jun¸˜o delas ca e caolhando para as respectivas etiquetas temporais e preenchendo os valores n˜o concordan- ates com NA’s. A fun¸˜o embed(), por sua vez, permite gerar diferentes colunas formadas pela s´rie ca etemporal deslizada diferentes passos temporais para tr´s. Vejamos um exemplo, a “Embed’s” temporais> (x <- ts(rnorm(10), frequency = 4, start = c(1959, 2))) Qtr1 Qtr2 Qtr3 Qtr41959 -1.26304477 0.52757493 -1.663844941960 1.79545393 0.07105220 -0.08895523 -1.774035721961 0.82165185 0.14742042 1.33359531
    • 36 2 FUNDAMENTOS DA LINGUAGEM R > embed(x, 3) [,1] [,2] [,3] [1,] -1.66384494 0.52757493 -1.26304477 [2,] 1.79545393 -1.66384494 0.52757493 [3,] 0.07105220 1.79545393 -1.66384494 [4,] -0.08895523 0.07105220 1.79545393 [5,] -1.77403572 -0.08895523 0.07105220 [6,] 0.82165185 -1.77403572 -0.08895523 [7,] 0.14742042 0.82165185 -1.77403572 [8,] 1.33359531 0.14742042 0.82165185 Note, em primeiro lugar que o resultado ´ uma matriz e n˜o uma s´rie multivariada. e a e Na matriz resultante, a linha i tem os valores Yi+e−1 , Yi+e−2 , · · · , Yi da s´rie temporal, e em que e ´ o tamanho do “embed” indicado no segundo argumento da fun¸˜o. e ca Um efeito semelhante, mas em que o resultado ´ uma s´rie multivariada, pode ser e e obtido da seguinte forma, > x Qtr1 Qtr2 Qtr3 Qtr4 1959 -1.26304477 0.52757493 -1.66384494 1960 1.79545393 0.07105220 -0.08895523 -1.77403572 1961 0.82165185 0.14742042 1.33359531 > na.omit(cbind(lag(x, 2), lag(x), x)) lag(x, 2) lag(x) x 1959 Q2 -1.66384494 0.52757493 -1.26304477 1959 Q3 1.79545393 -1.66384494 0.52757493 1959 Q4 0.07105220 1.79545393 -1.66384494 1960 Q1 -0.08895523 0.07105220 1.79545393 1960 Q2 -1.77403572 -0.08895523 0.07105220 1960 Q3 0.82165185 -1.77403572 -0.08895523 1960 Q4 0.14742042 0.82165185 -1.77403572 1961 Q1 1.33359531 0.14742042 0.82165185 Note como a fun¸˜o na.omit() foi usada para retirar do resultado do cbind() as ca “linhas” em que existiam NA’s. 2.11.2 S´ries Irregulares e Nas s´ries irregulares os valores n˜o tˆm necessariamente que ser espalhados de forma e a e igual ao longo do tempo. Isto quer dizer que as etiquetas temporais n˜o tˆm neces- a e sariamente que ter um regularidade como acontece com as s´ries regulares que vimos e anteriormente. O R tem v´rias packages que definem objectos espec´ a ıficos para armazenar este tipo de dados. A lista seguinte apresenta as principais: ˆ A package its que define os objectos “its”. ˆ A package tseries que define os objectos “irts”. ˆ A package fBasics que define os objectos “timeSeries”. ˆ A package zoo que define os objectos “zoo”. No nosso estudo vamos usar a package “zoo”. Vejamos como criar um objecto “zoo”Criar uma s´rie e em R:irregular
    • 2.11 S´ries Temporais e 37> library(zoo)> (x <- zoo(rnorm(5), c("2006-3-21", "2006-3-24", "2006-6-21",+ "2006-6-23", "2006-09-21"))) 2006-09-21 2006-3-21 2006-3-24 2006-6-21 2006-6-23-2.45827056 -1.13546300 0.10284559 -0.57846242 -0.04002960> index(x)[1] "2006-09-21" "2006-3-21" "2006-3-24" "2006-6-21" "2006-6-23"> coredata(x)[1] -2.45827056 -1.13546300 0.10284559 -0.57846242 -0.04002960 O segundo argumento da fun¸˜o zoo(), as etiquetas temporais dos dados, pode ser cade qualquer tipo (!), desde que fa¸a sentido ordenar os seus valores (isto ´ desde que se c epossa aplicar a fun¸˜o order() aos valores). Fora isto, n˜o h´ qualquer limita¸˜o o que ca a a catorna este tipo de objectos bastante flex´ ıveis. A maior parte das vezes as etiquetas das nossas s´ries temporais v˜o ser datas/horas. e aNesse contexto, vamos agora ver maneiras alternativas de lidar com datas e/ou horas emR. Datas/horas em R O R tem v´rios tipos de objectos para lidar com datas e tempo em geral. Vejamos aalguns exemplos: 1. Os objectos do tipo “Date” Objectos do tipo “Date” Neste tipo de objectos as datas s˜o representadas internamente como o n´mero de a u dias que passaram desde 1970-01-01. > Sys.Date() [1] "2006-10-21" > hoje <- Sys.Date() > format(hoje, "%d %b %Y") [1] "21 Out 2006" > (dezsemanas <- seq(hoje, len = 10, by = "1 week")) [1] "2006-10-21" "2006-10-28" "2006-11-04" "2006-11-11" "2006-11-18" [6] "2006-11-25" "2006-12-02" "2006-12-09" "2006-12-16" "2006-12-23" > weekdays(hoje) [1] "s´bado" a > months(hoje) [1] "Outubro" A fun¸˜o Sys.Date() permite-nos obter a data de hoje num objecto do tipo “Date”. ca A fun¸˜o format() permite mostrar um objecto deste tipo de muitas formas, atra- ca v´s de um segundo parˆmetro que tem in´meras possibilidades para extra´ e mos- e a u ır trar partes de uma data no ´cran. Consulte a ajuda desta fun¸˜o para saber mais e ca sobre estas variantes. A fun¸˜o seq(), que j´ estudamos anteriormente, quando ca a aplicada a objectos do tipo “Date” permite gerar sequˆncias de datas. A fun¸˜o e ca possui valores pr´prios no parˆmetro “by” que podem ser usados para produzir a o a sequˆncia desejada8 . A fun¸˜o weekdays() permite-nos obter o dia da semana cor- e ca respondente ` data em causa, enquanto que a fun¸˜o months() faz o mesmo para a ca o nome do mˆs. e 8 Consulte a ajuda da fun¸˜o seq.Date para obter mais alternativas. ca
    • 38 2 FUNDAMENTOS DA LINGUAGEM R > as.Date("2006-9-23") - as.Date("2003-04-30") Time difference of 1242 days > ISOdate(2001, 1, 1) - ISOdate(2000, 6, 14) Time difference of 201 days > cut(ISOdate(2001, 1, 1) + 70 * 86400 * runif(10), "weeks") [1] 2001-02-12 2001-01-15 2001-01-29 2001-01-29 2001-01-08 2001-02-26 [7] 2001-01-29 2001-01-01 2001-01-08 2001-01-01 9 Levels: 2001-01-01 2001-01-08 2001-01-15 2001-01-22 ... 2001-02-26 > table(cut(seq(ISOdate(2006, 1, 1), to = ISOdate(2006, 12, 31), + by = "day"), "month")) 2006-01-01 2006-02-01 2006-03-01 2006-04-01 2006-05-01 2006-06-01 2006-07-01 31 28 31 30 31 30 31 2006-08-01 2006-09-01 2006-10-01 2006-11-01 2006-12-01 31 30 31 30 31 Nestes novos exemplos vemos a fun¸˜o as.Date(), que permite converter uma ca string para um objecto do tipo “Date”. Vemos tamb´m a fun¸˜o ISOdate() que e ca nos possibilita uma forma alternativa de criar um objecto do tipo “Date” indicando o ano, mˆs e dia pelos seus n´meros. Vemos ainda a possibilidade que o R nos d´ de e u a usar alguns operadores aritm´ticos com objectos do tipo “Date”, obtendo resultados e em termos da diferen¸a temporal entre as datas. Por fim, vemos dois exemplos de c utiliza¸˜o da fun¸˜o cut() que, quando aplicada a objectos do tipo “Date”, gera um ca ca factor em que cada valor resulta de uma discretiza¸˜o das datas fornecidas no pri- ca meiro argumento do cut(), para um conjunto de intervalos definidos pelo segundo argumento. No primeiro exemplo os intervalos s˜o definidos dividindo as datas por a semanas, enquanto que no segundo ´ por mˆs. No segundo exemplo, vemos uma e e utilidade deste tipo de discretiza¸˜o, aplicando a fun¸˜o table() ao factor resul- ca ca tante, obtendo deste modo uma contagem do n´mero de datas em cada intervalo u (cada mˆs neste exemplo). Na realidade, neste segundo exemplo, se repararmos e atentamente nas datas que s˜o fornecidas ao cut(), o que vamos obter ´ o n´mero a e u de dias em cada mˆs do ano de 2006. eObjectos do tipo 2. Objectos do tipo POSIXt“POSIXt” Este tipo de objectos permite guardar tempos que contˆm informa¸˜o n˜o s´ sobre e ca a o a data, como os anteriores, mas tamb´m sobre as horas. Com este tipo de objectos e podemos guardar tempos at´ ao segundo. Na realidade existem dois tipos de “sub- e objectos”: (a) POSIXct que representam as datas como o n´mero de segundos que passaram u desde 1970. (b) POSIXlt que representam as datas como uma lista com v´rias componentes, a como: “sec”; “min”; “hour”; “mday”; “mon”; “year”; etc. Vejamos exemplos destes tipo de objectos: > (z <- Sys.time()) [1] "2006-10-21 00:59:09 Hora de Ver~o de GMT" a > as.POSIXlt(Sys.time(), "GMT") [1] "2006-10-20 23:59:09 GMT"
    • 2.11 S´ries Temporais e 39 > as.POSIXct("2006-12-23 12:45") - as.POSIXct("2006-12-21 21:54") Time difference of 1.61875 days > format(Sys.time(), "%a %b %d %X %Y %Z") [1] "s´b Out 21 0:59:09 2006 Hora de Ver~o de GMT" a a A fun¸˜o Sys.time() obt´m a data/hora actual no computador num objecto do ca e tipo POSIXt. A fun¸˜o as.POSIXlt() pode ser usada para converter diferentes ca objectos para a classe POSIXlt, e neste caso aproveitamos tamb´m para mostrar e como, durante essa convers˜o, resolvemos mudar de fuso hor´rio, do nosso para a a GMT. Vemos tamb´m um exemplo de como fazer aritm´tica com este tipo de e e objectos, al´m de um outro exemplo do uso da fun¸˜o format() que j´ vimos e ca a acima. > x <- c("1jan1960", "2jan1960", "31mar1960", "30jul1960") > strptime(x, "%d%b%Y") [1] "1960-01-01" "1960-01-02" "1960-03-31" "1960-07-30" > dates <- c("02/27/92", "02/27/92", "01/14/92", "02/28/92", "02/01/92") > times <- c("23:03:20", "22:29:56", "01:03:30", "18:21:03", "16:56:26") > x <- paste(dates, times) > strptime(x, "%m/%d/%y %H:%M:%S") [1] "1992-02-27 23:03:20" "1992-02-27 22:29:56" "1992-01-14 01:03:30" [4] "1992-02-28 18:21:03" "1992-02-01 16:56:26" Nestes novos exemplos vemos ilustra¸˜es de uma opera¸˜o bastante frequente, em co ca particular se vamos importar dados que involvem datas, de outras aplica¸˜es. Nor- co malmente recebemos essas datas como strings, e portanto temos depois que extra´ ır dessas strings as nossas datas/horas. O problema ´ que n˜o existe uma unica e a ´ norma seguida por todos para representar datas. Aqui entra a fun¸˜o strptime() ca que pode ser usada para extra´ datas/horas de strings indicando quar o formato ır em que essas datas/horas est˜o representadas nas strings. Isso ´ feito atrav´s do a e e segundo argumento da fun¸˜o que usa um conjunto de c´digos com v´rio signifi- ca o a cado, muito ao estilo do que vimos na fun¸˜o format(). Para mais detalhes sobre ca estes c´digos o melhor ´ consultar a ajuda da fun¸˜o. o e ca Ap´s esta incurs˜o pelas datas e horas em R voltemos aos nossos objectos “zoo”. o aCome¸emos por ver exemplos de visualiza¸˜o deste tipo de objectos. Os gr´ficos da c ca aFigura 6 mostram-nos uma s´rie univariada e tamb´m uma multivariada, guardadas em e eobjectos “zoo”. S´ries multivariadas e irregulares> z <- zoo(rnorm(100), sort(ISOdate(2001, 1, 1) + 70 * 86400 *+ runif(100)))> z.mtx <- zoo(matrix(rnorm(100), 50, 2), sort(ISOdate(2001, 1,+ 1) + 70 * 86400 * runif(50)))> par(mfrow = c(1, 2))> plot(z)> plot(z.mtx, plot.type = "single", col = 1:2)> legend("topright", c("1ªcol", "2ªcol"), lty = 1, col = 1:2)> par(mfrow = c(1, 1)) Vejamos agora um conjunto de fun¸˜es uteis para diversos tipos de manipula¸˜o de co ´ caobjectos “zoo”. In´ ıcio e fim de s´ries e “zoo”
    • 40 2 FUNDAMENTOS DA LINGUAGEM R 2 1ªcol 2ªcol 2 1 1 0 0 z.mtx z −1 −1 −2 −2 −3 −3 9.79e+08 9.83e+08 9.79e+08 9.83e+08 Index Index Figura 6: Gr´ficos de objectos “zoo”. a
    • 2.11 S´ries Temporais e 41> (x <- zoo(rnorm(15), seq(as.Date("2006-09-01"), length = 15,+ by = "days"))) 2006-09-01 2006-09-02 2006-09-03 2006-09-04 2006-09-05 2006-09-06 0.367653423 1.446087183 1.342642534 2.005092105 -0.310355469 -0.001024538 2006-09-07 2006-09-08 2006-09-09 2006-09-10 2006-09-11 2006-09-12 0.209334800 1.250436925 0.161235127 -0.270383756 2.978076138 -1.512003802 2006-09-13 2006-09-14 2006-09-15-0.172072092 0.237434668 -1.095001597> start(x)[1] "2006-09-01"> end(x)[1] "2006-09-15"> x[3:6] 2006-09-03 2006-09-04 2006-09-05 2006-09-06 1.342642534 2.005092105 -0.310355469 -0.001024538> x[coredata(x) > 0]2006-09-01 2006-09-02 2006-09-03 2006-09-04 2006-09-07 2006-09-08 2006-09-09 0.3676534 1.4460872 1.3426425 2.0050921 0.2093348 1.2504369 0.16123512006-09-11 2006-09-14 2.9780761 0.2374347 As fun¸˜es start() e end() funcionam da mesma forma do que com objectos “ts”. coCOmo vemos a indexa¸˜o funciona da mesma forma como se de um vector “normal” case trata-se, mantendo-se as respectivas etiquetas temporais. De qualquer modo conv´m en˜o esquecer que se trata, n˜o de um vector normal, mas de um objecto mais complexo a a e e e ´que cont´m para al´m dos valores da s´rie, as etiquetas. E importante lembrar-mo-nosdisso quando pretendemos escolher um subconjunto de valores de uma s´rie impondo euma condi¸˜o aos seus valores, como ´ ilustrado no ultimo exemplo. Nesses casos temos ca e ´que nos lembrar que a condi¸˜o a ser imposta ´ sobre os valores (e da´ o uso da fun¸˜o ca e ı cacoredata()) e n˜o sobre o objecto como um todo. a> x[as.Date("2006-09-14")]2006-09-14 0.2374347> window(x, start = as.Date("2006-09-10"), end = as.Date("2006-09-15"))2006-09-10 2006-09-11 2006-09-12 2006-09-13 2006-09-14 2006-09-15-0.2703838 2.9780761 -1.5120038 -0.1720721 0.2374347 -1.0950016> (y <- zoo(rnorm(10), seq(as.Date("2006-09-10"), length = 10,+ by = "days"))) 2006-09-10 2006-09-11 2006-09-12 2006-09-13 2006-09-14 2006-09-15 0.67339402 1.75291084 -0.13133473 -0.01916885 0.50119663 -1.07051968 2006-09-16 2006-09-17 2006-09-18 2006-09-19 1.27971776 0.79160867 0.64387366 -0.64057581> x - y
    • 42 2 FUNDAMENTOS DA LINGUAGEM R 2006-09-10 2006-09-11 2006-09-12 2006-09-13 2006-09-14 2006-09-15 -0.94377777 1.22516530 -1.38066907 -0.15290324 -0.26376196 -0.02448191 Janelas temporais No primeiro exemplo vemos como podemos indexar um objecto “zoo” por valores de objectos “zoo das etiquetas temporais. No segundo vemos a fun¸˜o window() aplicada a um objecto ca “zoo”. Em seguida vemos outros exemplos envolvendo sequˆncias de datas e opera¸˜es e co aritm´ticas com objectos com etiquetas temporais n˜o totalmente coincidentes. e a Nos exemplos seguintes vemos como juntar s´ries “zoo”. e > x <- zoo(rnorm(7), seq(as.Date("2006-09-01"), length = 7, by = "days")) > y <- zoo(rnorm(7), seq(as.Date("2006-09-06"), length = 7, by = "days")) > cbind(x, y) x y 2006-09-01 0.072992109 NA 2006-09-02 -0.302664430 NA 2006-09-03 0.597683194 NA 2006-09-04 0.572150915 NA 2006-09-05 -0.002487241 NA 2006-09-06 -0.898433693 -0.9438510 2006-09-07 0.753787841 1.3302728 2006-09-08 NA 1.1581772 2006-09-09 NA -0.4568366 2006-09-10 NA -0.7295473 2006-09-11 NA -0.6993896 2006-09-12 NA -0.6021335 > merge(x, y, all = FALSE) x y 2006-09-06 -0.8984337 -0.943851 2006-09-07 0.7537878 1.330273Juntar objectos A fun¸˜o cbind() pode ser usada para juntar duas s´ries univariadas numa s´rie ca e e“zoo” multivariada, encarregando-se o R de tratar de valores com etiquetas n˜o concordantes a (os valores da outra s´rie ficam com NA), enquanto que a jun¸˜o usando a fun¸˜o merge() e ca ca permite, em alternativa e atrav´s do parˆmetro “all”, indicar que s´ queremos na jun¸˜o e a o ca os valores concordantes. > xx <- x[1:6] > lag(xx) 2006-09-01 2006-09-02 2006-09-03 2006-09-04 2006-09-05 -0.302664430 0.597683194 0.572150915 -0.002487241 -0.898433693 > merge(xx, lag(xx)) xx lag(xx) 2006-09-01 0.072992109 -0.302664430 2006-09-02 -0.302664430 0.597683194 2006-09-03 0.597683194 0.572150915 2006-09-04 0.572150915 -0.002487241 2006-09-05 -0.002487241 -0.898433693 2006-09-06 -0.898433693 NA > diff(xx) 2006-09-02 2006-09-03 2006-09-04 2006-09-05 2006-09-06 -0.37565654 0.90034762 -0.02553228 -0.57463816 -0.89594645
    • 2.11 S´ries Temporais e 43n¸˜es, diferen¸as co cags de objectos No c´digo anterior vemos a utiliza¸˜o da fun¸˜o lag() sobre objectos “zoo”, bem o ca caoo” como mais um exemplo de jun¸˜o de s´ries atrav´s da fun¸˜o merge(). J´ a fun¸˜o ca e e ca a ca diff() permite-nos obter diferen¸as entre valores sucessivos da s´rie. c e Vejamos agora alguns exemplos de formas de lidar com valores desconhecidos em s´ries temporais guardadas em objectos “zoo”. e Valores desconhecidos em > x objectos “zoo” 2006-09-01 2006-09-02 2006-09-03 2006-09-04 2006-09-05 2006-09-06 0.072992109 -0.302664430 0.597683194 0.572150915 -0.002487241 -0.898433693 2006-09-07 0.753787841 > x[sample(1:length(x), 3)] <- NA > x 2006-09-01 2006-09-02 2006-09-03 2006-09-04 2006-09-05 2006-09-06 2006-09-07 NA -0.3026644 NA 0.5721509 NA -0.8984337 0.7537878 > na.omit(x) 2006-09-02 2006-09-04 2006-09-06 2006-09-07 -0.3026644 0.5721509 -0.8984337 0.7537878 > na.contiguous(x) 2006-09-06 2006-09-07 -0.8984337 0.7537878 > na.approx(x) 2006-09-02 2006-09-03 2006-09-04 2006-09-05 2006-09-06 2006-09-07 -0.3026644 0.1347432 0.5721509 -0.1631414 -0.8984337 0.7537878 > na.locf(x) 2006-09-02 2006-09-03 2006-09-04 2006-09-05 2006-09-06 2006-09-07 -0.3026644 -0.3026644 0.5721509 0.5721509 -0.8984337 0.7537878 A fun¸˜o na.omit() permite eliminar os pontos em que o valor ´ NA. A fun¸˜o ca e ca na.contiguous() extrai a mais longa sequˆncia sem valores NA. A fun¸˜o na.approx() e ca usa interpola¸˜o linear para preencher os valores NA, enquanto que a fun¸˜o na.locf() ca ca preenche cada valor NA com o valor n˜o desconhecido mais recente (i.e. anterior ao NA). a Por vezes temos interesse em aplicar uma qualquer fun¸˜o a uma janela de tamanho x ca da nossa s´rie. Ainda mais interessante ´ fazer essa janela deslizar pela s´rie toda. Para e e e isso podemos usar as seguintes fun¸˜es: co Fun¸˜es deslizantes co > (x <- zoo(rnorm(7), seq(as.Date("2006-09-01"), length = 7, by = "days"))) 2006-09-01 2006-09-02 2006-09-03 2006-09-04 2006-09-05 2006-09-06 -0.961754723 0.008705073 -0.991048555 1.438521921 0.650619612 0.312436234 2006-09-07 -1.376853779 > rapply(x, 4, mean) 2006-09-02 2006-09-03 2006-09-04 2006-09-05 -0.1263941 0.2766995 0.3526323 0.2561810 > rapply(x, 4, mean, align = "right")
    • 44 2 FUNDAMENTOS DA LINGUAGEM R2006-09-04 2006-09-05 2006-09-06 2006-09-07-0.1263941 0.2766995 0.3526323 0.2561810> rollmean(x, 3)2006-09-02 2006-09-03 2006-09-04 2006-09-05 2006-09-06-0.6480327 0.1520595 0.3660310 0.8005259 -0.1379326> rollmean(x, 3, na.pad = T)2006-09-01 2006-09-02 2006-09-03 2006-09-04 2006-09-05 2006-09-06 2006-09-07 NA -0.6480327 0.1520595 0.3660310 0.8005259 -0.1379326 NA> rollmean(x, 3, na.pad = T, align = "right")2006-09-01 2006-09-02 2006-09-03 2006-09-04 2006-09-05 2006-09-06 2006-09-07 NA NA -0.6480327 0.1520595 0.3660310 0.8005259 -0.1379326> rollmean(x, 3, align = "right")2006-09-03 2006-09-04 2006-09-05 2006-09-06 2006-09-07-0.6480327 0.1520595 0.3660310 0.8005259 -0.1379326 A fun¸˜o rapply() permite-nos aplicar uma fun¸˜o qualquer a uma janela deslizante ca cade um certo tamanho (2º argumento), de uma s´rie “zoo”. A aplica¸˜o da fun¸˜o pode e ca caser feita centrando a janela em cada ponto (valor por defeito), ou alinhando a janela` direita ou ` esquerda, usando para isso o parˆmetro “align”. A fun¸˜o rollmean()a a a can˜o ´ mais do que um “envelope” ` chamada da fun¸˜o rapply() com a fun¸˜o “mean”. a e a ca caAmbas as fun¸˜es (rapply e rollmean) tˆm um parˆmetro “na.pad” que permite indicar se co e apretendemos que as etiquetas temporais para as quais n˜o ´ poss´ calcular o valor da a e ıvelfun¸˜o, por inexistˆncia de valores suficientes para preencher a janela deslizante, dever˜o ca a aou n˜o ser preenchidos por NA’s. a
    • 453 Programa¸˜o em R ca3.1 Interac¸˜o com o Utilizador caO R possui diversas fun¸˜es que tˆm como objectivo ou escrever conte´dos no ´cran, ou co e u eler coisas introduzidas pelo utilizador no teclado, isto ´ para gerir a interac¸˜o com o e cautilizador. A fun¸˜o print(), por exemplo, pode ser usada para escrever o conte´do de qualquer ca u Escrever no ´cran eobjecto9 . Por vezes, quando os objectos s˜o muito grandes (p. ex. grandes listas) ´ mais a econveniente usar a fun¸˜o str(), ca> str(list(nros = rnorm(100), dados = matrix(rnorm(10000), 100,+ 100)))List of 2 $ nros : num [1:100] -0.543 0.654 0.207 0.454 -1.125 ... $ dados: num [1:100, 1:100] -2.210 0.511 1.681 0.358 0.656 ... A fun¸˜o cat() tamb´m pode ser usada para escrever objectos ou constantes. Fun- ca eciona com um n´mero qualquer de argumentos, e o que faz ´ transformar os seus argu- u ementos em “strings”, concaten´-los, e s´ depois os escreve no ´cran, a o e> x <- 34> cat("x tem o valor de ", x, "t o que ´ estranho!n") ex tem o valor de 34 o que ´ estranho! e Nesta instru¸˜o, certos caracteres contidos em “strings” tˆm significado especial. Por ca eexemplo “t” significa o caracter Tab, enquanto “n” significa o caracter Newline (isto ´, emuda de linha). Relativamente a leitura de dados introduzidos pelo utilizador tamb´m existem v´rias e a Leitura de dadoship´teses em R. A fun¸˜o scan(), por exemplo, permite ler dados de v´rio tipo, o ca a> x <- scan(n=5)1: 45 21.4 56 66.54 45.8787Read 5 items> x[1] 45.0000 21.4000 56.0000 66.5400 45.8787 Ainda um outro exemplo,> x <- scan()1: 45 66 34.24: 456.7 76: 12.27:Read 6 items> x[1] 45.0 66.0 34.2 456.7 7.0 12.2 E finalmente um outro exemplo com dados de outro tipo,> scan(what=character())1: erer fdf3: 233 44.55:Read 4 items[1] "erer" "fdf" "233" "44.5" A fun¸˜o tem ainda muitas outras poss´ ca ıveis formas de ser usada que podem serconsultadas na respectiva ajuda. 9 Note que este ´ mais um exemplo de uma fun¸˜o gen´rica (c.f. Sec¸˜o 3.4), existindo diversos m´todos e ca e ca epara diferentes classes de objectos.
    • 46 3 ¸˜ PROGRAMACAO EM R 3.2 Estruturas de Controlo da Linguagem R A linguagem R, como a qualquer linguagem de programa¸˜o, possui v´rias instru¸˜es ca a co destinadas a alterar o curso sequencial normal de execu¸˜o dos programas. ca 3.2.1 Instru¸˜es Condicionais co As instru¸˜es condicionais permitem ao programador explicitar diferentes alternativas a co serem executadas dependendo de alguma condi¸˜o a ser testada na altura da execu¸˜o ca ca das instru¸˜es. coA instru¸˜o if ca A instru¸˜o if, por exemplo, permite explicitar uma condi¸˜o booleana e dois con- ca ca juntos de instru¸˜es alternativos que s˜o executados dependendo do valor da condi¸˜o. co a ca Vejamos um pequeno exemplo, > if (x > 0) y <- z / x else y <- z Esta instru¸˜o pode ser facilmente explicada dizendo que no caso de a vari´vel x ser ca a superior a 0, a instru¸˜o que ´ executada ´ a atribui¸˜o da express˜o z/x a y. Caso ca e e ca a contr´rio, o R efectua a outra atribui¸˜o que vem ` frente da palavra else. Em termos a ca a gen´ricos, a semˆntica associada ` instru¸˜o if pode ser descrita da seguinte forma: se e a a ca a condi¸˜o booleana inclu´ entre parenteses ` frente da palavra if fˆr verdadeira, o R ca ıda a o executa o conjunto de instru¸oes que aparecem entre esta condi¸˜o e a palavra else; se a c˜ ca condi¸˜o fˆr falsa, ´ executado o conjunto de instru¸˜es que aparece ` frente da palavra ca o e co a else. No sentido de passarmos do exemplo apresentado acima, para um exemplo mais gen´rico envolvendo um conjunto de instru¸˜es, temos que introduzir a no¸˜o de conjunto e co caBlocos de instru¸˜es co ou bloco de instru¸˜es na linguagem R. Em R um bloco de instru¸˜es ´ normalmente co co e indicado fornecendo essas instru¸˜es em linhas separadas e seguidas, delimitadas por co chavetas. Por exemplo, > if (x > 0) { cat(x ´ positivo.n) e y <- z / x } else { cat(x n~o ´ positivo!n) a e y <- z } Note-se que neste pequeno exemplo usamos a identa¸˜o das instru¸˜es em cada um ca co dos 2 blocos de instru¸˜es “contidos” na instru¸˜o if. Embora n˜o obrigat´ria, esta co ca a o forma de proceder ´ sempre aconselh´vel, por facilitar a “leitura” da instru¸˜o. e a ca A instru¸˜o if tem ainda outras variantes que passamos a descrever. Por exemplo, ca a cla´sula else ´ opcional, podendo n´s usar if’s sem alternativa para o caso de a u e o condi¸˜o ser falsa. Nesse caso, o R n˜o far´ nada como resultado da instru¸˜o if. ca a a caIF’s aninhados Podemos ainda usar v´rias instru¸˜es if aninhadas, como no exemplo seguinte: a co > if (idade < 18) { grupo <- 1 } else if (idade < 35) { grupo <- 2 } else if (idade < 65) { grupo <- 3 } else { grupo <- 4 } Note-se que embora s´ exista uma instru¸˜o em cada bloco deste exemplo, colocamos o ca todas as instru¸˜es entre chavetas como se tratassem de conjuntos de instru¸˜es. Neste co co exemplo concreto, n˜o colocar as chavetas iria originar um erro de sintaxe. A explica¸˜o a ca
    • 3.2 Estruturas de Controlo da Linguagem R 47de tal comportamento, aparentemente estranho, tem a ver com o facto de o R ser umalinguagem interpretada e sai um pouco do ˆmbito desta disciplina. De qualquer modo, auma boa regra para evitar problemas, ´ usar sempre as chavetas para delimitar as duas epartes de uma instru¸˜o if. Mais detalhes e explica¸˜es sobre este comportamento podem ca coser obtidas na sec¸˜o 3.2.1 do manual “R Language Definition” que vem com o R e est´ ca adispon´ no sistema de ajuda do R. ıvel Uma fun¸˜o relacionada com a instru¸˜o if ´ a fun¸˜o ifelse(). Esta fun¸˜o per- ca ca e ca ca A fun¸˜o “ifelse()” camite trabalhar com vectores de condi¸oes boleanas. O seu significado poder´ ser melhor c˜ aapreendido vom um pequeno exemplo,> x <- rnorm(5, sd = 10)> x[1] -5.9357417 -4.5964847 0.5452268 -2.9091063 -9.2760717> sig <- ifelse(x < 0, "-", "+")> sig[1] "-" "-" "+" "-" "-" A instru¸˜o switch() pode tamb´m ser usada para escolher uma de v´rias alterna- ca e a A fun¸˜o “switch()” cativas. Ela consiste numa s´rie de argumentos em que dependendo do valor do primeiro eargumento, o resultado do switch ´ um dos outros argumentos. Vejamos em primeiro elugar um exemplo em que o primeiro argumento ´ um n´mero. Neste caso, o valor desse e un´mero determina qual o argumento do switch que ´ avaliado. Por exemplo, u e> op <- 2> vs <- rnorm(10)> switch(op, mean(vs), median(vs))[1] -0.1936888 O valor obtido resulta de aplicar a fun¸˜o median() ao vector vs, uma vez que o cavalor de op ´ 2, e logo ´ escolhido o segundo argumento a seguir ao teste contido no e eprimeiro argumento do switch. Na realidade, todos os argumentos a seguir ao primeiros˜o tomados como uma lista (c.f. Sec¸˜o 2.9) que pode ter nomes associados a cada a cacomponente como vamos ver no exemplo a seguir. No caso de n˜o ter nomes, como ano exemplo acima, ´ escolhida a componente da lista pelo n´mero indicado no primeiro e uargumento do switch. No caso de o n´mero ser superior ao tamanho da lista, o resultado udo switch ´ NULL. e Ao dar nomes `s componentes da lista, passamos a poder usar valores textuais no aprimeiro argumento, como podemos ver no exemplo seguinte,> semaforo <- "verde"> switch(semaforo, verde = "continua", amarelo = "acelera", vermelho = "p´ra") a[1] "continua" Por estes exemplos podemos ver que a instru¸˜o switch tem a forma gen´rica de ca e switch(valor,lista)e que o resultado da instru¸˜o n˜o ´ mais do que usar o conte´do do primeiro argumento ca a e upara aceder a uma das componentes da lista cujo conte´do das componentes ´ indicado u enos argumentos seguintes da instru¸˜o. Se o primeiro argumento fˆr um n´mero ent˜o ca o u ao resultado ´ a componente com esse n´mero de ordem, se o primeiro argumento fˆr um e u onome, ent˜o ´ extra´ a componente com esse nome. a e ıda
    • 48 3 ¸˜ PROGRAMACAO EM R 3.2.2 Instru¸˜es Iterativas co O R tem v´rias instru¸˜es iterativas (“ciclos”) que nos permitem repetir blocos de instru- a co c˜es. Para al´m destas instru¸˜es o R possui ainda duas instru¸˜es que podem ser usadas ¸o e co co Instru¸˜es iterativ co para controlar a execu¸˜o dos ciclos. ca A instru¸˜o while tem a seguinte estrutura gen´rica, ca e O ciclo while while (<condi¸~o boolena>) ca <bloco de instru¸~es> co A sua semˆntica pode ser descrita por: enquanto a condi¸˜o booleana fˆr verdadeira, a ca o repetir o bloco de instru¸˜es no “corpo” do ciclo. Vejamos um pequeno exemplo, co > x <- rnorm(1) > while (x < -0.3) { + cat("x=", x, "t") + x <- rnorm(1) + } > x [1] 1.516122 Note-se que as instru¸˜es no bloco dentro do ciclo podem nunca ser executadas, co bastando para isso que a condi¸˜o seja falsa da primeira vez que o R “chega” ao ciclo. ca No exemplo acima, se o primeiro n´mero “sorteado” pela fun¸˜o rnorm() fˆr superior ou u ca o igual a -0.3, as instru¸˜es do ciclo n˜o s˜o executadas nenhuma vez. Em sintese podemos co a a dizer que as instru¸˜es no bloco do ciclo while podem ser executadas zero ou mais vezes. co Atente-se que ´ um erro relativamente frequente escrever blocos de instru¸˜es que e co levam a que os ciclos nunca mais terminem. Por exemplo, se no exemplo anterior nos tivessemos enganado e, dentro do ciclo, tivessemos escrito “y <- rnorm(1)”, em vez da atribui¸˜o que a´ se encontra, caso o R “entrasse” no ciclo, nunca mais o terminaria10 . ca ı Como regra geral podemos dizer que se deve escrever os ciclos de tal forma que exista sempre possibilidade de que a(s) vari´vel(eis) que controla(m) a execu¸˜o dos mesmos a ca (no nosso exemplo a vari´vel x), possa sempre ver o seu valor alterado nas instru¸˜es que a co formam o bloco contido no ciclo, de forma a que a condi¸˜o possa vir a ser falsa, ou seja ca de forma a que o ciclo possa vir a terminar.O ciclo repeat A instru¸˜o repeat permite mandar o R executar um bloco de instru¸˜es uma ou ca co mais vezes. A sua forma gen´rica ´, e e repeat <bloco de instru¸~es> co Repare que uma vez que n˜o existe qualquer condi¸˜o l´gica a governar a execu¸˜o a ca o ca repetida do bloco de instru¸oes, como no caso do ciclo while, o R socorre-se de outras c˜ instru¸˜es que permitem parar a execu¸˜o de um processo iterativo. Em concreto a co caSa´ de um ır instru¸˜o break se executada dentro do ciclo faz o R terminar a repeti¸˜o da execu¸˜o ca ca cabloco/ciclo do bloco de instru¸˜es. Mais uma vez, para evitar ciclos “infinitos” convir´ garantir que co a tal instru¸˜es ´ pass´ de ser executada no bloco de instru¸˜es que forma o corpo do co e ıvel co ciclo. Vejamos um pequeno exemplo que lˆ frases introduzidas pelo utilizador at´ este e e introduzir uma frase vazia, texto <- c() repeat { cat(Introduza uma frase ? (frase vazia termina) ) fr <- readLines(n=1) if (fr == ) break else texto <- c(texto,fr) } 10 Se por acaso isso lhe acontecer, pode pressionar a tecla Esc para fazer o R abortar a computa¸˜o do ca ciclo.
    • 3.2 Estruturas de Controlo da Linguagem R 49 Conforme dever´ ser ´bvio, este ciclo s´ ir´ terminar quando a vari´vel fr, que cont´m a o o a a ea frase que o utilizador acabou de introduzir, fˆr vazia. Se tal n˜o acontecer, a instru¸˜o o a cabreak n˜o ´ executada e como tal o ciclo ´ repetido, ou seja nova frase ´ pedida. a e e e O pr´ximo exemplo ilustra o uso de outra instru¸˜o que pode ser usada para controlar o cao que ´ feito num ciclo, a instru¸˜o next, e ca Avan¸ar para a c pr´xima itera¸˜o o carepeat { cat(Introduza um nro positivo ? (zero termina) ) nro <- scan(n=1) if (nro < 0) next if (nro == 0) break pos <- c(pos,nro)} Neste exemplo pretende-se ler um conjunto de n´meros positivos que s˜o coleccionados u anum vector. O utilizador dever´ introduzir o n´mero zero para terminar o ciclo. No caso a ude o utilizador introduzir um n´mero negativo, pretende-se pedir novo n´mero sem que u uo n´mero negativo seja acrescentado ao vector com os n´meros lidos. Conseguimos esse u uefeito com a instru¸˜o next. Quando o R encontra esta instru¸˜o, salta imediatamente ca capara o in´ do ciclo que esteja a executar, n˜o executando portanto qualquer instru¸˜o ıcio a caque viesse a seguir ao next dentro do ciclo. Finalmente o R tem ainda a instru¸˜o for que permite controlar o n´mero de vezes ca u O ciclo forque um ciclo ´ executado atrav´s de uma vari´vel de controlo que vai tomar uma s´rie e e a ede valores pr´-definidos em cada itera¸ao do ciclo. A sua sintaxe gen´rica ´, e c˜ e efor(<var> in <conjunto>) <bloco de instru¸~es> co Vejamos um pequeno exemplo de utiliza¸˜o destes ciclos, ca> x <- rnorm(10)> k <- 0> for (v in x) {+ if (v > 0)+ y <- v+ else y <- 0+ k <- k + y+ } Este pequeno ciclo come¸a por obter 10 n´mero aleat´rios de uma distribui¸˜o normal, c u o cae depois obt´m a soma daqueles que s˜o positivos. Para isso ´ usado um ciclo for em e a eque a vari´vel de controlo, neste caso chamada v, vai tomar, em cada itera¸˜o, um dos a cavalores do conjunto x, isto ´ os 10 n´meros sorteados. Isto quer dizer que na primeira e uitera¸˜o o valor de v ´ igual a x[1], na segunda ´ igual a x[2] e assim sucessivamente ca e epara todos os elementos de x. Note que este ´ um simples exemplo ilustrativo do uso do efor, uma vez que em termos de estilo de programa¸˜o “` R” a solu¸˜o para este problema ca a capoderia ser obtida de forma muito mais simples, sem recurso a qualquer ciclo,> k <- sum(x[x > 0]) Note-se ainda que esta segunda forma seria muito mais eficiente em termos de tempo Eficiˆncia dos ciclos ede execu¸˜o, embora para um vector com este tamanho a diferen¸a seja irrelevante. ca cO mesmo j´ n˜o se poder´ dizer para vectores maiores como se pode constatar nesta a a apequena experiˆncia, e> x <- rnorm(1e+05)> t <- Sys.time()> k <- 0
    • 50 3 ¸˜ PROGRAMACAO EM R > for (v in x) { + if (v > 0) + y <- v + else y <- 0 + k <- k + y + } > Sys.time() - t Time difference of 3.188 secs > t <- Sys.time() > k <- sum(x[x > 0]) > Sys.time() - t Time difference of 0.07799983 secsTempos de execu¸˜o ca A fun¸˜o Sys.time() permite-nos aceder ao rel´gio do computador, conseguindo ca o dessa forma temporizar a execu¸˜o de uma parte do nosso c´digo como vemos no exemplo. ca o O que tamb´m podemos ver ´ a diferen¸a muito significativa dos tempos de execu¸˜o e e c ca envolvendo o ciclo for e sem esse ciclo. Ou seja para obter o mesmo resultado demoramos cerca de 30 vezes mais! De facto, uma li¸˜o a aprender deste pequeno exemplo ´ que os ca e ciclos s˜o estruturas computacionalmente pesadas na linguagem R 11 e que muitas vezes a os podemos evitar usando a vectoriza¸˜o das opera¸˜es que o R disponibiliza. ca co 3.2.3 Evitando ciclos O R possui, como a maioria das linguagens, objectos que permitem armazenar conjuntos de valores (p. ex. vectores, matrizes, etc.). Existem in´meros problemas onde para os u resolver, precisamos de percorrer todos os elementos desses objectos. Na maioria das linguagens isso faz-se com o recurso a ciclos. No R, temos felizmentes v´rias alternativas a bastante mais pr´ticas e sint´ticas, para al´m de muito mais eficientes como vimos no a e e ultimo exemplo da sec¸˜o anterior. ´ caM´todos para evitar e Uma das formas mais comuns de evitar os ciclos consiste em tirar partido do factociclos de muitas fun¸˜es do R serem vectoriz´veis. Por exemplo, se pretendemos sumar todos co a os elementos de uma matriz m em vez de andarmos a percorrˆ-los, usando para isso e dois ciclos for aninhados um dentro do outro (para permitir percorrer todas as colunas, para cada linha), como ´ comum em muitas lingaugens de programa¸˜o, em R podemos e ca simplesmente fazer s <- sum(m). Compare a simplicidade disto com a vers˜o dos ciclos, a > m <- matrix(rnorm(10), 5, 2) > s <- 0 > for (c in 1:ncol(m)) for (l in 1:nrow(m)) s <- s + m[l, c] Para al´m da maior simplicidade nunca ´ demais real¸ar que a vers˜o com ciclos de- e e c a morar consideravelmente mais tempo a ser executada, o que pode ser critico em matrizes muito grandes. O R tem ainda outras fun¸˜es que podem ser explicitamente usadas para vectorizar co opera¸˜es. Suponhamos que pretendemos saber o valor m´ co ınimo de cada coluna de uma matriz. No fundo o que pretendemos ´ aplicar a fun¸˜o min() a cada uma das colunas da e caA fun¸˜o apply ca matriz. Em R podemos implementar essa ideia atrav´s da fun¸˜o apply(), como vemos e ca em seguida, > m <- matrix(rnorm(100), 10, 10) > apply(m, 2, min) [1] -0.2740504 -1.4357644 -2.3413347 -1.7631999 -1.8275833 -1.5714361 [7] -1.3689081 -0.9579934 -2.9972401 -0.4734547 11 Note-se no entanto que isto tem vindo a melhorar de forma significativa nas vers˜es mais recentes. o
    • 3.2 Estruturas de Controlo da Linguagem R 51 A fun¸˜o apply() permite-nos aplicar uma qualquer fun¸˜o a uma das dimens˜es ca ca ode uma matriz ou array. Neste caso estamos a aplicar a fun¸˜o min() ` 2ª dimens˜o ca a a(as colunas) da matriz m. O resultado ´ um vector de n´meros, os m´ e u ınimos de cadacoluna. Se pretendessemos o mesmo resultado sobre as linhas bastaria colocar um 1 nosegundo argumento da fun¸˜o, indicando desta forma que a fun¸˜o deveria ser aplicada ca ca` 1ª dimens˜o do objecto.12a a A fun¸˜oo tapply() permite executar opera¸˜es semelhantes mas em sub-grupos dos ca co A fun¸˜o tapply cadados, determinados por valores de factores. Vejamos um exemplo usando um conjuntode dados que vem com o R para efeitos ilustrativos,> data(warpbreaks)> head(warpbreaks) breaks wool tension1 26 A L2 30 A L3 54 A L4 25 A L5 70 A L6 52 A L> tapply(warpbreaks$breaks, warpbreaks[, -1], sum) tensionwool L M H A 401 216 221 B 254 259 169 Como vemos o conjunto de dados warpbreaks possui 2 colunas que s˜o factores a(wool e tension). A chamada ` fun¸˜o tapply() calcula a soma da coluna breaks a cadeste conjunto de dados, mas para todos os sub-grupos formados pelas combina¸˜es dos covalores dos dois factores. Assim por exemplo, 401 ´ a soma do valor de breaks para as elinhas do conjunto de dados onde wool tem o valor A e tension o valor L. Uma outra fun¸˜o interessante ´ a fun¸˜o sapply(), que permite aplicar uma fun¸˜o ca e ca ca A fun¸˜o sapply caa todos os elementos de um vector ou lista. Vejamos dois exemplos ilustrativos,> x <- sample(10)> sapply(x, function(y) (y - mean(x))/sd(x)) [1] 1.1560120 -0.8257228 0.8257228 0.4954337 -0.1651446 1.4863011 [7] -1.1560120 0.1651446 -0.4954337 -1.4863011> l <- list(f1 = sample(20), f2 = c(2.3, 1.3, 4.5, 2.4), f3 = rnorm(100))> sapply(l, quantile) f1 f2 f30% 1.00 1.300 -3.245352025% 5.75 2.050 -0.601143250% 10.50 2.350 0.154580975% 15.25 2.925 0.6604947100% 20.00 4.500 2.3431545 No primeiro exemplo, aplicamos uma fun¸˜o a um vector. Note, que a fun¸˜o n˜o ca ca anecessita de existir no R e pode mesmo ser definida na pr´pria chamada ao sapply(), ocomo ´ o caso deste exemplo. Esta fun¸˜o pode ser vista como tempor´ria, uma vez e ca aque s´ existe durante a execu¸˜o do sapply(). No segundo exemplo, vemos a fun¸˜o o ca caquartile() a ser aplicada a uma lista. Disto resultada a aplica¸˜o a cada elemento da calista, originado neste caso uma matriz de resultados, com nomes apropriados aos mesmos. Para finalizar diga-se que a fun¸˜o sapply() ´ uma vers˜o amig´vel da fun¸˜o ca e a a calapply(), cuja ajuda pode ser consultada para mais informa¸˜es. co 12 Na realidade o segundo argumento da fun¸˜o pode ser um vector de dimens˜es, mas esse tipo de ca outiliza¸˜o sai fora do ˆmbito deste texto. ca a
    • 52 3 ¸˜ PROGRAMACAO EM R 3.3 Fun¸oes c˜ Na linguagem R as fun¸˜es s˜o tamb´m objectos e podem ser manipuladas de forma co a e semelhante aos outros objectos que estudamos at´ agora. Uma fun¸˜o tem trˆs caracte- e ca e r´ ısticas principais: uma lista de argumentos, o corpo da fun¸˜o e o ambiente onde ela ´ ca e definida. A lista de argumentos ´ uma lista de s´ e ımbolos (os argumentos) separada por v´ ırgulas, que podem ter valores por defeito. Existe ainda a possibilidade de um argu- mento ser o conjunto de caracteres “...”, cujo significado iremos descrever mais ` frente. a O corpo de uma fun¸˜o ´ formado por um conjunto de instru¸˜es da linguagem R, sendo ca e co que normalmente ´ um bloco de instru¸˜es. Quanto ao ambiente da fun¸˜o, trata-se do e co ca ambiente activo quando ela foi criada e isso determina que tipo de objectos s˜o vis´ a ıveis pela fun¸˜o conforme vermos mais ` frente. ca a 3.3.1 Criar fun¸˜es co A cria¸˜o de uma fun¸˜o consiste na atribui¸˜o do conte´do de uma fun¸˜o a um nome, ca ca ca u caCriar fun¸˜es co como qualquer outro objecto do R. Esse conte´do ´ a lista dos seus argumentos e as u e instru¸˜o que formam o corpo da fun¸˜o. Vejamos um exemplo simples de uma fun¸˜o ca ca ca que recebe como argumento uma temperatura em graus Celsius e a converte para graus Fahrenheit, > cel2far <- function(cel) { + res <- 9/5 * cel + 32 + res + } > cel2far(27.4) [1] 81.32 > cel2far(c(0, -34.2, 35.6, 43.2)) [1] 32.00 -29.56 96.08 109.76 Note como, tirando partido da vectoriza¸˜o das opera¸˜es aritm´ticas do R (c.f. Sec- ca co e ca ¸˜o 2.3), podemos usar a nossa fun¸˜o com um vector de n´meros como argumento e ca u n˜o s´ com um unico valor de temperatura. Repare ainda que o corpo desta fun¸˜o est´ a o ´ ca a desnecessariamente complexo, podendo n´s em alternativa definir a fun¸˜o como, o ca > cel2far <- function(cel) 9/5 * cel + 32 Em resumo, a cria¸˜o de uma fun¸˜o ´ uma atribui¸˜o com a forma gen´rica, ca ca e ca e <nome da fun¸~o> <- function(<lista de argumentos>) <corpo da fun¸~o> ca caValor retornado O valor retornado como resultado da fun¸˜o ´ o resultado da ultima computa¸˜o ca e ´ ca efectuada na fun¸˜o. No exemplo acima essa ultima computa¸˜o ´ o conte´do do objecto ca ´ ca e u res e portanto esse ´ o resultado da fun¸˜o. Existe uma fun¸˜o espec´ e ca ca ıfica, a fun¸˜o ca return(), que permite retornar um determinado valor numa fun¸˜o. Isso quer dizer que ca essa fun¸˜o se executada no corpo de uma fun¸˜o vai fazer com que a execu¸˜o da mesma ca ca ca termine a´ imediatamente. Vejamos um exemplo, ı > calculo <- function(x) { + if (x < 0) + return(NULL) + y <- 34 * sqrt(x)/5.2 + y + } Se esta fun¸˜o for chamada com um n´mero negativo a condi¸˜o do if ´ verdadeira e ca u ca e portanto a fun¸˜o return ´ executada. O seu efeito ´ terminar imediatamente a execu¸˜o ca e e ca da fun¸˜o calculo, e retornar o valor NULL como resultado dessa execu¸˜o. Se a fun¸˜o ca ca ca fˆr chamada com um n´mero n˜o negativo, ent˜o a execu¸˜o segue o curso normal sendo o u a a ca nesse caso o conte´do do objecto y que ´ retornado como resultado da fun¸˜o. u e ca
    • 3.3 Fun¸˜es co 533.3.2 Ambientes e “scope” de vari´veis aQuando come¸amos a nossa interac¸˜o com o R, por exemplo criando novos objectos c ca(vectores, matrizes, fun¸˜es, etc.), estamos a fazˆ-lo num ambiente chamado o workspace, co eou o ambiente de topo. Sempre que fazemos ls() por exemplo, para saber os objectos Workspaceque temos na mem´ria, o que obtemos ´ a lista de objectos neste ambiente de topo. o eComo vamos ver, existem situa¸˜es que levam ` cria¸˜o de novos ambientes, levando a co a cauma hierarquia de ambientes com a forma de uma ´rvore invertida, aninhados uns nos aoutros, at´ ao ambiente de topo. A importˆncia destas no¸˜es reside nas regras de “scope” e a coou visibilidade dos objectos em R que dependem do ambiente em que eles s˜o definidos. a Scoping Quando criamos uma fun¸˜o ela, como objecto que ´, fica associada ao ambiente onde ca efoi criada. Este ´ normalmente o ambiente de topo, o tal workspace do R. No entanto, equando chamamos essa fun¸˜o o R vai execut´-la num novo ambiente “por baixo” do ca aambiente onde ela ´ chamada. Quer isto dizer que o ambiente onde s˜o executadas as e ainstru¸˜es que formam o corpo de uma fun¸˜o n˜o ´ o mesmo ambiente onde a fun¸˜o co ca a e ca´ chamada. Isto tem impacto nos objectos que s˜o vis´e a ıveis em cada um destes doisambientes, o ambiente de onde chamamos a fun¸˜o, e o ambiente onde as instru¸˜es ca coda fun¸˜o s˜o executadas (que est´ em baixo do primeiro em termos da hierarquia de ca a aambientes do R). Vejamos um exemplo das implica¸˜es e importˆncia desta informa¸˜o. co a caConsideremos o seguinte c´digo, que inclui a defini¸˜o de uma fun¸˜o, e que assumimos o ca caser introduzido no ambiente de topo,> x <- 2> z <- 56.3> f <- function(x) {+ a <- 34+ y <- x / 4 * a * z+ y+ }> f(21)[1] 10049.55> aError: Object "a" not found Este pequeno exemplo ilustra v´rias quest˜es importantes ligadas ` quest˜o dos am- a o a abientes e tamb´m do “scope” ou visibilidade das vari´veis. Analisemos cada uma delas. e aO objecto a, por exemplo, ´ criado dentro da fun¸˜o f, ou seja a instru¸˜o de atribui¸˜o e ca ca caque cria o objecto a, ´ executada no ambiente da fun¸˜o f que ´ diferente do ambiente e ca ede topo, concretamente est´ abaixo deste. Essa ´ a raz˜o pela qual, quando no ambiente a e ade topo, pedimos o conte´do do objecto a, obtemos um erro, indicando que n˜o foi en- u acontrado nenhum objecto com esse nome. O erro tem l´gica uma vez que no ambiente ode topo n˜o existe de facto, qualquer objecto com o nome a. Por outro lado, se anten- atarmos de novo no c´digo da fun¸˜o, verificaremos que existe uma atribui¸˜o que usa o o ca caobjecto z, objecto esse que n˜o existe no ambiente da fun¸˜o f. No entanto, ele existe no a caambiente acima deste na hierarquia de ambientes. E isto leva-nos ` regra fundamental ada avalia¸˜o de instru¸˜es na linguagem R, relativamente ` visibilidade do objectos. Esta ca co aregra, conhecida por lexical scoping, diz-nos que: A regra de lexical scoping Quando um objecto ´ necess´rio numa avalia¸˜o, ele ´ procurado pelo R no e a ca e ambiente em que foi pedido. Caso seja encontrado um objecto com esse nome nesse ambiente, ele ´ usado. Caso tal n˜o aconte¸a o R procura-o no ambiente e a c acima, e assim sucessivamente at´ ao ambiente de topo. Se neste processo for e encontrado um objecto com esse nome ele ´ usado. De contr´rio o R d´ um e a a erro dizendo que tal objecto n˜o existe. a Assim, no ambiente da execu¸˜o da fun¸˜o f, o objecto z n˜o existe, no entanto, ca ca ano ambiente acima, o ambiente de topo, existe um objecto com o nome z e por isso oseu valor (56.3), ´ usado na atribui¸˜o dentro da fun¸˜o f. Por outro lado, na mesma e ca ca
    • 54 3 ¸˜ PROGRAMACAO EM R instru¸˜o de atribui¸˜o dentro da fun¸˜o f, ´ referido um objecto com o nome x. O valor ca ca ca e que ´ usado ´ o valor do objecto com esse nome que existe na pr´pria fun¸˜o (que por e e o ca sinal ´ o seu unico argumento), e n˜o o valor do objecto com o nome x que existe no e ´ a ambiente de topo. Assim, no exemplo de chamada da fun¸˜o mostrado acima, o valor de ca x usado na atribui¸˜o ´ o valor 21 e n˜o o valor 2. ca e a Estas s˜o provavelmente as no¸˜es principais ligadas a ambientes e “scoping” da lin- a co guagem R. No entanto, existe muito mais por detr´s destas importantes no¸˜es, como a co por exemplo fun¸˜es espec´ co ıficas para lidar com ambientes, ou para aceder a objectos em ambientes espec´ ıficos. Tais assuntos saem no entanto fora do ˆmbito deste texto. O a leitor interessado poder´ consultar por exemplo o livro S Programming por Venables and a Ripley (2000). 3.3.3 Argumentos de fun¸˜es co Quando criamos uma fun¸˜o indicamos normalmente a sua lista de argumentos. Nesta ca altura a linguagem R permite-nos tamb´m explicitar, caso queiramos, um valor por defeito eValores por defeito para cada um desses argumentos. O uso desta facilidade, vai permitir ao utilizador das nossas fun¸˜es, evitar incluir um valor para esses argumentos caso pretenda usar o valor co por defeito. Isto ´ particularmente util em fun¸˜es com muitos argumentos, alguns dos e ´ co quais s´ usados em situa¸˜es muito particulares, sendo que os seus valores por defeito o co fazem sentido na maioria das utiliza¸˜es dessas fun¸˜es. Por exemplo, a fun¸˜o mean() co co ca serve para calcular a m´dia dos valores que lhe s˜o fornecidos, e a > mean(c(21, 45.3, 342.4, 54.3, 65.3, 1000.2)) [1] 254.75 A maioria das vezes iremos usar esta fun¸˜o deste modo. No entanto, se consultarmos ca a ajuda desta fun¸˜o iremos observar que ela tem outros dois argumentos, trim e na.rm, caValores por defeito cada um deles com um valor por defeito, 0 e FALSE, respectivamente. O facto de eles terem um valor por defeito permite-nos fazer chamadas ` fun¸˜o como a apresentada em a ca cima, sem que obtenhamos um erro por n˜o termos indicado o valor destes argumentos. a Ao n˜o indicarmos estes valores o R vai assumir os valores por defeito indicados pelo a criador da fun¸˜o nos c´lculos executados dentro da mesma. Se n˜o pretendessemos usar ca a a estes valores, teriamos que o explicitar na chamada ` fun¸˜o, como no exemplo a seguir, a ca > mean(c(21, 45.3, 342.4, 54.3, 65.3, 1000.2), trim = 0.2) [1] 126.825 Use a ajuda da fun¸˜o para ver se entende o que foi calculado com este valor do ca parˆmetro trim. a Em resumo, ao criarmos uma fun¸˜o podemos indicar valores por defeito para alguns ca dos seus parˆmetros, bastanto para isso usar o sinal igual seguido do valor ` frente do a a nome do argumento, conforme ilustrado neste pequeno exemplo, > valor.central <- function(x, estat = "mean") { + if (estat == "mean") + return(mean(x)) + else if (estat == "median") + return(median(x)) + else return(NULL) + } > x <- rnorm(10) > valor.central(x) [1] 0.4182037 > valor.central(x, estat = "median")
    • 3.3 Fun¸˜es co 55 [1] 0.4513049umero vari´vel de´ a Uma outra facilidade bastante conveniente da linguagem R ´ a possibilidade de criar erˆmetros a fun¸˜es com n´mero vari´vel de parˆmetros. Isso ´ conseguido por um parˆmetro especial co u a a e a que ´ indicado por “...”. Este parˆmetro especial ´ de facto uma lista que pode agregar e a e um n´mero qualquer de parˆmetros usados na chamada da fun¸˜o. Uma utiliza¸˜o u a ca ca frequente desta facilidade ´ na cria¸˜o de fun¸˜es que chamam outras fun¸˜es e ao fazˆ- e ca co co e lo pretendem passar-lhes parˆmetros que s´ a elas lhes interessam. Por exemplo, no a o exemplo da fun¸˜o valor.central mostrada acima, n˜o previmos a possibilidade de o ca a utilizador ao calcular o valor central usando a fun¸˜o mean() pretender fazˆ-lo usando ca e um m´dia truncada dos 20% valores extremos. Tal ´ poss´ atrav´s do parˆmetro trim e e ıvel e a da fun¸˜o mean(), mas da forma como criamos a fun¸˜o valor.central(), o utilizador ca ca n˜o tem forma de usar a fun¸˜o mean deste modo. Do mesmo modo a fun¸˜o median(), a ca ca que tamb´m pode ser chamada da fun¸ao que criamos, tamb´m tem parˆmetros pr´prios e c˜ e a o que s˜o inacess´ a ıveis ao utilizador da nossa fun¸˜o. Uma forma de dar a volta a este ca problema reside exactamente na utiliza¸˜o do parˆmetro “...”, como vemos nesta defini¸˜o ca a ca alternativa de valor.central(), > valor.central <- function(x, estat = "mean", ...) { + if (estat == "mean") + return(mean(x, ...)) + else if (estat == "median") + return(median(x, ...)) + else return(NULL) + } > x <- rnorm(10) > valor.central(x) [1] 0.1530552 > valor.central(x, trim = 0.2) [1] 0.2216488 > valor.central(x, estat = "median", na.rm = T) [1] 0.1385397 Desta forma, tudo o que n˜o sejam parˆmetros espec´ a a ıficos da fun¸˜o valor.central() ca s˜o agregados no tal parˆmetro especial “...”, que por sua vez ´ passado para as chama- a a e das das fun¸˜es mean e median, com qualquer que seja o seu conte´do. Desta forma co u conseguimos, por exemplo, obter um valor central calculado com a fun¸˜o mean(), mas ca que seja uma m´dia truncada dos 20% valores extremos, como vemos no exemplo acima. e Existem ainda outras utiliza¸˜es deste parˆmetro especial, mas mais uma vez est˜o co a a fora do ˆmbito deste texto, pelo que o leitor interessado dever´ consultar bibliografia a a mais avan¸ada sobre a linguagem R. c Para al´m das quest˜es ligadas aos parˆmetros formais (os parˆmetros usados na e o a a Parˆmetros formais a defini¸˜o da fun¸˜o), que descrevemos at´ agora, existem ainda quest˜es ligadas aos ca ca e o e actuais parˆmetros actuais (os usados nas chamadas `s fun¸˜es), que agora detalhamos. a a co Em particular, como j´ vem acontecendo em diversos exemplos fornecidos ao longo a deste texto, existem duas formas de indicar os valores dos parˆmetros com os quais a pretendemos chamar uma qualquer fun¸˜o: atrav´s de posi¸˜o, ou por nome. ca e ca Uma chamada por posi¸˜o ocorre quando pretendemos que o valor indicado na posi- ca ca ¸˜o x da lista de argumentos da fun¸˜o seja associado ao argumento formal na mesma ca posi¸˜o. Por exemplo, ao executar seq(10,23) o R vai assumir que o valor 10 ´ para ca e ser atribu´ ao primeiro argumento formal da fun¸˜o seq() (o argumento from no caso, ıdo ca conforme pode confirma na ajuda da fun¸˜o), e o valor 23 no segundo argumento formal ca (o argumento to). Isto leva a obter uma sequˆncia de n´meros de 10 a 23, de 1 em 1. e u
    • 56 3 ¸˜ PROGRAMACAO EM R J´ a chamada seq(10,length=23) tem um resultado completmente diferente, uma vez a que o segundo valor ´ indicado por nome e n˜o por posi¸˜o como no exemplo anterior. e a ca Isto quer dizer que o n´mero 23 n˜o ´ atribu´ ao argumento na segunda posi¸˜o, como u a e ıdo ca anteriormente, mas sim ao argumento formal com o nome length. A utiliza¸˜o da chamada por nome, al´m de mais clara, ´ por vezes indispens´vel, ca e e a nomeadamente em fun¸˜es com muitos argumentos, a maioria com valores por defeito, co em que o utilizador pretende usar um valor diferente num dos argumentos do fim da lista de argumentos formais. Sem esta facilidade o utilizador iria ter que “preencher” todos os outros argumentos at´ “chegar” ao argumento que pretende alterar. Com a chamada e por nome, basta-lhe proceder como vimos no exemplo de cima, indicando o nome do argumento formal e o valor que pretende usar. 3.3.4 Lazy evaluation Conforme j´ foi mencionado na Sec¸˜o 3.3.2, sempre que ´ chamada uma fun¸˜o o R cria a ca e ca um novo ambiente por baixo do ambiente onde a chamda foi efectuada. Nessa altura as express˜es dos argumentos actuais s˜o verificadas sintaticamente, mas n˜o s˜o avaliadas. o a a aO que ´ a lazy e A este procedimento chama-se lazy evaluation. Os argumentos actuais s´ s˜o avaliados o aevaluation? quando s˜o necess´rios pela primeira vez no corpo da fun¸˜o. Esta regra pode ter por a a ca vezes implica¸˜es inexperadas conforme ilustrado nestes pequenos exemplos: co > f1 <- function(a1, a2 = sqrt(a1)) { + a1 <- a1^2 + a2 + } > f1(4) [1] 4 > f2 <- function(a1, a2 = sqrt(a1)) { + z <- a2/a1 + a1 <- a1^2 + a2 + } > f2(4) [1] 2 Na primeira fun¸˜o, embora o argumento a2 seja definido com uma valor por defeito ca igual ` ra´ quadrada do primeiro argumento, quando chamamos a fun¸˜o com o valor a ız ca 4, poder´ ıamos estar ` espera que o argumento a2 (que por sinal ´ o valor retornado pela a e fun¸˜o), tomasse o valor 2. Todavia, devido ` lazy evaluation, a express˜o sqrt(a1) s´ ´ ca a a oe calculada quando necess´rio no corpo da fun¸˜o, e isso s´ acontece na ultima instru¸˜o. a ca o ´ ca Acontece que nessa altura a1 j´ n˜o ´ 4 mas sim 16, devido ` primeira instru¸˜o do corpo a a e a ca da fun¸˜o, e portanto sqrt(a1) vai dar 4 e n˜o 2 como poder´ ca a ıamos esperar. J´ na segunda fun¸˜o, porque a2 ´ necess´rio na primeira instru¸˜o, logo a´ ´ iniciali- a ca e a ca ıe zado com o valor sqrt(a1), que nessa altura ´ igual a 2. Da´ o resultado diferente desta e ı segunda fun¸˜o. ca 3.3.5 Algumas fun¸˜es uteis co ´ O R possui uma enorme quantidade de fun¸˜es. Nesta sec¸˜o apresentamos uma brev´ co ca ıs- sima resenha de algumas fun¸˜es uteis, agrupadas pelo seu tipo de funcionalidade. Esta co ´ lista est´ obviamente muito longe de ser exaustiva. a Algumas estat´ ısticas b´sicas a
    • 3.3 Fun¸˜es co 57 sum(x) Soma dos elementos do vector x. max(x) M´ximo dos elementos de x. a min(x) M´ınimo dos elementos de x. which.max(x) O´ ındice do maior valor em x. which.min(x) O´ ındice do menor valor em x. range(x) O range de valores em x (produz o mesmo re- sultado que c(min(x),max(x))). length(x) O n´mero de elementos em x. u mean(x) A m´dia dos valores em x. e median(x) A mediana dos valores em x. sd(x) O desvio padr˜o dos elementos em x. a var(x) A variˆncia dos elementos em x. a quantile(x) Os quartis de x. scale(x) Normaliza os elementos em x, i.e. subtrai a m´dia e divide pelo desvio-padr˜o, resul- e a tando num vector de n´meros com m´dia zero u e e desvio-padr˜o unit´rio. Tamb´m funciona a a e com data frames (s´ as colunas num´ricas, ob- o e viamente).Algumas opera¸˜es vectoriais e matem´ticas co a sort(x) Elementos de x ordenados. rev(x) Inverte a ordem dos elementos em x. rank(x) Faz o ranking dos elementos de x. log(x,base) Calcula o logaritmo na base “base” de todos os elementos de x. exp(x) Calcula o exponencial dos elementos de x. sqrt(x) Raiz quadrada dos elementos de x. abs(x) Valor absoluto dos elementos de x. round(x,n) Arredonda os valores em x para n casas deci- mais. cumsum(x) Obt´m um vector em que o elemento i ´ a e e soma dos elementos x[1] at´ x[i]. e cumprod(x) O mesmo para o produto. match(x,s) Obt´m um vector com o mesmo tamanho de x, e contendo os elementos de x que pertencem a s. Os elementos que n˜o pertencem a s aparecem a no resultado assinalados com o valor NA. union(x,y) Obt´m um vector com a uni˜o dos vectores x e a e y. intersect(x,y) Obt´m um vector com a intersec¸˜o dos vec- e ca tores x e y. setdiff(x,y) Obt´m um vector resultante de retirar os ele- e mentos de y do vector x. is.element(x,y) Retorna o valor TRUE se x est´ contido no a vector y. choose(n,k) Calcula o n´mero de combina¸˜es k, n a n. u co´Algebra Matricial
    • 58 3 ¸˜ PROGRAMACAO EM R diag(x,nrow,ncol) Constr´i uma matriz diagonal com nrow linhas o e ncol colunas, usando o n´mero x. Tam- u b´m pode ser usada para extrair ou substituir e os elementos na diagonal de uma matriz (ver exemplos fazendo “? diag”). t(x) A matriz transposta de x. nrow(x) N´mero de linhas de x. u ncol(x) N´mero de colunas de x. u A %*% B Multiplica¸˜o matricial de A por B. ca solve(A,b) Resolve o sistema de equa¸˜es lineares Ax = b. co Com um unico argumento (uma matriz) (e.g. ´ solve(A)) calcula a sua inversa. qr(x) Decomposi¸˜o QR da matriz x. ca svd(x) Decomposi¸˜o SVD (singular value decompo- ca sition) da matriz x. eigen(x) Valores e vectores pr´prios da matriz qua- o drada x. det(x) O determinante da matriz quadrada x.3.4 Objectos, Classes e M´todos eEsta sec¸˜o inclui informa¸˜o que sai um pouco fora do ˆmbito introdut´rio deste texto. ca ca a oDe facto, existe muito para dizer sobre estes t´picos no contexto da linguagem R. Todavia, omesmo tratando-se de uma introdu¸˜o, h´ quest˜es relacionadas com estes t´picos que ca a o oqualquer utilizador do R deve conhecer. A maioria dos objectos que vimos at´ agora tem uma estrutura relativamente sim- eples. Todavia, ´ poss´ em R constru´ novos tipos (classes) de objectos, usando estes e ıvel ırtipos elementares que temos vindo a descrever. Por exemplo, existem fun¸˜es em R que coretornam como resultado um modelo de um conjunto de dados (por exemplo uma redeneuronal). Tal objecto tem uma complexidade bem maior do que os que estudamos at´ eagora, n˜o deixando no entanto de ser um objecto como outro qualquer do ponto de vista ado R. Isto quer dizer que por exemplo pode fazer sentido perguntar ao R qual o conte´do udeste objecto complexo. Para tal ser poss´ ıvel, e de forma transparente para o utilizador,´ conveniente que a pessoa que decidiu criar tais objectos complexos, indique tamb´m aoe eR como mostr´-los ao utilizador. Traduzido de outro modo, o utilizador dever´ indicar a aao R um m´todo para mostrar um objecto da classe que acabou de criar. e Muita desta aparente complexidade, pode ser “escondida” do utilizador comum. Porexemplo, a fun¸˜o summary() produz um sum´rio do conte´do do objecto que lhe ´ ca a u efornecido como argumento. O significado deste sum´rio, bem como a forma como ele ´ a eobtido, est´ em grande parte dependente do tipo de objecto de que queremos o sum´rio. a aNo entanto o utilizador n˜o precisa de saber isso. Vejamos um exemplo concreto deste acomportamento,> x <- rnorm(10)> summary(x) Min. 1st Qu. Median Mean 3rd Qu. Max.-1.3790 -0.2195 -0.1066 0.1157 0.8568 1.3760> summary(matrix(x, 5, 2)) V1 V2 Min. :-0.6689 Min. :-1.37895 1st Qu.:-0.1069 1st Qu.:-0.25349 Median :-0.1062 Median :-0.11738 Mean : 0.3167 Mean :-0.08521 3rd Qu.: 1.0894 3rd Qu.: 0.15905 Max. : 1.3758 Max. : 1.16472
    • 3.4 Objectos, Classes e M´todos e 59 Repare como duas chamadas ` mesma fun¸˜o (na realidade s´ aparentemente a mesma a ca ocomo veremos), produzem resultados diferentes dependendo da classe do objecto dadocomo argumento, embora conceptualmente ambos sejam sum´rios desse argumento. De afacto, a fun¸˜o summary() ´ uma fun¸˜o gen´rica, que basicamente o que faz ´ ver a classe ca e ca e e Fun¸˜es gen´ricas co edo objecto que lhe ´ passado como argumento, e depois “despacha” a tarefa de produzir eo sum´rio para fun¸˜es especializadas nessa classe de objectos. Para isso, obviamente ´ a co epreciso que algu´m tenha escrito essas fun¸˜es especializadas, ou seja que algu´m tenha e co efornecido uma m´todo summary para a classe de objectos em causa (no caso do exemplo e M´todos eum vector e uma matriz). Podemos rapidamente confirmar isto que se est´ a passar “por adetr´s” da fun¸˜o summary() executando o seguinte, a ca> methods(summary) [1] summary.aov summary.aovlist summary.connection [4] summary.data.frame summary.Date summary.default [7] summary.ecdf* summary.factor summary.glm[10] summary.infl summary.lm summary.loess*[13] summary.manova summary.matrix summary.mlm[16] summary.nls* summary.packageStatus* summary.POSIXct[19] summary.POSIXlt summary.ppr* summary.prcomp*[22] summary.princomp* summary.stepfun summary.stl*[25] summary.table summary.tukeysmooth* Non-visible functions are asterisked A fun¸˜o methods() mostra a lista de m´todos (isto ´ fun¸˜es especializadas em ca e e coclasses particulares) que existem para a fun¸˜o gen´rica summary(). Podemos ver, por ca eexemplo que existe uma fun¸˜o summary.matrix(), que como o nome indica, ´ a fun¸˜o ca e causada para produzir sum´rios para objectos da classe “matrix”. a Esta caracter´ıstica da linguagem R, e das linguagens orientadas aos objectos generi-camente, ´ bastante conveniente, uma vez que permite uma interac¸˜o com o utilizador e camais transparente. A este, basta-lhe saber que a fun¸˜o summary() produz sum´rios de ca aobjectos, sejam eles de que tipo forem, n˜o necessitando por exemplo de conhecer todas aas fun¸˜es espec´ co ıficas que existem para produzir os sum´rios para cada classe de objecto. a A fun¸˜o class() permite-nos saber qual a classe de um qualquer objecto, ca Classes> x <- rnorm(10)> class(x)[1] "numeric"> class(matrix(x, 5, 2))[1] "matrix"> class(as.POSIXct("2006-9-23"))[1] "POSIXt" "POSIXct" Para criarmos uma nova classe basta-nos criar uma fun¸˜o que possa ser usada para ca Criar um nova classecriar essa classe de objectos e depois podemos escrever fun¸˜es que implementem alguns com´todos que sejam uteis para objectos dessa nova classe. e ´ Vejamos um exemplo deste processo criando uma nova classe de objectos que visearmazenar dados sobre pessoas. Para simplificar vamos assumir que um objecto daclasse “pessoa” ´ formado por um nome, os nomes dos pais, a data de nascimento e o esexo da pessoa.> pessoa <- function(n, p, d, s) {+ p <- list(nome = n, pais = p, nascimento = d, sexo = s)+ class(p) <- "pessoa"
    • 60 3 ¸˜ PROGRAMACAO EM R + p + } > chefe <- pessoa("Ana", list(pai = "Carlos", mae = "Joana"), as.Date("1970-03-3"), + "f") > class(chefe) [1] "pessoa" Repare como, depois de criar a fun¸˜o pessoa(), podemos us´-la para criar objectos ca a ´ da classe “pessoa”. E este o caso do objecto chefe que como vemos tem essa classe. Em seguida podemos ver como criar uma fun¸˜o para implementar o m´todo de ca e sumariza¸˜o de objectos da classe “pessoa”. ca > summary.pessoa <- function(p) cat("O meu nome ´ ", p$nome, " e sou ", e + ifelse(p$sexo == "f", "filha", "filho"), " de ", p$pais$pai, + " e ", p$pais$mae, " tendo nascido a ", format(p$nascimento, + "%d %b %Y"), "n") > summary(chefe) O meu nome ´ e Ana e sou filha de Carlos e Joana tendo nascido a 03 Mar 1970 Ap´s a cria¸˜o deste m´todo passamos a poder usar a fun¸˜o summary() aplicada a o ca e ca objectos da classe “pessoa”. Uma vez que criamos a fun¸˜o summary.pessoa(), quando ca chamamos summary(chefe), o R vai come¸ar por ver qual a classe do objecto chefe e, c uma vez que essa ´ “pessoa”, vai procurar uma fun¸˜o com o nome summary.pessoa(). e ca Assim, se pretendemos criar uma m´todo espec´ e ıfico para a classe “pessoa” para uma fun¸˜o gen´rica qualquer “xpto”, o que temos que fazer ´ criar a fun¸˜o “xpto.pessoa”. ca e e ca Por exemplo, se pretendessemos aplicar a fun¸˜o gen´rica plot() a objectos da classe ca e “pessoa”, precisariamos de criar uma fun¸˜o chamada plot.pessoa(). ca 3.5 Depura¸˜o de Programas em R caO que ´? e A depura¸˜o de programas em qualquer linguagem (debugging) de programa¸˜o tem ca ca como objectivo principal encontrar a fonte de erros ou comportamentos imprevistos nos programas que desenvolvemos. O R possui v´rias fun¸˜es que podem ser utilizadas para ajudar nesta tarefa. Uma a co delas ´ a fun¸˜o traceback() que permite ao utilizador obter a sequˆncia de fun¸˜es que e ca e co foram chamadas at´ o erro ocorrer. e Se tal n˜o fˆr suficiente para identificar a fonte do erro, ou ent˜o se localizamos a a o a sua poss´ origem mas n˜o entendemos o porquˆ do erro, poderemos tamb´m socorrer- ıvel a e e mo-nos da fun¸˜o browser(). Esta fun¸˜o se introduzida no c´digo de uma fun¸˜o ca ca o ca onde suspeitamos existir algo de errado, far´ com que a partir da sua posi¸˜o, todas as a ca instru¸˜es seguintes sejam executadas passo a passo e unicamente sob a nossa ordem. Ou co seja, depois de encontrar browser() o R vai parar e s´ executar´ a instru¸˜o seguinte o a ca quando n´s mandarmos, parando logo em seguida de novo. Em cada uma destas paragens o o R vai mostrar um prompt especial onde o utilizador poder´ fazer quase tudo o que a pode fazer no prompt normal do R (por exemplo ver o conte´do de objectos da fun¸˜o u ca a ser depurada), mas onde existem ainda sertos comandos especiais ligados ` fun¸˜o a ca browser(). Vejamos um pequeno exemplo deste tipo de depura¸˜o. Suponhamos que temos a ca seguinte fun¸˜o, que aparenta estar sem problemas, ca > er <- function(n,x2) { + s <- 0 + for(i in 1:n) { + s <- s + sqrt(x2) + x2 <- x2-1 + }
    • 3.5 Depura¸˜o de Programas em R ca 61+ s+ }> er(2,4)[1] 3.732051 Suponhamos agora que fazemos a seguinte chamada que inesperadamente produz umaviso sobre um erro num´rico (NaN significa Not A Number ) na execu¸˜o da fun¸˜o, e ca ca> er(3,1)[1] NaNWarning message:NaNs produced in: sqrt(x2) Vamos incluir uma chamada ` fun¸˜o browser() no corpo da fun¸˜o antes do local a ca caque suspeitamos ser a fonte do aviso. Voltamos a fazer a mesma chamada e usamos ent˜o aas facilidades da execu¸˜o passo a passo, como vemos a seguir, ca> er <- function(n,x2) {+ s <- 0+ browser()+ for(i in 1:n) {+ s <- s + sqrt(x2)+ x2 <- x2-1+ }+ s+ }> er(3,1)Called from: er(3, 1)Browse[1]> x2[1] 1Browse[1]> print(n)[1] 3Browse[1]> ndebug: for (i in 1:n) { s <- s + sqrt(x2) x2 <- x2 - 1}Browse[1]> ndebug: iBrowse[1]> iNULLBrowse[1]> ndebug: s <- s + sqrt(x2)Browse[1]> i[1] 1Browse[1]> s[1] 0Browse[1]> sqrt(x2)[1] 1Browse[1]>debug: x2 <- x2 - 1Browse[1]> s[1] 1Browse[1]>debug: iBrowse[1]> x2[1] 0Browse[1]>
    • 62 3 ¸˜ PROGRAMACAO EM Rdebug: s <- s + sqrt(x2)Browse[1]> i[1] 2Browse[1]> sqrt(x2)[1] 0Browse[1]>debug: x2 <- x2 - 1Browse[1]>debug: iBrowse[1]>debug: s <- s + sqrt(x2)Browse[1]> sqrt(x2)[1] NaNWarning message:NaNs produced in: sqrt(x2)Browse[1]> x2[1] -1Browse[1]> Q> Quando chamamos de novo a fun¸˜o o R p´ra quando encontra a instru¸˜o browser() ca a cafazendo aparecer um prompt com a forma gen´rica Browse[i]>. A partir daqui est´ nas e anossas m˜os o que pretendemos fazer. Tipicamente come¸amos por inspeccionar o valor a cdos objectos da fun¸˜o para ver se econtramos algo suspeito que possa estar a orginar o caerro. Nesta sess˜o exemplo come¸amos por interrogar o R sobre o valor dos parˆmetros, x2 a c ae n. No caso deste ultimo, repare que usamos a constru¸˜o print(n) e n˜o simplesmente ´ ca ao nome do objecto como fizemos para o x2. A explica¸˜o para isto reside no facto de neste caambiente de debugging o n seguido de Enter tem um significado especial que ´ dizer ao eR, “podes avan¸ar para a pr´xima instru¸˜o”, que foi o que fizemos a seguir. O mesmo c o caefeito pode ser conseguido carregando unicamente na tecla Enter. E por a´ continuamos ıat´ que reparamos que o erro est´ a ser originado por uma chamada sqrt(x2), e quando e aperguntamos o valor de x2 na altura da chamada que deu o erro, verificamos que ele ´ -1, ee da´ o erro uma vez que o R n˜o sabe calcular ra´ ı a ızes quadradas de n´meros negativos. uOu seja, a nossa fun¸˜o vai decrementando o valor de x2, dentro do ciclo e se este fˆr ca oexecutado bastantes vezes o x2 acabar´ por ficar negativo, em particular se fˆr inferior a oa n que ´ o par`metro que controla o n´mero de execu¸˜es do ciclo. Descoberto o erro e a u copodemos abortar este ambiente de debugging usando o comando Q. Um outro comandodeste ambiente de debugging que por vezes ´ util ´ o comando c. Se executado quando e´ eo debugger est´ dentro de um ciclo, faz com que o R deixe execute o resto das itera¸˜es a codo mesmo at´ ao fim, sem qualquer interrup¸˜o s´ voltando a aparecer o prompt no fim e ca odestas. Em vez de alterar a fun¸ao que pretendemos depurar, podemos simplesmente fazer c˜debug(er) e depois fazer a chamada problem´tica, er(3,1). A intereac¸˜o que se segue a ca´ em tudo idˆntica ` que vimos acima. Note-se que at´ fazermos undebug(er), sempree e a eque voltamos a chamar a fun¸˜o er() o R entra em modo de debugging. A vantagem cada fun¸˜o browser() em rela¸˜o a esta alternativa ´ que podemos iniciar o debugging no ca ca eponto da fun¸˜o que queremos, enquanto que com esta alternativa ele come¸a logo deste ca ca primeira instru¸˜o da fun¸ao. ca c˜
    • 634 Manipula¸˜o de Dados caO R tem v´rios objectos onde podemos armazenar diversos tipos de dados. No entanto, aconforme j´ mencionado, s˜o os data frames que se revelam como os mais adequados para a aarmazenar tabelas de dados de um problema qualquer. Na Sec¸˜o 2.10 vimos j´ o que ´ ca a eum data frame, como os criar, bem como algumas opera¸˜es essenciais para a sua mani- copula¸˜o. Nesta sec¸˜o iremos analisar mais algumas quest˜es importante para analisar ca ca odados guardados em data frames usando as potencialidades do R. Nomeadamente iremosver: como carregar dados de v´rias fontes para um data frame, como obter sum´rios das a apropriedades principais dos dados, e tamb´m t´cnicas para visualizar esses dados. e e Antes de abordarmos estes t´picos s´ uma pequena nota sobre o facto de o R ter o oj´ dispon´ a ıveis diversas tabelas de dados que poderemos usar para por exemplo testar Dados que vˆm com eas nossas capacidades com a linguagem. Al´m disso, a maioria das packages extra que e o Rvamos instalando vem tamb´m com mais conjuntos de dados para ilustrar algumas das esuas funcionalidades. Para sabermos os dados que est˜o actualmente (isto ´ com as a epackages neste momento carregadas) dispon´ ıveis, podemos fazer:> data() Como resultado ´-nos apresentada um lista com os nomes e breves descri¸˜es dos e coconjuntos de dados dispon´ ıveis. Podemos obter mais informa¸˜o sobre qualquer um cadeles, usando as fun¸˜es de ajuda aplicadas ao nome do conjunto de dados, como se de couma fun¸˜o se tratasse. ca Se pretendermos usar algum dos conjuntos de dados podemos usar a mesma fun¸˜o, ca> data(cars) O efeito disto ´ criar um data frame com o nome cars contendo este conjunto de edados.4.1 Carregar dados para o RNesta sec¸˜o iremos analisar formas de clocar em data frames, dados que se encontram caarmazenados noutras plataformas e que, pela sua dimens˜o, n˜o faz sentido introduzi-los a ade novo “` m˜o” no R. Dito de outra forma, iremos ver como importar dados para o R. a a4.1.1 De ficheiros de textoOs ficheiros de texto s˜o uma das formas mais comum de armazenar dados. Para al´m a edisso, existem ainda diversas plataformas que permitem exportar dados armazenadosnas suas estruturas pr´prias, para ficheiros de texto em formatos particulares, como por oexemplo o formato CSV. Esta ´ muitas vezes a forma mais simples de importar para o R eos dados de uma aplica¸˜o qualquer, que use um formato mais fora de vulgar. ca O formato mais comum de armazenar uma tabela de dados num ficheiro de texto Formato CSVconsiste em pˆr cada linha da tabela de dados numa linha separada do ficheiro, e fazer oseparar os valores de cada coluna de uma linha, por um qualquer caracter separador.Relativamente a este ultimo, escolhas comuns s˜o a v´ ´ a ırgula (levando ao formato CSV,Comma Separated Values)), o ponto e v´ ırgula, ou o caracter tab. A fun¸˜o principal do caR para ler este tipo de ficheiros ´ a fun¸˜o read.table(). Esta fun¸˜o tem in´meros e ca ca u A fun¸˜o read.table caparˆmetros que permitem ajustar a importa¸˜o aos detalhes particulares do formato dos a cadados no ficheiro que pretendemos carregar. Entre eles, est´ obviamente uma parˆmetro a aque permite explicitar o separador dos valores que ´ usado (o parˆmetro sep) no ficheiro. e aPor defeito, o seu valor ´ white space, que inclui um ou mais caracteres de espa¸o e tab’s. e c´E poss´ explicitar outro separador, como por exemplo a v´ ıvel ırgula. Todavia, por v´rias adestas alternativas serem muito comuns, existem outras fun¸˜es que s˜o essencialmente co aiguais ` read.table(), sendo que a diferen¸a fundamental est´ no separador por defeito a c aque ´ assumido bem como noutros pequenos detalhes relacionados com os defaults. E e ´esse o caso das fun¸˜es read.csv(), read.csv2(), read.delim() e read.delim2(). Para co
    • 64 4 ¸˜ MANIPULACAO DE DADOS ver todos os detalhes das pequenas diferen¸as entre elas aconselhamos a leitura da ajuda c dessas fun¸˜es que, pela sua semelhan¸a, est´ toda junta. co c a Vejamos um pequeno exemplo de como usarmos uma destas fun¸˜es. Suponhamos co que temos um ficheiro de texto com dados, de que mostramos as primeiras linhas, ID;Nome;Nota 434;Carlos;13.2 523;Ana;15.1 874;Susana;4.8 103;Joaquim;15.9 ... Olhando para o ficheiro com aten¸˜o poderemos reparar que os valores s˜o separados ca a por ponto e v´ ırgula, os n´meros reais usando o ponto como separador das casas decimais, u e o ficheiro inclui o nome das colunas na primeira linha. Todas estas particularidades tˆm correspondˆncia em parˆmetros das fun¸˜o de leitura que mencionamos acima. Se e e a ca pretendessemos usar a fun¸˜o read.table() para ler este ficheiro, deveriamos fazer: ca dados <- read.table(ficheiro.txt,header=T,sep=;,dec=,) O parˆmetro header permite-nos indicar se o ficheiro tem, ou n˜o, o nome das colunas a a na primeira linha de dados. O parˆmetro sep permite conforme j´ mencionado, indicar a a o separador de valores usado no ficheiro. Finalmente o parˆmetro dec permite indicar a o caracter usado como separador de casas decimais dos n´meros reais. Note-se que este u formato ´ bastante vulgar, sendo que uma das fun¸˜es mencionadas usa estes valores e co como valores por defeito, e portanto seria mais pr´tico, neste caso particular, fazer, a dados <- read.csv2(ficheiro.txt) Estas s˜o as fun¸˜es principais para ler ficheiros de texto no R. Existem ainda outras a co possibilidades, embora menos usadas, das quais destacar´ ıamos s´ a fun¸˜o read.fwf(), o caLer ficheiros muito que permite ler ficheiros que usem um formato de tamanho fixo. Deixamos ainda umagrandes breve nota sobra a leitura de ficheiros muito grandes (dezenas de milhares de linhas eLer ficheiros muito centenas de colunas). Nestas situa¸˜es, e assumindo que os dados cabem na mem´ria co ograndes do computador que se est´ a usar, as fun¸˜es do tipo read.table() poder˜o mostrar-se a co a demasiado lentas. Nestas situa¸˜es recomenda-se que se considere a utiliza¸˜o da fun¸˜o co ca ca scan(), de uso menos intuitivo, mas bastante mais eficiente em termos computacionais. 4.1.2 Da Internet Por vezes existem dados que nos interessam que est˜o acess´ a ıveis em p´ginas da Internet. a Para sabermos qual a melhor forma de os importar para o R temos que analisar com cui- dado o formato em que s˜o fornecidos. Existem aqui v´rias possibilidades. Se os dados es- a a t˜o fornecidos como um ficheiro de texto com um formato qualquer (por exemplo CSV), e a o que nos d˜o ´ o URL para esse local (por exemplo http://www.blabla.com/dados.txt), a e ent˜o a melhor forma de proceder ´ fazer o download dos dados para um ficheiro local, e a e depois proceder de alguma das formas indicadas na Sec¸˜o 4.1.1. Para fazer o download ca do ficheiro, poderemos ou abrir um browser e usar alguma op¸˜o do g´nero Save As..., ca e ou ent˜o fazer tudo “dentro” do R. Para isso poderemos usar a fun¸˜o download.file(). a ca Vejamos, > download.file(http://www.blabla.com/dados.txt,c:My Documentsdados.txt) O primeiro argumento indica o URL, e o segundo o nome do ficheiro local no nosso computador onde os dados devem ser guardados. Note que se indicar um caminho para o ficheiro, como no exemplo acima, dever´ separar o nome das pastas por dois caracteres a “” e n˜o um s´ como estaria ` espera. a o a Se o URL apontar para uma p´gina Web normal (que ´ escrita na linguagem HTML), a e n˜o ´ t˜o f´cil importar os dados para o R. Por exemplo, a p´gina poderia mostrar uma a e a a a
    • 4.1 Carregar dados para o R 65tabela, no meio de outra informa¸˜o, cujo conte´do gostariamos de importar para o R. ca uNestes casos ´ necess´rio importar toda a p´gina (em HTML) e depois interpretar o e a aconte´do dessa p´gina para da´ extra´ a informa¸˜o da tabela. Realizar essa tarefa ´ u a ı ır ca eposs´ em R, nomeadamente tirando partido de fun¸˜es existentes na package XML, ıvel comas no entanto sai fora do ˆmbito deste texto. a4.1.3 Do ExcelEm muitas organiza¸˜es ´ comum usar o Excel para armazenar tabelas de dados. Existem co ev´rias possibilidades para importar os dados para o R. Um consiste em gravar os dados ado Excel para um ficheiro CSV, com as facilidades que o Excel tem para isso, e depoisusar alguma das fun¸˜es da Sec¸˜o 4.1.1. co ca Uma outra possibilidade ´ utilizar a fun¸˜o read.xls() dispon´ na package gdata. e ca ıvelEsta fun¸˜o permite explicitar o nome da folha de c´lculo e o n´mero da worksheet ca a ucontendo os dados que pretendemos importar,dados <- read.xls(dados.xls, sheet=3) Finalmente, ´ poss´ usar o clipboard do Windows 13 , para fazer a importa¸˜o dos e ıvel cadados. Em concreto, podemos seleccionar a tabela de dados no Excel, fazer Edit+Copy,e depois, j´ no R, fazer: adados <-4.1.4 De bases de dadosAs bases de dados s˜o as infraestruturas por excelˆncia para armazenar dados, particu- a elarmente quando de grande dimens˜o, no contexto das organiza¸˜es. Neste contexto, n˜o a co aser´ surpreendente descobrir que o R tem v´rias facilidades para fazer o interface com a aeste tipo de software, tanto para importar dados como para exportar dados do R parauma base de dados. O R tem uma package chamada DBI que implementa uma s´rie de fun¸˜es de interface e cocom bases de dados. Estas fun¸˜es s˜o independentes do sistema de gest˜o de bases de co a adados (SGBD) que estamos a usar, sendo o seu objectivo exactamente tornar o c´digo em oR independente (ou pelo menos o mais poss´ ıvel) desse software. A men¸˜o ao SGBD a causar ´ feita unicamente quando se faz a liga¸˜o entre o R e esse software, sendo tudo o resto e caindependente de qualquer que seja o SGBD usado. Para tornar tudo isto poss´ ıvel, paraal´m da package DBI, precisamos ainda de outras packages associadas a cada um dos eSGBD’s que pretendemos de facto usar. Por exemplo, se pretendemos fazer o interfacecom uma base de dados guardada em Oracle, temos que instalar tamb´m a package eROracle. A ideia geral desta arquitectura de comunica¸˜o entre o R e os SGBD’s pode caser melhor descrita pela Figura 7. DBMS ODBC Driver Protocolo R ODBC Driver (MyODBC) ODBC (RODBC) DBMS (MySQL) MySQL Driver (RMySQL) Database Interface R DBMS (DBI) ORACLE Driver (ORACLE) (RORACLE) DBMS (Xpto) XPTO Driver Figura 7: A arquitectura de comunica¸˜o entre o R e diferentes SGBD’s. ca 13 Note que esta estrat´gia ´ espc´ e e ıfica a vers˜es Windows do R. o
    • 66 4 ¸˜ MANIPULACAO DE DADOS Ou seja a maioria do tempo o utilizador s´ “vˆ” as fun¸˜es da package DBI, e portanto o e copara ele ´ tudo praticamente igual independentemente do SGBD que se est´ a usar como e afonte de dados. Neste texto vamos ver um exemplo concreto usando o SGBD MySQL, um excelenteSGBD de car´cter gratu´ como o R. A melhor forma de fazermos o interface com este a ıtoSGBD depende da plataforma onde estamos a trabalhar com o R. No Windows ´ melhor eusar o protocolo ODBC, enquanto que noutras plataformas ´ mais f´cil usar o package e aRMySQL. A ideia de usar o protocolo ODBC est´ descrita na Figura 7. Temos o apackage gen´rico DBI que vai “falar” com o package RODBC que tamb´m precisamos e ede instalar. Este por sua vez vai falar com as bases de dados no MySQL atrav´s de eum driver que precisamos instalar no Windows que de uma forma simplista traduz alinguagem do protocolo ODBC para algo entend´ pelo SGBD MySQL. ıvel Da primeira vez que pretendemos fazer o interface a uma base de dados no MySQLusando o protocolo ODBC, s˜o necess´rios alguns passos extra. Estes passos s´ s˜o a a o aefectuados da primeira vez. Em particular precisamos de instalar o driver ODBC doMySQL que podemos obter no site deste SGBD (http://www.mysql.com). Depoisde termos este driver (myodbc ´ o seu nome) instalado, j´ podemos fazer liga¸˜es ao e a coMySQL usando o protocolo ODBC. De acordo com este protocolo cada liga¸˜o a uma cabase de dados tem um nome (o Data Source Name, ou DSN na linguagem ODBC).Este nome vai ser usado para nos referirmos ` base de dados quando pretendermos aimportar dados do lado do R. Para criar uma liga¸˜o ODBC em Windows temos de usar caum programa chamado ODBC data sources que est´ dispon´ a ıvel no Control Panel doWindows. Depois de excutar este programa temos que criar uma nova User Data Sourceque use o MySQL ODBC driver (myodbc) que instalamos anteriormente. Durante esteprocesso de cria¸˜o v˜o-nos ser perguntadas v´rias coisas como por exemplo o endere¸o ca a a cdo servido MySQL (tipicamente localhost se o servidor est´ a ser executado no seu acomputador), o nome da base de dados que pretendemos aceder, e tamb´m o nome eque pretendemos dar a esta liga¸˜o (o tal nome que depois vamos usar no R). Assim caque este processo esteja completo, que voltamos a referir s´ ´ feito a primeira vez que oepretendemos criar uma liga¸˜o a um determinada base de dados, estamos prontos a, cadesde o R, establecer liga¸˜es ` base de dados usando o protocolo ODBC. O exemplo co aque mostramos em seguida, establece uma liga¸˜o a um base de dados, para a qual caanteriormente criamos uma liga¸˜o ODBC (DSN) com o nome “teste”, ca> library(RODBC)> library(DBI)> drv <- dbDriver(ODBC)> ch <- dbConnect(drv,teste,xpto,passwordxpto)> dados <- dbGetQuery(ch,select * from tabela)> dbDisconnect(ch)> dbUnloadDriver(drv) As primeiras duas instru¸oes carregam as packages necess´rias para importar os da- c˜ ados. As duas seguintes establecem a liga¸˜o ` base de dados, sendo usado o DSN que ca acriamos no programa ODBC Data Sources, bem como introduzido o nosso nome de uti-lizador e respectiva password para podermos aceder ` base de dados do MySQL. Em aseguida vem a instru¸˜o principal para irmos importar dados de qualquer tabela da nossa cabase de dados14 . Neste caso estamos a importar todos as linhas e colunas de uma tabelachamada “tabela” da nossa base de dados. Note-se que para conseguirmos lidar com estetipo de bases de dados relacionais vamos precisar de saber SQL, que ´ a linguagem de econsulta por excelˆncia deste tipo de bases de dados. O resultado da fun¸˜o dbQuery() e ca´ um data frame.e Finalmente, as ultimas instru¸˜es fecham a liga¸˜o ` base de dados. Note-se que ´ co ca aa package DBI define ainda v´rias outras fun¸˜es que permitem, por exemplo, fazer a a co 14 Note-se que esta instru¸˜o j´ ´ completamente independente do SGBD que estamos a usar e seria ca a eportanto igual para qualquer outro sistema que n˜o o MySQL. a
    • 4.2 Sumariza¸˜o de dados ca 67opera¸˜o inversa, ou seja enviar dados de um data frame do R para uma tabela de uma cabase de dados.4.2 Sumariza¸˜o de dados caAssim que temos os nossos dados no R, usando algum dos processos indicados, podemoscome¸ar a analis´-los. Nesta sec¸˜o descrevemos algumas fun¸˜es que indicam algumas c a ca cocaracter´ ısticas dos nossos conjuntos de dados. Para efeitos de ilustra¸˜o destas fun¸˜es ca covamos carregar o conjunto de dados chamado iris que vem com o R,> data(iris) Este conjunto de dados descreve em cada linha uma planta atrav´s de algumas das esuas biometrias, al´m da esp´cie a que pertence. e e Uma das primeiras coisas que podemos querer saber s˜o as dimens˜es dos nossos a odados,> nrow(iris)[1] 150> ncol(iris)[1] 5 A fun¸˜o summary() fornece-nos algumas estat´ ca ısticas descritivas b´sicas, a Estat´ ısticas descritivas> summary(iris) Sepal.Length Sepal.Width Petal.Length Petal.Width Min. :4.300 Min. :2.000 Min. :1.000 Min. :0.100 1st Qu.:5.100 1st Qu.:2.800 1st Qu.:1.600 1st Qu.:0.300 Median :5.800 Median :3.000 Median :4.350 Median :1.300 Mean :5.843 Mean :3.057 Mean :3.758 Mean :1.199 3rd Qu.:6.400 3rd Qu.:3.300 3rd Qu.:5.100 3rd Qu.:1.800 Max. :7.900 Max. :4.400 Max. :6.900 Max. :2.500 Species setosa :50 versicolor:50 virginica :50 Por vezes interessa-nos ter este tipo de an´lise descritiva por sub-grupos dos dados. aQuando os sub-grupos s˜o definidos por factores, podemos usar a fun¸˜o by(), a ca An´lise por a sub-grupos> by(iris[,-5],iris$Species,summary)iris$Species: setosa Sepal.Length Sepal.Width Petal.Length Petal.Width Min. :4.300 Min. :2.300 Min. :1.000 Min. :0.100 1st Qu.:4.800 1st Qu.:3.200 1st Qu.:1.400 1st Qu.:0.200 Median :5.000 Median :3.400 Median :1.500 Median :0.200 Mean :5.006 Mean :3.428 Mean :1.462 Mean :0.246 3rd Qu.:5.200 3rd Qu.:3.675 3rd Qu.:1.575 3rd Qu.:0.300 Max. :5.800 Max. :4.400 Max. :1.900 Max. :0.600------------------------------------------------------------iris$Species: versicolor Sepal.Length Sepal.Width Petal.Length Petal.Width Min. :4.900 Min. :2.000 Min. :3.00 Min. :1.000 1st Qu.:5.600 1st Qu.:2.525 1st Qu.:4.00 1st Qu.:1.200 Median :5.900 Median :2.800 Median :4.35 Median :1.300 Mean :5.936 Mean :2.770 Mean :4.26 Mean :1.326 3rd Qu.:6.300 3rd Qu.:3.000 3rd Qu.:4.60 3rd Qu.:1.500 Max. :7.000 Max. :3.400 Max. :5.10 Max. :1.800------------------------------------------------------------iris$Species: virginica Sepal.Length Sepal.Width Petal.Length Petal.Width Min. :4.900 Min. :2.200 Min. :4.500 Min. :1.400
    • 68 4 ¸˜ MANIPULACAO DE DADOS1st Qu.:6.225 1st Qu.:2.800 1st Qu.:5.100 1st Qu.:1.800Median :6.500 Median :3.000 Median :5.550 Median :2.000Mean :6.588 Mean :2.974 Mean :5.552 Mean :2.0263rd Qu.:6.900 3rd Qu.:3.175 3rd Qu.:5.875 3rd Qu.:2.300Max. :7.900 Max. :3.800 Max. :6.900 Max. :2.500 Por vezes pretendemos unicamente ver os dados, ou parte deles. Neste tipo de tarefas,nem sempre ´ pr´tico escrevermos o nome do data frame devido ` dimens˜o dos dados. e a a aNestas situa¸˜es, existem algumas fun¸˜es uteis como por exemplo as seguintes, co co ´> head(iris) Sepal.Length Sepal.Width Petal.Length Petal.Width Species1 5.1 3.5 1.4 0.2 setosa2 4.9 3.0 1.4 0.2 setosa3 4.7 3.2 1.3 0.2 setosa4 4.6 3.1 1.5 0.2 setosa5 5.0 3.6 1.4 0.2 setosa6 5.4 3.9 1.7 0.4 setosa> tail(iris) Sepal.Length Sepal.Width Petal.Length Petal.Width Species145 6.7 3.3 5.7 2.5 virginica146 6.7 3.0 5.2 2.3 virginica147 6.3 2.5 5.0 1.9 virginica148 6.5 3.0 5.2 2.0 virginica149 6.2 3.4 5.4 2.3 virginica150 5.9 3.0 5.1 1.8 virginica> str(iris)`data.frame: 150 obs. of 5 variables: $ Sepal.Length: num 5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ... $ Sepal.Width : num 3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ... $ Petal.Length: num 1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ... $ Petal.Width : num 0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ... $ Species : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ... As primeiras duas fun¸˜es mostram as primeiras e ultimas linhas do data frame, co ´enquanto que a fun¸˜o str() d´-nos um sum´rio global do data frame. ca a a Finalmente, os esquemas de indexa¸˜o que estudamos na Sec¸˜o 2.6 podem ser usados ca capara obter sub-grupos de dados, aos quais podemos aplicar alguma fun¸˜o de sumariza¸˜o ca case desejarmos, como os seguintes exemplos ilustram,> summary(iris[iris$Petal.Length > 6, ]) Sepal.Length Sepal.Width Petal.Length Petal.Width Species Min. :7.200 Min. :2.600 Min. :6.100 Min. :1.800 setosa :0 1st Qu.:7.400 1st Qu.:2.800 1st Qu.:6.100 1st Qu.:2.000 versicolor:0 Median :7.700 Median :3.000 Median :6.400 Median :2.100 virginica :9 Mean :7.578 Mean :3.144 Mean :6.433 Mean :2.122 3rd Qu.:7.700 3rd Qu.:3.600 3rd Qu.:6.700 3rd Qu.:2.300 Max. :7.900 Max. :3.800 Max. :6.900 Max. :2.500> summary(subset(iris, Petal.Length > 6)) Sepal.Length Sepal.Width Petal.Length Petal.Width Species Min. :7.200 Min. :2.600 Min. :6.100 Min. :1.800 setosa :0 1st Qu.:7.400 1st Qu.:2.800 1st Qu.:6.100 1st Qu.:2.000 versicolor:0
    • 4.2 Sumariza¸˜o de dados ca 69 Median :7.700 Median :3.000 Median :6.400 Median :2.100 virginica :9 Mean :7.578 Mean :3.144 Mean :6.433 Mean :2.122 3rd Qu.:7.700 3rd Qu.:3.600 3rd Qu.:6.700 3rd Qu.:2.300 Max. :7.900 Max. :3.800 Max. :6.900 Max. :2.500> summary(subset(iris, Petal.Length > 6, c(Petal.Width, Species))) Petal.Width Species Min. :1.800 setosa :0 1st Qu.:2.000 versicolor:0 Median :2.100 virginica :9 Mean :2.122 3rd Qu.:2.300 Max. :2.500> summary(subset(iris, Petal.Length > 6, Sepal.Width:Petal.Width)) Sepal.Width Petal.Length Petal.Width Min. :2.600 Min. :6.100 Min. :1.800 1st Qu.:2.800 1st Qu.:6.100 1st Qu.:2.000 Median :3.000 Median :6.400 Median :2.100 Mean :3.144 Mean :6.433 Mean :2.122 3rd Qu.:3.600 3rd Qu.:6.700 3rd Qu.:2.300 Max. :3.800 Max. :6.900 Max. :2.500 Note que as duas primeiras instru¸oes produzem exactamente os mesmo resultados. c˜A segunda usa a fun¸˜o subset(), que ´ uma forma alternativa de fazermos indexa¸˜o de ca e caestruturas como os data frames, mas que pode revelar-se mais pr´tica em certas situa¸˜es. a coAs instru¸˜es seguintes mostram mais alguns exemplos do uso desta fun¸˜o. co ca Por vezes estamos interessados em produzir sum´rios particulares dos dados que me- alhor se adequem `s nossas necessidades. Por exemplo, poderiamos pretender ter um atabela que para cada coluna de um data frame nos mostrasse o seu valor m´dio, o m´- e aximo, o m´ınimo, o desvio padr˜o, a variˆncia e o n´mero de valores desconhecidos. Uma a a uforma simples de conseguir tais efeitos ´ atrav´s da cria¸˜o de fun¸˜es pr´prias que pro- e e ca co oduzam os resultados pretendidos. Na Sec¸˜o 3.3.1 iremos ver em detalhe como criar cafun¸˜es, no entanto aqui deixamos uma ilustra¸˜o de como usar essas fun¸˜es criadas co ca copara obter os sum´rios que pretendemos. a> meuSumario <- function(x) {+ s <- c(mean(x, na.rm = T), min(x, na.rm = T), max(x, na.rm = T),+ sd(x, na.rm = T), var(x, na.rm = T), length(which(is.na(x))))+ names(s) <- c("m´dia", "m´n", "m´x", "desvioPadr~o", "vari^ncia", e ı a a a+ "N.desc.")+ s+ }> apply(iris[, 1:4], 2, meuSumario) Sepal.Length Sepal.Width Petal.Length Petal.Widthm´dia e 5.8433333 3.0573333 3.758000 1.1993333m´n ı 4.3000000 2.0000000 1.000000 0.1000000m´x a 7.9000000 4.4000000 6.900000 2.5000000desvioPadr~o a 0.8280661 0.4358663 1.765298 0.7622377vari^ncia a 0.6856935 0.1899794 3.116278 0.5810063N.desc. 0.0000000 0.0000000 0.000000 0.0000000 A fun¸˜o apply(), que j´ mencionamos na Sec¸˜o 3.2.3, permite-nos aplicar a todas ca a caas colunas de um data frame uma fun¸ao qualquer, produzindo desta forma um conjunto c˜de resultados para cada coluna. Neste caso aplicamos a fun¸˜o que criamos para obter caas estat´ ısticas que pretendiamos.
    • 70 4 ¸˜ MANIPULACAO DE DADOS4.3 F´rmulas oAs f´rmulas s˜o objectos da linguagem R que permitem explicitar uma forma gen´rica o a ede um sub-conjunto de dados. Elas s˜o muito usadas para indicar a estrutura gen´rica a ede um modelo de dados que pretendemos obter com uma qualquer fun¸˜o. S˜o tamb´m ca a ebastante usadas para obter gr´ficos que mostrem uma rela¸˜o espec´ a ca ıfica entre um sub-conjunto das vari´veis dos nossos dados. a Uma f´rmula tem a estrutura gen´rica o evari´vel ~ express~o a a em que vari´vel representa a vari´vel dependente, e express~o ´ uma express˜o a a a e aque indica de que vari´veis depende vari´vel. a a Vejamos um exemplo com os dados “iris”,> data(iris)> names(iris)[1] "Sepal.Length" "Sepal.Width" "Petal.Length" "Petal.Width" "Species" No contexto destes dados, a f´rmula “Sepal.Length ∼ Petal.Length + Species”, oindica que pretendemos obter algo (um modelo, um gr´fico, etc.) que relacione a vari´vel a aSepal.Length com as vari´veis Petal.Length e Species. a As f´rmulas tamb´m podem incluir transforma¸˜es dos dados, como ilustrado nesta o e cof´rmula o“Petal.Length ~ log(Petal.Width)”. As express˜es a seguir ao s´ o ımbolo “~” podem inclu´ ır: ˆ O sinal “+” significando inclus˜o. a ˆ O sinal “-” significando exclus˜o. a ˆ O sinal “.” significando incluir todas as vari´veis. a ˆ O sinal “*” aplicado a factores representa todas as combina¸˜es dos seus valores. co ˆ A fun¸˜o “I()” permite usar os operadores no seu verdadeiro sentido aritm´tico. ca e ˆ O sinal “:” gera todas as interac¸˜es com os valores de um factor. co Vejamos alguns exemplos do uso de f´rmulas. Come¸emos por exemplos de uso de o cf´rmulas no contexto da obten¸˜o de modelos. O exemplo seguinte obt´m um modelo o ca ede regress˜o linear que relaciona a vari´vel “Petal.Length” com a vari´vel “Sepal.Width”, a a ausando os dados do conjunto de dados “iris”.> lm(Petal.Length ~ Sepal.Width, data = iris)Call:lm(formula = Petal.Length ~ Sepal.Width, data = iris)Coefficients:(Intercept) Sepal.Width 9.063 -1.735 Os exemplos seguintes obtˆm modelos do mesmo tipo que relacionam a vari´vel “Pe- e atal.Length” com a todas as interac¸˜es entre “Sepal.Width” e os valores de “Species” no cocaso do primeiro, enquanto o segundo exemplo faz o mesmo com todas as combina¸˜es coposs´ıveis entre “Sepal.Width” e os valores de “Species”.> lm(Petal.Length ~ Sepal.Width:Species, data = iris)
    • 4.4 Visualiza¸˜o de dados ca 71Call:lm(formula = Petal.Length ~ Sepal.Width:Species, data = iris)Coefficients: (Intercept) Sepal.Width:Speciessetosa 2.1887 -0.2085Sepal.Width:Speciesversicolor Sepal.Width:Speciesvirginica 0.7489 1.1258> lm(Petal.Length ~ Sepal.Width * Species, data = iris)Call:lm(formula = Petal.Length ~ Sepal.Width * Species, data = iris)Coefficients: (Intercept) Sepal.Width 1.18292 0.08141 Speciesversicolor Speciesvirginica 0.75200 2.32798Sepal.Width:Speciesversicolor Sepal.Width:Speciesvirginica 0.75797 0.60490 Na Figura 8 podemos ver um exemplo de um gr´fico (neste caso um “boxplot”) que anos d´ uma ideia da distribui¸˜o da vari´vel “Petal.Width” para os sub-conjuntos dos a ca adados correspondentes a cada valor da vari´vel “Species”, o que ´ produzido pelo seguinte a ec´digo, o> boxplot(Petal.Width ~ Species, data = iris) 2.5 2.0 1.5 1.0 q 0.5 q setosa versicolor virginica Figura 8: Um gr´fico obtido com uma f´rmula. a o4.4 Visualiza¸˜o de dados caO R tem como um dos seus pontos mais fortes a flexibilidade e poder em termos devisualiza¸˜o de dados. De facto, para al´m de uma s´rie de fun¸˜es de alto n´ ca e e co ıvel queproduzem os gr´ficos mais comuns neste tipo de an´lises, o R possibilita ao utilizador, a a
    • 72 4 ¸˜ MANIPULACAO DE DADOS atrav´s de um conjunto de fun¸˜es de mais baixo n´ e co ıvel, alterar e produzir gr´ficos que me- a lhor se adequem ao seu problema. Neste documento iremos analisar alguns dos aspectos mais b´sicos deste vasto assunto. Para informa¸˜o mais detalhada pode ser consultado a ca o interessante livro R Graphics por Murrell (2006).Sistemas de gr´ficos a Os gr´ficos em R est˜o organizados em 2 tipos de sistemas de gr´ficos: a a a 1. O sistema tradicional implementado na package “graphics”. 2. O sistema de gr´ficos Trellis implementado com base na package “grid” e disponi- a bilizado na package “lattice”. As fun¸˜es disponibilizadas em cada uma destas packages podem ser divididas em 3 co classes de fun¸˜es: co ˆ Fun¸˜es de alto-n´ que produzem gr´ficos completos. co ıvel a ˆ Fun¸˜es de baixo-n´ que permitem adicionar elementos a gr´ficos j´ desenhados. co ıvel a a ˆ Fun¸˜es para trabalhar de forma interactiva com gr´ficos j´ desenhados. co a a Independentemente do tipo de gr´ficos que produzimos eles “v˜o parar” a um de- a aDevices gr´ficos a terminado device gr´fico. Por defeito, e na maioria das situa¸˜es, esse device vai ser o a co ´cran. No entanto, existem situa¸˜es em que podemos crer mudar o device de sa´ dos e co ıda gr´ficos, como por exemplo se pretedermos colocar o gr´fico num ficheiro PDF. A escolha a a do device define n˜o s´ o local onde o gr´fico ´ produzido, mas tamb´m o tipo de output. a o a e e Por exemplo, se pretendemos que um determinado gr´fico v´ parar a um ficheiro em a a formato PDF, podemos fazer algo do g´nero, e pdf(file=exp.pdf) plot(rnorm(10)) dev.off() Se quisessemos o mesmo em formato JPEG, jpeg(file=exp.pdf) plot(rnorm(10)) dev.off() Qualquer destes (e de muitos outros) devices existentes no R, tem uma s´rie de parˆ- e a metros que permitem controlar o output. Em R tamb´m ´ poss´ abrir v´rios devices ao mesmo tempo, embora s´ um deles e e ıvel a o possa estar activo (para onde v˜o os gr´ficos). Isto ´ util, por exemplo, para ter v´rios a a e´ a gr´ficos no ´cran ao mesmo tempo. a e A fun¸˜o windows() permite abrir mais uma janela de gr´ficos em Windows, ca a > plot(rnorm(10) > windows() > plot(rnorm(20) O segundo gr´fico vai surgir numa outra janela, o que permite ao utilizador ver os a dois ao mesmo tempo se quiser. Note que posteriores gr´ficos que venhamos a realizar a v˜o ser desenhados na segunda janela de gr´ficos (o device actualmente activo). a a As fun¸˜es dev.cur(), dev.set(), e dev.list() s˜o uteis para saber qual o device co a ´ activo actualmente, mudar o device activo, e listar os devices activos.
    • 4.4 Visualiza¸˜o de dados ca 73 Histogram of iris$Petal.Width 35 30 25 20 Frequency 15 10 5 0 0.0 0.5 1.0 1.5 2.0 2.5 iris$Petal.Width Figura 9: Um exemplo de um histograma. 4.4.1 Gr´ficos Univariados a Quando pretendemos visualizar um unica vari´vel, em particular se ela ´ cont´ ´ a e ınua, temosstogramas ao nosso dispˆr v´rias fun¸˜es de alto n´ o a co ıvel. Por exemplo, podemos obter um histograma da vari´vel: a > hist(iris$Petal.Width) O resultado desta instru¸˜o pode ser visto na Figura 9. ca A Figura 10) mostra uma outra variante de um histograma obtida manipulando alguns dos parˆmetros da fun¸˜o hist(). a ca > hist(iris$Petal.Width, main = "Histograma de Petal.Width", xlab = "", + ylab = "Probabilidade", prob = T) Histograma de Petal.Width 1.0 0.8 Probabilidade 0.6 0.4 0.2 0.0 0.0 0.5 1.0 1.5 2.0 2.5 Figura 10: Ainda outro histograma. Os gr´ficos de caixa de bigodes (box plots) s˜o outros gr´ficos univariados bastante a a a Boxplots usados. Podem ser obtidos em R usando a fun¸˜o boxplot() da seguinte forma (ver o ca resultado na Figura 11), > boxplot(iris$Petal.Length, main = "Petal.Length") A fun¸˜o barplot() pode ser usada para obter gr´ficos de barras, conforme ilustrado ca a Gr´ficos de barras a no seguinte exemplo (ver Figura 12), criado para nos mostrar quantas plantas existem de cada esp´cie dentro do subconjunto que tem P etal.W idth > 1, e
    • 74 4 ¸˜ MANIPULACAO DE DADOS Petal.Length 7 6 5 4 3 2 1 Figura 11: Um gr´fico de caixa de bigodes. a > barplot(table(subset(iris, Petal.Width > 1)$Species)) 50 40 30 20 10 0 setosa versicolor virginica Figura 12: Um gr´fico de barras. a 4.4.2 Gr´ficos de 3 Vari´veis a a As fun¸˜es principais para obter gr´ficos com dados que envolvem 3 vari´veis s˜o: co a a a ˆ persp() para produzir superf´ ıcies tridimensionais. ˆ countour() para produzir gr´ficos com curvas de n´ representando uma super- a ıvel f´ tridimensional. ıcie ˆ image() para produzir uma representa¸˜o bidimensional de uma superf´ tridi- ca ıcie mensional, usando cores para representar a 3ª dimens˜o. aGr´ficos a Vejamos alguns exemplos da sua utiliza¸˜o. catri-dimensionais > x <- seq(-10, 10, length = 30) > y <- x > f <- function(x, y) { + r <- sqrt(x^2 + y^2) + 10 * sin(r)/r + }
    • 4.4 Visualiza¸˜o de dados ca 75> z <- outer(x, y, f)> z[is.na(z)] <- 1> persp(x, y, z, theta = 30, phi = 30, expand = 0.5, col = "lightblue") O resultado das instru¸˜es apresentadas acima, que pode ser visto na Figura 13, ´ uma co √ e sin( x2 +y 2 )representa¸˜o tri-dimensional da fun¸˜o 10 × ca ca √ . Para isso criamos uma fun¸˜o ca x2 +y 2(f()) que calcula o valor da referida express˜o, para quaisquer valores de x e y. Depois, ausamos a fun¸˜o outer() para obter os valores dessa fun¸˜o para todas as combina¸˜es ca ca code um conjunto de valores de x e y. z y x Figura 13: Um gr´fico tri-dimensional com a fun¸˜o “persp”. a ca A Figura 14 mostra-nos um outro exemplo de utiliza¸˜o da fun¸˜o persp(), usando ca caoutras parametriza¸˜es, bem como um outro conjunto de dados dispon´ no R. co ıvel> z <- 2 * volcano> x <- 10 * (1:nrow(z))> y <- 10 * (1:ncol(z))> op <- par(bg = "slategray")> persp(x, y, z, theta = 135, phi = 30, col = "green3", scale = FALSE,+ ltheta = -120, shade = 0.75, border = NA, box = FALSE)> par(op) Por vezes estamos interessados em obter representa¸˜es bi-dimensionais de superf´ co ıciestri-dimensionais. Isto pode ser conseguido de v´rias formas. Uma delas consiste em usar acurvas de n´ que possam transmitir a ideia do valor da terceira dimens˜o. No R tal ıvel aefeito pode ser obtido com a fun¸˜o contour(). O c´digo seguinte mostra um exemplo ca o Gr´ficos de curva de ada sua utiliza¸˜o com os dados volcano, cujo resultado pode ser visualizado na Figura 15. ca n´ ıvel> x <- 10 * 1:nrow(volcano)> y <- 10 * 1:ncol(volcano)> contour(x, y, volcano, col = "red", lty = "solid") Uma alternativa `s curvas de n´ ´ representar a terceira dimens˜o atrav´s de v´rias a ıvel e a e agrada¸˜es de cor. Isto mesmo pode ser obtido com a fun¸˜o image() do modo seguinte, co ca Gr´ficos com n´ a ıveispodendo o resultado ser visto na Figura 16. de cor> image(volcano)
    • 76 4 ¸˜ MANIPULACAO DE DADOS Figura 14: Um outro gr´fico tri-dimensional com a fun¸˜o “persp”. a ca 600 500 400 300 200 100 0 0 200 400 600 800 Figura 15: Um gr´fico de curvas de n´ a ıvel.
    • 4.4 Visualiza¸˜o de dados ca 77 1.0 0.8 0.6 0.4 0.2 0.0 0.0 0.2 0.4 0.6 0.8 1.0 Figura 16: Um gr´fico com grada¸˜es de cor. a co Por fim, na Figura 17 podemos ver uma conjuga¸˜o das duas ideias: as curvas de can´ e as cores: ıvel> x <- 10 * (1:nrow(volcano))> y <- 10 * (1:ncol(volcano))> image(x, y, volcano, col = terrain.colors(100))> contour(x, y, volcano, levels = seq(90, 200, by = 5), add = TRUE,+ col = "peru")> title(main = "Maunga Whau Volcano", font.main = 4) Maunga Whau Volcano 600 500 400 300 y 200 100 200 400 600 800 x Figura 17: Um gr´fico com curvas de n´ e grada¸˜es de cor. a ıvel co
    • 78 4 ¸˜ MANIPULACAO DE DADOS 4.4.3 Gr´ficos Multivariados a Por vezes pretendemos obter gr´ficos com dados referentes a mais do que uma vari´vel. a a fun¸˜o matplot(), por exemplo, permite-nos desenhar s´ries de dados, guardadas numa ca e matriz em que cada coluna tem uma s´rie de dados. Vejamos um exemplo cujo resultado e ´ apresentado na Figura 18, e > m <- matrix(rnorm(100), 20, 5) > op <- par(mfrow = c(1, 2), mar = c(2, 3, 0, 1)) > matplot(m) > matplot(m, type = "l") > par(op) 4 5 2 2 1 2 2 4 1 5 1 1 3 5 1 3 2 2 1 32 251 2 4 511 4 2 5 33 5 2 5 21 1 3 3 54 43 5 4 5 1 3 4 1 m m 52 41 0 0 3 5 4 1 4 3 2 3 5 1 3 1 55 5 2 1 4 4 3 2 3 4 1 5 22 3 4 4 2 −1 −1 2 4 1 1 3 3 4 2 2 4 5 3 −2 −2 1 3 4 5 5 10 15 20 5 10 15 20 Figura 18: Gr´ficos de v´rias s´ries de dados. a a e Em R ´ tamb´m poss´ e e ıvel encontrar diversas fun¸˜es que s˜o capazes de lidar com co a data frames formados por v´rias colunas. Obviamente, este tipo de gr´ficos, muitas vezes a a resulta em figuras demasiado “cheias” com pouca compreensibilidade, devido ` dimens˜o a a dos dados. No entanto, em muitas situa¸˜es, estas s˜o boas ferramentas de an´lise visual co a a de dados.Gr´ficos bivariados a A fun¸˜o pairs() ´ provavelmente a mais comum para este tipo de dados. Ela produz ca e uma matriz sim´trica de gr´ficos bivariados, como podemos ver na Figura 19, e a > pairs(iris[,1:4])
    • 4.4 Visualiza¸˜o de dados ca 79 2.0 3.5 0.5 2.0 qqq q q q qq qqq qq qq qqq q q q qq q q qq q qq qq qqq q q q qq qq qq q q qq qqq qqq qqq qqq q q qq 6.5 q qqq qq qqq q qq q qq qq q q qq qqq qq qqqq q q qq q Sepal.Length q qqqqq q q qq qq q q qqqqq q qq q qq qqq qq q qq q qq q q qq qq qq q qq q q q qq q q q qqqq qq qqq q q qq qqq qq qq q qq qq qq qq qq qq q qq q q qq q qqqq q qq qq qqqq qq q qq q q q q q q qqq qqqq qq qq q qq qq q qq qq q qq qq q q qq q qq q qqq q qqqqq q q qqq qq qq qq q q q qq qq q q q qq q q qqq q q q qqq q q q q qqqq qq qq q q q q q qq q qq qq q q q qq q q 4.5 q qq qq qq q qq qq qq q q q q q q qq qq q q q qqq q q qq qq qq qqq qq qq qq q qq qq q qq qq qq qq q qq 3.5 qqqq q q q qq q q qq q q q q qq q q q q qq q q q qq q q q qq q q qq qq q q q q qqq q q qq qq q q qq q q q q qqq qq qqq qq q q Sepal.Width qq q q q qq q qq qqqq q q qq qq q qqq qq q q qq q qqqq qq q q qqqqqq qq qq q q q qqq q q q qqq q q q qq q q q q qq q q qqqqqq q qq q qq q qq q qq q q qq qq q qq qq qq qqqq q qq q q qq q q q qq q qq qq q qq q q qqq qqq qq qqq qq q q qqqqq qq qq q q q q q qqq q q qq q q q q q q qqqqq q q qqq qq q q q q qq qq q q qq qq q qq q qqq q q qq qq q q q qq q q q 2.0 q q q 7 q q qqq q qq qq qqq q qq q qq q qq qq qq q qqq q qq q qq q qqqqq qqqqq qq q q q q qqq qqq q qq qqqq qqqq q q qqq qq qqq qq q qq qqq qq q qqq q q qqq qq 5 qq q qq qq qqqqq qqqq q q qqqqq qqqqq q q qqqq q q qqq q qqq qq q qq q qqq qqq qq qqqq q q q qqqq qqqqq Petal.Length q qqq qqq qq q q q q qqqq q q qq q q q q 3 qq qqq q qq qqqq q qqq qqq qqqqq qq qqq q q q q qqqqqqq q qqqqqqq qq q qqqq q qqq qqq qq qq qq qq q 1 qq q q q qq qq qq q qq q qqqqq q qqq q qq qq qq qqq qq q qqq q qq qq qq 2.0 q q q qqq q q q qq q qqqq q qq qq q q q qqq qq qqqq qq qq qq qq qq q q qqq q qq q q qqqq qq q q q qqqq q q qq qqq qq q q q qqqqq qqq qq qq q qq qqqq q qqqq q qqqq q qq q q qqq q qqqq qqq qq qq q qqq q qq qq Petal.Width q qq q qqq qqqq qq q qqqq qq q qqq q qq qq q qq qqqq q qqq qqqq qq qq q q 0.5 q qqq qq q q q q q qqqqq qqqqq qq q qqqqqq qq q qqqqqq qq qq q qqqq qqq q qq q qq qq q qqq q q qq qq qq q qq q q q q qq 4.5 6.5 1 3 5 7 Figura 19: Uma matriz de gr´ficos bivariados. a Tirando partido da flexibilidade da programa¸˜o em R ´ poss´ modificar grande- ca e ıvelmente este tipo de fun¸˜es, fazendo por exemplo o R incluir histogramas de cada uma das covari´veis na diagonal da matriz de gr´ficos da Figura 19, ou mesmo substituir a parte a asuperior da matriz (tirando partido dela ser sim´trica), por outros gr´ficos. Vejamos e aalguns exemplos deste tipo de modifica¸˜es. co Na Figura 20 vemos um gr´fico do tipo “pairs” onde, na diagonal, acrescentamos ahistogramas de cada uma das vari´veis, e na parte superior direita colocamos os valores ada correla¸˜o, numa fonte tanto maior quanto maior a correla¸˜o. Para isso, criamos ca caduas fun¸˜es: panel.hist() e panel.cor() que produzem esses objectivos e que s˜o co apassadas depois em certos argumentos da fun¸˜o pairs(). ca> panel.hist <- function(x, ...) {+ usr <- par("usr")+ on.exit(par(usr))+ par(usr = c(usr[1:2], 0, 1.5))+ h <- hist(x, plot = FALSE)+ breaks <- h$breaks+ nB <- length(breaks)+ y <- h$counts+ y <- y/max(y)+ rect(breaks[-nB], 0, breaks[-1], y, col = "cyan", ...)+ }> panel.cor <- function(x, y, digits = 2, prefix = "", cex.cor) {+ usr <- par("usr")+ on.exit(par(usr))+ par(usr = c(0, 1, 0, 1))+ r <- abs(cor(x, y))
    • 80 4 ¸˜ MANIPULACAO DE DADOS + txt <- format(c(r, 0.123456789), digits = digits)[1] + txt <- paste(prefix, txt, sep = "") + if (missing(cex.cor)) + cex <- 0.8/strwidth(txt) + text(0.5, 0.5, txt, cex = cex * r) + } > pairs(USJudgeRatings[1:5], lower.panel = panel.smooth, upper.panel = panel.cor, + diag.panel = panel.hist, cex.labels = 2, font.labels = 2) 6.0 7.5 9.0 5 6 7 8 9 CONT 6 7 8 9 0.13 0.15 0.14 0.012 q 9.0 q q q qqq q qqq q qq qq q qq q q q INTG q qq q q 0.96 q qq 0.87 0.81 7.5 q q q qq q q q q 6.0 q qq qq 5 6 7 8 9 q qqqq q qq q q qq q qq qq q q qqqqq q q q q q q q qq qq qq q qq qq q qq qq qq DMNR q qq q qq qq q q q q q q q q qq q qqq 0.84 0.81 q q qq q q q qq qq 9 qqqq q qq q qqq q qq q qq q q q qq q q q q q qqqq qqq q q q q qq qq qq qq q q DILG 8 q qq qq q q q q qq qq qq qq qq 0.96 q q qqq qq q q qq q qqq q q q q q q q q q 7 qq q q qq q q qq q q q q q q q q q q 6 q q q q q q 5 qq q q qq 8.5 q q q q q qq q q qq qq qqq q qqq q qq q q qqq q q q qqqq q q q q q q qqqq q q q qq qq q q q qq q q qqq q q q qqq qqq q q q q qq q q CFMG q qq q q q q q qq q qq q qqq q qq qq q qq 7.0 q q q q q q q q q q q q q q q qq q q q qqqq qq qq q qq q qq q q q qqq q q q q 5.5 q q q q qq q q q q q q 6 7 8 9 5 6 7 8 9 5.5 7.0 8.5 Figura 20: Um gr´fico “pairs” com histogramas no meio e valores da correla¸˜o no canto a ca superior direito. Um outro tipo de gr´ficos que por vezes ´ muito interessante uma vez que nos per- a e mite comparar observa¸˜es descritas por v´rias vari´veis cont´ co a a ınuas, s˜o os gr´ficos do a aGr´ficos stars a tipo stars. Estes gr´ficos mostram cada observa¸˜o de um data frame por uma esp´cie a ca e de estrela, com tantos raios quantas as vari´veis que descrevem as observa¸˜es. O tama- a co nho de um raio representa a diferen¸a do valor nessa vari´vel na observa¸˜o em causa c a ca relativamente ao valor m´dio em todas as observa¸˜es (depois de normalizados todos os e co valores). A primeira vari´vel ´ representada pelo raio na posi¸˜o horizontal, ` direita. a e ca a As vari´veis seguintes seguem o sentido contr´rio aos ponteiros de rel´gio. Vejamos um a a o exemplo com o conjunto de dados “mtcars” usando para isso a fun¸˜o stars(), ca > stars(mtcars[1:10, 1:7], main = "Motor Trend Cars")
    • 4.4 Visualiza¸˜o de dados ca 81 Note que este tipo de gr´ficos ´ de dif´ visualiza¸˜o quando o n´mero de obser- a e ıcil ca uva¸˜es ´ grande, podendo n´s, nessas situa¸˜es, focar-mo-nos em sub-conjuntos mais co e o cointeressantes dos dados. Motor Trend Cars Mazda RX4 Wag Mazda RX4 Datsun 710 Hornet 4 Drive Valiant Hornet Sportabout Merc 240D Duster 360 Merc 230 Merc 280 Figura 21: Um gr´fico “stars”. a Finalmente, vamos ver um tipo de gr´ficos bastante util para vari´veis nominais que a ´ a Gr´ficos mosaic as˜o os gr´ficos do tipo mosaic. Eles usam as ´reas relativas de diversos rectˆngulos a a a apara representar as diferen¸as entre as propor¸˜es de casos que possuem determinados c covalores das vari´veis nominais em estudo. Vejamos um exemplo com o conjunto de dados a“Titanic” que vem com o R,> mosaicplot(Titanic, main = "Survival on the Titanic") O resultado desta chamada ` fun¸˜o mosaicplot() pode ser visto na Figura 22. a ca4.4.4 Gr´ficos Condicionados aPor vezes pretendemos obter certo tipo de gr´ficos para diferentes sub-grupos dos nossos a Gr´ficos adados, de tal modo que seja f´cil comparar cada sub-grupo. Por exemplo, poderiamos a condicionadosquerer obter um gr´fico de caixa de bigodes da vari´vel Petal.Width para cada esp´cie de a a eplanta (ver Figura 23). Em R isso ´ f´cil obter, uma vez que a pr´pria fun¸˜o boxplot() e a o capermite explicitar este tipo de condicionamentos usando as f´rmulas que estudamos na oSec¸˜o 4.3 ca> boxplot(Petal.Width ~ Species, iris)
    • 82 4 ¸˜ MANIPULACAO DE DADOS Survival on the Titanic 1st 2nd 3rd Crew Child Adult Child Adult Child Adult Child Adult No Male Yes Sex No Female Yes Class Figura 22: Um gr´fico “mosaic”. a
    • 4.4 Visualiza¸˜o de dados ca 83 2.5 2.0 1.5 1.0 q 0.5 q setosa versicolor virginica Figura 23: Um gr´fico condicionado. a4.4.5 Interac¸˜o com Gr´ficos ca aPor vezes pretendemos ter alguma forma de interagir com os gr´ficos desenhados no ´cran. a eO R tem algumas fun¸˜es que podem ser usadas neste contexto. A fun¸˜o locator(), co capor exemplo, pode ser usada para obter as coordenadas dos pontos “cliquados” com orato numa janela de gr´ficos. Uma exemplo de uma situa¸˜o em que isto pode dar jeito ´ a ca epara interactivamente decidir a localiza¸˜o da legenda de um gr´fico. Isto pode ser feito ca ada seguinte forma:> plot(AirPassengers)> legend(locator(1), "n.passageiros", lty = 1)
    • 84 4 ¸˜ MANIPULACAO DE DADOS 600 n.passageiros 500 AirPassengers 400 300 200 100 1950 1952 1954 1956 1958 1960 Time A fun¸˜o legend() permite acrescentar uma legenda numas determinadas coordena- ca das X-Y do gr´fico. Na Sec¸ao 4.4.6 iremos ver esta e outras fun¸˜es mais em detalhe. a c˜ co No exemplo acima, em vez de explicitar as coordenadas X-Y onde queremos colocar a legenda, usamos a fun¸˜o locator(). Ao encontrar esta fun¸˜o o R vai ficar em modo in- ca ca teractivo, o que quer dizer que fica ` espera que o utilizador clique num qualquer local da a janela gr´fica. O resultado da fun¸˜o s˜o as coordenadas X-Y do local onde o utilizador a ca a cliquar. O argumento da fun¸˜o indica quantos cliques esperamos do utilizador. ca Uma outra fun¸˜o interactiva ´ a fun¸˜o identify() que serve para identificar pontos ca e ca espec´ ıficos de um gr´fico e por exemplo escrever perto os respectivos valores da vari´vel. a a Experimente esta fun¸˜o com os seguintes exemplos: ca > plot(CO2$uptake) > identify(CO2$uptake) > plot(CO2$uptake) > identify(CO2$uptake, labels = CO2$Plant) 4.4.6 Adicionar Informa¸˜o a Gr´ficos Existentes ca a O R tem v´rias fun¸˜es que podem ser usadas para acrescentar diversos tipos de infor- a co ma¸˜o a gr´ficos j´ existentes. ca a a Por exemplo, a fun¸˜o points() pode ser usada para acrescentar novos dados a um caAcrescentar novos gr´fico j´ desenhado: a adados > plot(rnorm(10)) > points(rnorm(10), col = "red") O resultado pode ser observado na Figura 24 onde os pontos a vermelho foram acres- centados ` posteriori, atrav´s da chamada ` fun¸˜o points(). a e a ca O R tem tamb´m algumas fun¸˜es que podem ser usadas para acrescentar mais al- e co guns elementos a gr´ficos que j´ existem. Vejamos um exemplo, ainda com o mesmo a a histograma (resultado na Figura 26),
    • 4.4 Visualiza¸˜o de dados ca 85 q q 2 q 1 q q q rnorm(10) q q 0 q q q q q −1 q q q q q q −2 q 2 4 6 8 10 Index Figura 24: O uso da fun¸˜o “points”. ca Por vezes os novos dados que pretendemos acrescentar devem ser desenhados comolinhas. Para isso a fun¸˜o lines() ´ mais indicada, e o seguinte exemplo ilustra a sua ca eutiliza¸˜o: ca Acrescentar linhas> plot(rnorm(10))> lines(rnorm(10), col = "red") O resultado pode ser observado na Figura 25. q 1.0 0.5 q q 0.0 q rnorm(10) q q −0.5 q q −1.0 q −1.5 q 2 4 6 8 10 Index Figura 25: O uso da fun¸˜o “lines”. ca O exemplo seguinte mostra uma utiliza¸˜o da fun¸˜o lines() noutro contexto. ca ca> hist(iris$Petal.Width, main = "Histograma de Petal.Width", xlab = "",+ ylab = "Probabilidade", prob = T)
    • 86 4 ¸˜ MANIPULACAO DE DADOS > lines(density(iris$Petal.Width)) > rug(jitter(iris$Petal.Width)) Neste exemplo concreto, cujo resultado ´ apresentado na Figura 26, passamos ` fun¸˜o e a ca como argumento o resultado produzido pela fun¸˜o density(). Esta fun¸˜o produz ca ca uma estimativa usando uma aproxima¸˜o tipo “kernel” ` densidade da distribui¸˜o de ca a ca uma vari´vel cont´ a ınua. Finalmente, usamos a fun¸˜o rug() para desenhar pequenos ca tra¸os nos valores concretos da vari´vel, perto do eixo onde est´ a escala do gr´fico. c a a a Para evitar demasiadas sobreposi¸˜es, causadas por valores muito iguais, usamos ainda co a fun¸˜o jitter() que pega num vector de n´meros e causa-lhes pequenas perturba¸˜es ca u co aleat´rias. o Histograma de Petal.Width 1.0 0.8 Probabilidade 0.6 0.4 0.2 0.0 0.0 0.5 1.0 1.5 2.0 2.5 Figura 26: Um histograma com elementos extra. Tamb´m relacionada com o desenho de linhas num gr´fico j´ existente, est´ a fun¸˜o e a a a ca abline(). Esta fun¸˜o permite desenhar linhas horizontais, verticais, ou mesmo linhas ca inclinadas atrav´s da indica¸ao do valor de Y quando X ´ zero e da inclina¸˜o da recta. e c˜ e ca Vejamos exemplos destas utiliza¸˜es, cujo resultado pode ser observado na Figura 27, co > x <- rnorm(10) > plot(x) > abline(h = mean(x), col = "green", lty = 2) > abline(v = 3, col = "blue", lty = 4) > abline(-0.3, 0.5, col = "red", lty = 3) Em R tamb´m ´ poss´ acrescentar texto a gr´ficos existentes. A fun¸˜o text(), por e e ıvel a ca exemplo, pode ser usada para acrescentar qualquer texto em determinadas coordenadasAcrescentar texto de um gr´fico. Vejamos um exemplo, a > y <- rnorm(10) > plot(y) > text(1:10, y, ifelse(y > 0, "pos", "neg")) Neste exemplo (ver Figura 28), escrevemos o texto “pos” ou “neg” em cima de cada ponto desenhado, dependendo de o seu valor de Y ser positivo ou negativo, respectiva- mente. A fun¸˜o mtext(), por sua vez, pode ser usada para acrescentar qualquer texto `s ca a margens de um gr´fico. A margem a usar ´ determinada pelo parˆmetro “side” desta a e a fun¸˜o. Vejamos um exemplo cujo resultado aparece na Figura 29, ca
    • 4.4 Visualiza¸˜o de dados ca 87 1.0 q 0.5 q 0.0 q q x q −0.5 q q −1.0 q q −1.5 q 2 4 6 8 10 Index Figura 27: O uso da fun¸˜o “abline”. ca pos q 2 pos q 1 pos q pos q y 0 neg q neg q neg q −1 neg q neg q neg q 2 4 6 8 10 Index Figura 28: A fun¸˜o “text”. ca
    • 88 4 ¸˜ MANIPULACAO DE DADOS > plot(rnorm(10)) > mtext("margem de baixo", side = 1) > mtext("margem de baixo (2ª linha)", side = 1, line = 1) > mtext("margem esquerda", side = 2) > mtext("margem direita", side = 4) q 2 q margem esquerda margem direita 1 rnorm(10) q q q 0 q q q −1 q q margem de baixo 2 margem de baixo (2ª linha) 4 6 8 10 Index Figura 29: Escrever nas margens. A fun¸˜o arrows(), pode ser usada para acrescentar setas a um gr´fico. Vejamos um ca aAcrescentar setas exemplo cujo resultado aparece na Figura 30, > plot(1:6, c(10, 20, 23, 16, 18, 25), type = "l", col = "green") > arrows(2, 12, 4, 15.7, col = "red") > text(2, 12, "descida estranha!", pos = 1) A fun¸˜o tem como parˆmetros principais as coordenadas X-Y dos pontos origem e ca a destino da seta.Acrescentar t´ ıtulos e A fun¸˜o title(), permite acrescentar t´ ca ıtulos a gr´ficos, embora a maioria das fun- alegendas c˜es de alto n´ tenha um parˆmetro pr´prio (normalmente “main”) onde se pode ex- ¸o ıvel a o plicitar directamente o t´ ıtulo do gr´fico em causa. J´ a fun¸˜o legend() permite-nos a a ca acrescentar uma legenda ao gr´fico. O c´digo seguinte ilustra o uso destas duas fun¸˜es, a o co aparecendo o resultado na Figura 31 > plot(rnorm(10), type = "l") > lines(rnorm(10), col = "red", lty = 2) > title("N´meros aleat´rios") u o > legend("topright", c("1ª s´rie", "2ª s´rie"), lty = 1:2, col = 1:2) e e A fun¸˜o legend() pode receber nos dois primeiros argumentos as coordenadas X-Y ca do canto superior direito onde deve ficar colocada a legenda ou, em alternativa, podemos usar uma “string” que indique a posi¸˜o relativa da legenda, como vemos no exemplo ca acima. Veja a ajuda da fun¸˜o para conhecer mais alternativas. caAcrescentar Finalmente, no R ´ tamb´m poss´ acrescentar f´rmulas matem´ticas a um gr´fico. e e ıvel o a af´rmulas o Para indicar as f´rmulas temos que usar uma sintaxe um pouco complexa, cuja explica¸˜o o ca sai fora do ˆmbito deste texto. Pode fazer demo(plotmath) no prompt do R para ver a mais exemplos da sua utiliza¸˜o. Entretanto vejamos um exemplo concreto, ca
    • 4.4 Visualiza¸˜o de dados ca 89 25 c(10, 20, 23, 16, 18, 25) 20 15 descida estranha! 10 1 2 3 4 5 6 1:6 Figura 30: Desenhar setas. Números aleatórios 1ª série 2 2ª série 1 rnorm(10) 0 −1 2 4 6 8 10 Index Figura 31: T´ ıtulos e legendas.
    • 90 4 ¸˜ MANIPULACAO DE DADOS> x <- rnorm(100)> boxplot(x, boxwex = 0.5)> abline(h = mean(x))> text(0.7, mean(x) + 0.5, substitute(paste(bar(x) == sum(frac(x[i],+ n), i == 1, n)))) O resultado pode ser observado na Figura 32 q 2 1 n xi x=∑ i=1 n = 0 −1 −2 q Figura 32: F´rmulas matem´ticas. o a4.4.7 Parˆmetros de Gr´ficos a aA estrutura gen´rica de um gr´fico em R pode ser descrita pela Figura 33. Assim, e atemos uma ´rea com o gr´fico propriamente dito, e uma regi˜o circundante que forma as a a amargens do gr´fico. Ao conjunto chama-se normalmente uma figura. a Margem de topo Margem esquerda Margem direita Area do grafico Margem de baixo Figura 33: A estrutura gen´rica dos gr´ficos em R. e a O espa¸o ocupado por cada um destes elementos que formam uma figura ´ totalmente c econfigur´vel pela fun¸˜o par(). Esta fun¸˜o permite fazer o setting “permanente” de a ca cav´rios parˆmetros gr´ficos para o device activo actual. Descrever os in´meros parˆmetros a a a u a
    • 4.4 Visualiza¸˜o de dados ca 91que podem ser modificados com esta fun¸˜o sai fora do ˆmbito deste texto. A ajuda da ca afun¸˜o fornece uma descri¸˜o exaustiva dos mesmos. ca ca Muitos dos parˆmetros que podem ser modificados pela fun¸˜o par(), tamb´m o po- a ca edem ser atrav´s de parˆmetros da maioria das fun¸˜es de alto n´ para produzir gr´ficos. e a co ıvel aTodavia, usar esta alternativa faz com que um determinado valor para o parˆmetro s´ a oseja usado no gr´fico em causa e n˜o em todos os gr´ficos produzidos no device activo, a a acomo acontece quando usamos a fun¸˜o par(). ca Vejamos alguns dos parˆmetros mais comuns e que aparecem em quase todas as afun¸˜es de alto n´ para produzir gr´ficos: co ıvel a ˆ col - permite indicar a cor de elementos do gr´fico. a ˆ main - permite dar um t´ ıtulo ao gr´fico. a ˆ xlab - permite dar um t´ ıtulo ao eixo dos X’s. ˆ ylab - permite dar um t´ ıtulo ao eixo dos Y’s. ˆ xlim - permite indicar um vector com 2 n´meros que ser˜o usados como o range u a de valores no eixo dos X’s. ˆ ylim - permite indicar um vector com 2 n´meros que ser˜o usados como o range u a de valores no eixo dos Y’s. ˆ lty - permite indicar o tipo de linhas que v˜o ser usadas nos gr´ficos. a a ˆ cex - permite indicar um tamanho relativo do texto usado nos gr´ficos. a ˆ pch - os s´ ımbolos usados para desenhar os pontos no gr´fico. a4.4.8 ´ Dividir a Janela de Gr´ficos em V´rias Areas a aH´ v´rias maneiras de usar a ´rea da janela de gr´ficos para desenhar v´rios gr´ficos ao a a a a a amesmo tempo. Vejamos duas das formas mais comuns: ˆ Gr´ficos de tamanho igual. a > op <- par(mfrow = c(2, 2)) > for (i in 1:4) plot(rnorm(10), col = i, type = "l") > par(op) O parˆmetro “mfrow” permite explicitar uma divis˜o igual da janela de gr´ficos em a a a x linhas e y colunas. Assim, ao colocarmos nesse parˆmetro o valor c(2,1) por a exemplo, iriamos dividir o device em duas linhas com uma coluna de gr´ficos, ou a seja dois gr´ficos. a ˆ Gr´ficos de diferente tamanho - a fun¸˜o layout(). a ca > layout(matrix(1:4, 2, 2)) > layout.show(4) A fun¸˜o layout() recebe uma matriz como parˆmetro principal. As dimens˜es da ca a o matriz definem a forma como device ´ “dividido”. Assim, no exemplo anterior ele e vai ser dividido em duas linhas e duas colunas. Os valores na matriz determinam a ordem em que s˜o usadas cada uma das ´reas quando se produzem gr´ficos. A fun- a a a ca ¸˜o layout.show() pode ser usada para exemplificar visualmente esta informa¸˜o.ca O argumento desta fun¸˜o ´ o n´mero de gr´ficos que “cabem” no device. ca e u a O pr´ximo exemplo ´ um pouco mais sofisticado. Ele usa a seguinte matriz como o e argumento, > matrix(1:2, 2, 2)
    • 92 4 ¸˜ MANIPULACAO DE DADOS 0.0 2 1 rnorm(10) rnorm(10) 0 −1.0 −2 −2.0 2 4 6 8 10 2 4 6 8 10 Index Index 0.5 2 0.0 rnorm(10) rnorm(10) 1 0 −1.0 −1 2 4 6 8 10 2 4 6 8 10 Index Index Figura 34: V´rios gr´ficos de tamanho igual. a a 1 3 2 4 Figura 35: O layout criado.
    • 4.4 Visualiza¸˜o de dados ca 93 [,1] [,2] [1,] 1 1 [2,] 2 2 O significado desta matriz ´ que o primeiro gr´fico vai ocupar as duas primeiras e a a ´reas da matriz (toda a primeira linha), enquanto o segundo ocupa toda a segunda linha. Isto quer dizer que na realidade s´ v˜o “caber” 2 gr´ficos no nosso device. o a a > layout(matrix(1:2, 2, 2), heights = c(2, 1)) > layout.show(2) O argumento “heights” serve para explicitar diferentes tamanhos entre as linhas da matriz que define as ´reas em que ´ dividido o device. Neste caso, e uma vez a e que a matriz tem duas linhas, os dois n´meros indicam que os gr´ficos na primeira u a linha v˜o ocupar 2/3 da ´rea do device, enquanto que a segunda linha ocupa 1/3. a a a ´ O resultado desta divis˜o pode ser observado na Figura 36. E tamb´m poss´ e ıvel explicitar tamanhos absolutos usando a fun¸˜o lcm() conforme poder´ confirmar ca a ca ´ na ajuda da fun¸˜o layout(). E tamb´m poss´ explicitar os tamanhos usando e ıvel o parˆmetro “widths”, ou ambos. a 1 2 Figura 36: Um layout com diferentes tamanhos. O nosso exemplo final usa a matriz, > rbind(c(1, 2), c(3, 3)) [,1] [,2] [1,] 1 2 [2,] 3 3 como argumento, o que quer dizer que vamos ter 3 gr´ficos, sendo que o terceiro a ocupa toda a linha de baixo da matriz de ´reas em que ´ dividido o device. a e > layout(rbind(c(1, 2), c(3, 3)), height = c(1, 2)) > layout.show(3) O resultado deste layout pode ser observado na Figura 37.
    • 94 4 ¸˜ MANIPULACAO DE DADOS 1 2 3 Figura 37: Mais um layout com diferentes tamanhos.
    • ˆREFERENCIAS 95Referˆncias eChambers, J. (1998). Programming with Data. Springer.Dalgaard, P. (2002). Introductory Statistics with R. Springer.Murrell, P. (2006). R Graphics. Chapman & Hall/CRC.R Development Core Team (2006). R: A Language and Environment for Statistical Computing. R Foundation for Statistical Computing, Vienna, Austria. ISBN 3-900051- 07-0.Venables, W. and Ripley, B. (2000). S Programming. Springer.
    • 96 ˆ REFERENCIAS
    • ´Indicea´lgebra matricial, 25, 57 fun¸˜es, 56 co determinante, 25 abline, 86 inversa, 25 apply, 50, 69 multiplica¸˜o, 25 ca apropos, 9 transposta, 25 argumentos, 19 array, 26ambientes arrows, 88 workspace, 53 as.Date, 38arrays, 26 as.POSIXlt, 39atribui¸˜o, 11, 14 ca attach, 30 barplot, 73blocos de instru¸˜es, 46 co boxplot, 73, 81 break, 48coer¸˜o de tipos, 13 ca browser, 60 by, 67data frames, 29 c, 13, 28 aceder `s colunas, 29 a cat, 45 aceder aos elementos, 29 cbind, 23, 35, 42 acrescentar colunas, 30 class, 59 criar, 29 colnames, 23 n´mero de colunas, 30 u contour, 75 n´mero de linhas, 30 u coredata, 41 preencher, 30 cut, 38datas/horas, 37 data, 63 discretizar, 38 data.frame, 29 extra´ 39 ır, mostrar, 37, 39 dbQuery, 66 objectos Date, 37 debug, 62 objectos POSIXt, 38 density, 86 sequˆncias, 37 e det, 25debugging, 60 detach, 30 debug, 62 dev.cur, 72 traceback, 60 dev.list, 72 undebug, 62 dev.set, 72 diff, 35, 43express˜es num´ricas, 11 o e dim, 22 download.file, 64factores, 15, 29 edit, 30 criar, 15 embed, 35 frequˆncias marginais, 17 e end, 34, 41 frequˆncias relativas, 17 e factor, 15 n´ıveis, 15 for, 49 tabelar, 16 format, 37 tabula¸˜o cruzada, 16 ca getwd, 8Fun¸˜es co gl, 19 argumentos, 54 head, 68 actuais, 55, 56 help, 9 formais, 55 help.search, 9 lazy evaluation, 56 hist, 73 n´mero vari´vel, 55 u a identify, 84 parˆmetro ..., 55 a if, 46 valores por defeito, 54 ifelse, 47 criar, 52 image, 75 valor, 52 install.packages, 10 97
    • ISOdate, 38 rm, 12jitter, 86 rnorm, 19, 48jpeg, 72 rollmean, 44lag, 35, 43 rownames, 23lapply, 51 RSiteSearch, 9layout, 91 rt, 19layout.show, 91 rug, 86legend, 84, 88 sapply, 51length, 13, 28 scan, 45, 64library, 10 seq, 18, 37, 55lines, 85 setwd, 8locator, 83 solve, 25ls, 12 sqrt, 14margin.table, 17 stars, 80matplot, 78 start, 34, 41matrix, 22 str, 45, 68mean, 54 strptime, 39median, 47 subset, 69merge, 42 summary, 67methods, 59 switch, 47min, 50 Sys.Date, 37months, 37 Sys.time, 39, 50mosaicplot, 81 t, 25mtext, 86 table, 16na.approx, 43 tail, 68na.contiguous, 43 tapply, 51na.locf, 43 text, 86na.omit, 36, 43 title, 88names, 21, 27 traceback, 60ncol, 30, 67 ts, 31next, 49 undebug, 62nrow, 30, 67 vector, 14 weekdays, 37objects, 12 while, 48outer, 75 window, 34, 42pairs, 78 windows, 72par, 90 zoo, 37pdf, 72persp, 74 indexa¸˜o, 13, 20 caplot, 32 ´ ındices negativos, 21points, 84 arrays, 26print, 45 data frames, 29prop.table, 17 matrizes, 23q, 8 vectores, 20quartile, 51 inteiros, 21rapply, 44 l´gicos, 20 orbind, 23 strings, 21read.csv, 63 vazios, 22read.csv2, 63 instru¸˜es iterativas, 48 coread.delim, 63read.delim2, 63 listas, 27read.fwf, 64 componentes, 27read.table, 63 extra´ 27 ır,read.xls, 65 contar componentes, 28rep, 19 extender, 28repeat, 48 juntar, 28return, 52 mostrar, 27
    • matrizes, 22 descendentes, 18 criar, 22 factores, 19 indexar, ver matrizes,indexa¸˜o ca n´meros reais, 18 u nomes dimens˜es, 23 o operador :, 18, 21 repetidas, 19NA, 13 sistemas de equa¸˜es, 26 co strings, 13objectos atribui¸˜o, ver atribui¸˜o ca ca vari´veis nominais, ver factores a defini¸˜o, 11 ca vectores, 12 listar, 12 alterar elemento, 14 nomes, 12 alterar tamanho, 14 remover, 12 criar, 13 ver conte´do, 11 u dar nomes aos elementos, 21operadores l´gicos, 20 o modo, 12 opera¸˜es aritm´ticas, 14 co epackages, 9 reciclagem, ver reciclagem instalar, 10 tamanho, 12 usar, 10 vazios, 14 vectoriza¸˜o, 14, 25 caR ajuda, 9 executar, 7 executar comandos, 7 executar comandos v´rias linhas, 17 a gravar estado, 8 instala¸˜o, 7 ca janela de aplica¸˜o, 7 ca packages, ver packages prompt, 7 site, 7 terminar, 8reciclagem, 15, 18, 20, 24s´ries temporais e diferen¸as, 35, 43 c embed, 35 fim, 34, 41 fun¸˜es deslizantes, 43 co gr´ficos, 32 a in´ ıcio, 34, 41 irregulares, 36 criar, 36 fun¸˜es uteis, 39 co ´ packages, 36 janela temporal, 34, 42 juntar, 35, 42 lagging, 35 regulares, 31 criar, 31 fun¸˜es uteis, 33 co ´ valores desconhecidos, 43scoping, 53 lexical scoping, 53sequˆncias, 18 e aleat´rias, 19 o