03_apostila:programar_ale

Diferenças

Aqui você vê as diferenças entre duas revisões dessa página.

Link para esta página de comparações

Próxima revisão
Revisão anterior
03_apostila:programar_ale [2020/08/12 09:04] – edição externa 127.0.0.103_apostila:programar_ale [2020/09/23 20:13] (atual) – link adalardo
Linha 1: Linha 1:
  
 +<WRAP tabs>
 +  * [[02_tutoriais:tutorial8:start|Tutorial]]
 +  * [[01_curso_atual:exercicios9| Exercícios]]
 +  * [[03_apostila:programar_ale| Apostila]]
 +</WRAP>
 +====== 9. Noções de Programação  ======
 +
 +
 +
 +===== R: Um Ambiente Orientado a Objetos =====
 +
 +
 +
 +==== Atributos ====
 +
 +Até esse ponto do curso, foi visto que existem no R funções, variáveis e vetores.  Todos esses ítens são chamados genericamente de **objetos**.  
 +
 +Veremos no decorrer do curso vários outros **objetos** do R.  A importância do conceito de **objeto** num ambiente de trabalho de análise de dados é que os objetos possuem **atributos**, os quais podem variar em função do tipo de objeto.
 +
 +Vejamos um exemplo.  
 +<code rsplus>
 +> zoo
 + onça  anta  tatu guará
 +    4    10        45
 +> class( zoo )
 +[1] "numeric"
 +> length( zoo )
 +[1] 4
 +> names( zoo )
 +[1] "onça"  "anta"  "tatu"  "guará"
 +>                                                                     
 +</code>
 +
 +O vetor '''zoo''' é um vetor de classe '''numeric''', de comprimento ('''length''') 4 e com nomes ('''names'''): onça, anta, tatu e guará.  Classe, comprimento e nomes são os atributos típicos de vetores.
 +
 +Qualquer vetor sempre terá uma classe e um comprimento, mas o atributo '''names''' é opcional:
 +<code rsplus>
 +> b
 +[1] 1 2 3 4 5 6 7 8
 +> class( b )
 +[1] "integer"
 +> length( b )
 +[1] 8
 +> names( b )
 +NULL
 +>         
 +</code>
 +
 +A função '''attributes''' nos mostra os atributos de um objeto, mas é de uso limitado no caso de vetores:
 +<code rsplus>
 +> zoo
 + onça  anta  tatu guará
 +    4    10        45
 +> attributes( zoo )
 +$names
 +[1] "onça"  "anta"  "tatu"  "guará"
 +
 +> b
 +[1] 1 2 3 4 5 6 7 8
 +> attributes( b )
 +NULL
 +>   
 +</code>
 +
 +
 +
 +==== Funções ====
 +
 +As funções do R também são objetos, mas da classe '''function''':
 +<code rsplus>
 +> class( ls )
 +[1] "function"
 +> class( log )
 +[1] "function"
 +> class( sin )
 +[1] "function"
 +
 +</code>
 +
 +No caso das funções, podemos associar a elas os **argumentos** que elas necessitam para serem executadas:
 +<code rsplus>
 +> args( ls )
 +function (name, pos = -1, envir = as.environment(pos), all.names = FALSE,
 +    pattern)
 +NULL
 +> args( log )
 +function (x, base = exp(1))
 +NULL
 +>    
 +</code>
 +
 +Algumas funções matemáticas, no entanto, tem sempre apenas um argumento e são consideradas **funções primitivas**:
 +<code rsplus>
 +> args( sin )
 +NULL
 +> sin
 +.Primitive("sin")
 +>
 +> args( exp )
 +NULL
 +> exp
 +.Primitive("exp")
 +>   
 +</code>
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +==== Mundo dos Objetos ====
 +
 +Um aspecto importante num ambiente orientado a objetos é que **tudo** o que o ambiente trabalha são objetos e o ambiente não pode trabalhar com nada que não seja um objeto conhecido.   Inclui nessa categoria tudo aquilo que o R apresenta na tela, por isso toda saída do R pode ser guardada num objeto:
 +<code rsplus>
 +> length( zoo )
 +[1] 4
 +> zoo.comp = length( zoo )
 +> zoo.comp
 +[1] 4
 +> class( zoo )
 +[1] "numeric"
 +> zoo.class = class( zoo )
 +> zoo.class
 +[1] "numeric"
 +> class( zoo.class )
 +[1] "character"
 +> names( zoo )
 +[1] "onça"  "anta"  "tatu"  "guará"
 +> class( names( zoo ) )
 +[1] "character"
 +> length( names( zoo ) )
 +[1] 4
 +>        
 +</code>
 +
 +
 +Quando o R nos mostra, como resultado de uma operação,  valores como '''NULL'''  e '''integer(0)''' ele está dizendo que o resultado é **vazio**, isto é, não há resultado: 
 +<code rsplus>
 +> b
 +[1] 1 2 3 4 5 6 7 8
 +> names( b )
 +NULL
 +> b[ b > 10 ]
 +integer(0)
 +>  
 +</code>
 +
 +Veja que o valor '''NULL''' é um valor válidos que podem ser utilizados.
 +<code rsplus>
 +> zoo2 = zoo
 +> zoo2
 + onça  anta  tatu guará
 +    4    10        45
 +> names( zoo2 )
 +[1] "onça"  "anta"  "tatu"  "guará"
 +> names( zoo2 ) = NULL
 +> zoo2
 +[1]  4 10  2 45
 +> names( zoo2 )
 +NULL
 +>       
 +</code>
 +
 +
 +=== Exercícios ===
 +
 +<box 100% left red | //**Exercício 7.1:** Freqüência de Espécies  // >
 +Considere o vetor com nome de espécies:
 +
 +> sp
 +[1] "Myrcia sulfiflora"      "Syagrus romanzoffianus" "Tabebuia cassinoides"
 +[4] "Myrcia sulfiflora"
 +>
 +
 +Para obter a freqüência das espécies podemos usar a função '''table''':
 +<code rsplus>
 +> table( sp )
 +sp
 +     Myrcia sulfiflora Syagrus romanzoffianus   Tabebuia cassinoides
 +                                          1                      1
 +
 +</code>
 +
 +Qual a classe do objeto que a função '''table''' retorna?  Quais são os seus attributos?
 +</box>
 +
 +
 +
 +<box 100% left red | //**Exercício 7.2:** Classe da Classe  // >
 +Qual a classe do objeto produzido pelo comando '''class( x )'''? 
 +</box>
 +
 +
 +
 +
 +
 +
 +
 +
 +===== Construindo Funções Simples =====
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +
 +==== A Estrutura Básica de uma Função ====
 +
 +
 +Toda manipulação de dados e análises gráficas e estatísticas no R são realizadas através de funções.  Entretanto, você não precisa ser um programador experimentado para construir algumas funções simples para facilitar a atividade de manipulação de dados.
 +
 +A estrutura básica de uma função é:
 +<code rsplus>
 +
 +> minha.funcao <- function( argumento1, argumento2, argumento3, . . .)
 +                                    {
 +
 +                                            comando 1
 +
 +                                            comando 2
 +                                            comando 3
 +                                            . . .
 +                                            comando n
 +                                            return("resultado")
 +                                    }
 +
 +</code>
 +Os elementos dessa expressão são:
 +  * **minha.funcao** é o nome que a nova função receberá;
 +  * **function** é a expressão no R que cria uma nova função;
 +  * **entre as chaves "{}"** são listados os comandos da função, sempre com um comando por linha;
 +  * **entre os parênteses "()"** são listados (separados por vírgula) os argumentos necessários a função;
 +  * **comando return("resultado") ** retorna os resultados, caso falte, será apresentado o resultado do último comando (comando n). 
 +
 +
 +Vejamos alguns exemplos simples:
 +<code rsplus>
 +
 +##criar um vetor de dados com 20 valores aleatórios de uma distribuição Poisson 
 +
 +dados.dens<-rpois(20,lambda=6)
 +
 +##funcão para calcular média
 +
 +media.curso <-function(x,rmNA=TRUE)  
 + {
 + soma=sum(x)
 + nobs=length(x)
 + media=soma/nobs
 + return(media)
 + }
 +
 +##Vamos agora preparar uma função mais elaborada, considerando a
 +##presença e excluíndo NA por padrão, e lançando mensagem na tela 
 +##sobre o número de NAs removidos. Note que é uma função com dois argumentos
 +##que permite ao usuário tomar a decisão de remover ou não NAs e avisando, 
 +##diferente da função mean() 
 +
 +
 +media.curso <-function(x,rmNA=TRUE)  
 + {
 + if(rmNA==TRUE)
 + {
 + dados=(na.omit(x))
 + dif=length(x)-length(dados)
 + cat("\t", dif," valores NA excluídos\n")
 + }
 + else
 + {
 + dados=x
 + }
 + soma=sum(dados)
 + nobs=length(dados)
 + media=soma/(nobs)
 + return(media)
 + }
 +
 +###calcular a média do objeto dados
 +media.curso(dados.dens)
 +
 +
 +##########################################
 +###função para calcular variância
 +
 +var.curso<-function(x)
 + {
 + media=media.curso(x)
 + dados=na.omit(x)
 + disvquad=(dados-media)^2
 + variancia=sum(disvquad)/(length(dados)-1)
 + return(variancia)
 + }
 +
 +###Calcular a variância de dados
 +var.curso(dados.dens)
 +
 +###Tomando dados.dens como a contagem de uma espécie em uma amostra de 20 parcelas de 20x20m, 
 +###podemos verificar o padrão de dispersão dessa espécie, utilizando o Índice de Dispersão (razão variância / média)
 +
 +ID.curso<-function(x)
 + {
 + id=var.curso(x)/media.curso(x)
 + return(id)
 + }
 +
 +##Calcular o  coeficiente de dispersão 
 +
 +ID.curso(dados.dens)
 +
 +## quando o valor é próximo a 1 a distribuição é considerada aleatória. 
 +## podemos fazer um teste de significância  pela aproximação com o valor Qui-Quadrado
 +para verificar a significância dos dados
 +
 +test.ID <- function(x)
 +        { 
 +         dados=na.omit(x)
 +    med=media.curso(x)
 +    dev.quad=(dados-med)^2
 +    qui=sum(dev.quad)/med
 +         critico.qui<-qchisq(c(0.025,0.975),df=(length(dados)-1))
 +          if(critico.qui[1]<=qui & critico.qui[2]>=qui)
 + { cat("\t distribuição aleatória para alfa=0.05\n")}
 +       else{}
 + if(qui < critico.qui[1]) 
 +            { cat("\t","distribuição agregada, p<0.025 \n")}
 +     else{}
 + if(qui>critico.qui[2])
 + { cat("\t","distribuição regular, p>0.975 \n")}
 +    resulta=c(qui,critico.qui)
 +    names(resulta)<-c("qui-quadrado", "critico 0.025", "critico 0.975")
 +         return(resulta)
 +         }
 +
 +############
 +
 +
 +</code>
 +=== Exercícios ===
 +
 +<box 100% left red | //**Exercício 7.3:** QUE FRIO!  // >
 +Construa uma função que calcula automaticamente o valor de graus Celsius, sabendo-se a temperatura em Fahrenheit.
 +
 + 
 +C° = 5/9 * (F°(temperatura dada) - 32)
 +
 +</box>
 +
 +
 +<box 100% left red | //**Exercício 7.4:** Somatório do Primeiros Números Naturais  // >
 +Construa uma função que calcula o somatório dos primeiros //n// números naturais.
 +
 +Por exemplo se //n=4// a função deve retornar o valor: //1+2+3+4//.
 +</box>
 +
 +
 +<box 100% left red | //**Exercício 7.5:** Índices de Dispersão I  // >
 +Existe uma série de índices de dispersão baseados em dados de contagem para verificar o padrão espacial de uma espécie.
 +
 +Alguns deles são:
 +  * **Razão Variância-Média**: ID = variância / média;
 +
 +  * **Coeficiente de Green**: IG = (ID-1)/(n-1);
 +
 +  * **Índice de Morisita**: 
 +                     {{:03_apostila:indice_morisita.jpg|}}
 +onde:
 + 
 +      n = tamanho da amostra;       xi= número de indivíduos na i -ésima unidade amostral 
 +
 +
 +Construa uma função para cada um desses índices, assumindo como argumento os valores de xi. 
 +Aplique  aos dados de caixetais, verificando a dispersão da árvores de caixeta em cada caixetal.
 +
 +</box>
 +
 +
 +
 +
 +
 +==== Definindo Argumentos ====
 +
 +Todos argumentos de uma função tem seu respectivo nome.  Ao evocar a função podemos fazê-lo de duas formas:
 +  * utilizando o **nome** dos argumentos **em qualquer ordem**;
 +  * utilizando a **ordem** dos argumentos, mas **omitindo** os nomes.
 +<code rsplus>
 +> plot( col="red", pch=2, y=egr$ht, x=egr$dap )
 +> plot( egr$dap, egr$ht )
 +</code>
 +
 +
 +Para qualquer argumento podemos definir um **valor default** apresentando esse valor junto com argumento na definição da função:
 +<code rsplus>
 +> myplot <- function(..., col="red") { plot(..., col="red") }
 +> myplot( cax$dap, cax$h )
 +> myplot( ht ~  dap, data=egr )
 +</code>
 +
 +O exemplo acima também mostra a função do argumento **". . ."**.  Esse argumento representa **qualquer argumento adicional** que desconhecemos, mas que desejamos que seja passado para as funções dentro da função que estamos construindo.
 +
 +
 +
 +=== Exercícios ===
 +
 +<box 100% left red | //**Exercício 7.6:** Gráfico de Whittaker  // >
 +Faça uma função para construir o gráfico de diversidade de espécies de Whittaker: logaritmo da abundância contra a ordem (descrescente) da abundância das espécies.  Construa essa função de forma que qualquer parâmetro gráfico possa ser alterado.
 +</box>
 +
 +
 +
 +===== Trabalhando com Funções mais Complexas =====
 +
 +==== Um Aspecto Prático ====
 +
 +Para saber qual é o editor padrão do R use o comando:
 +<code rsplus>
 +> getOption("editor")
 +[1] "vi"
 +
 +</code>  
 +
 +Para alterar o editor padrâo use o comando:
 +<code rsplus>
 +> options( editor= "gedit" )       # Faz o editor "gedit" ser o editor padrão do R 
 +</code>
 +
 +
 +No caso de editar sua função num editor externo ao R (p.ex., no arquivo '''minhas-funcoes.R'''),  você traz o código para dentro do R utilizando o comando **"source"**:
 +<code rsplus>
 +> source( "minhas-funcoes.R" )
 +</code>
 +É importante que o arquivo editado externamente ('''minhas-funcoes.R''') seja um arquivo **ASCII** sem qualquer símbolo especial.
 +
 +
 +=== Exercícios ===
 +
 +<box 100% left red | //**Exercícios:** Editando Funções Externamente  // >
 +Experimente definir um editor com o qual você consiga trabalhar ('''gedit'''?) e refaça os exercícios anteriores salvando todos os códigos num arquivo externo.
 +</box>
 +
 +
 +<box 100% left red | //**Exercícios:** Índices de Diversidade de Espécies  // >
 +Construa funções para computar os seguintes índices de diversidade de espécies:
 +
 +
 +  * Índice de Shannon:  ''H = - ∑ (p//i// * ln( p//i// ))''
 +
 +  * Índice de Simpson:  ''D = ∑(p//i//^2)'' 
 +
 +onde  p//i//  é a proporção da espécie //i//
 +
 +Considere que o argumento de sua função será uma matriz com a abundância das espécies sendo as 
 +parcelas amostradas nas colunas. Considere a possibilidade de haver NA nessa matrix e a remoção dele.
 +</box>
 +
 +
 +
 +
 +
 +==== Realizando "Loops" ====
 +
 +Em linguagem de programação um **loop** é quando você força um programa a executar uma série de comandos repedidas vêzes.
 +
 +A estrutura de loop no R é:
 +<code rsplus>
 +                       for( "variável"  in  "vetor de valores")
 +                       {
 +                              comando 1
 +                              comando 2
 +                              comando 3
 +                              . . .
 +                              comando n
 +                       }
 +</code>
 +
 +A palavra **for** é o chamado do loop.  Dentro dos parênteses se define uma variável seguida da palavra **in** e um vetor de valores que a variável deverá assumir.  Dentro das chaves se lista os comandos que devem ser repeditos a cada passo do loop.  
 +
 +Vejamos um exemplo: //Convergência da distribuição t de Student para distribuição Normal Padronizada//:
 +<code rsplus>
 +> #
 +> # Convergência da distribuição t de Student para distribuição Normal Padronizada
 +> #
 +> curve(dnorm(x), from=-4, to=4, col="red", lwd=6)
 +> for(gl in 1:200)
 ++ {
 ++      curve(dt(x, gl), -4, 4, add=TRUE, col="green")
 ++ }
 +>   
 +</code>
 +
 +No exemplo acima temos:
 +  * '''gl''' é a variável definida para o loop;
 +  * '''1:200''' é o vetor de valores que a variável assumirá, logo, o loop será repetido 200 vêzes.
 +
 +
 +
 +
 +=== Exercícios ===
 +
 +<box 100% left red | //**Exercícios:** Loop para Demonstrar o TCL  // >
 +Construa uma função para demonstrar o Teorema Central do Limite.
 +</box>
 +
 +==== Solução Vetorial x Loop ====
 +
 +Sendo um **ambiente vetorial**,  os //loops// não são uma opção muito eficiente para computação dentro do R.  Em geral, o R é mais eficiente se encontrarmos uma **solução vetorial** para problemas de computação que aparentemente exigem um loop.  A solução vetorial, entretanto, costuma ser mais exigente em termos do tamanho de memória RAM do computador.
 +
 +
 +Considere o problema o seguinte problema: temos a localização espacial de plantas num plano cartesiano com coordenadas **(x,y)**.  Por exemplo:
 +<code rsplus>
 +> x = runif(100)
 +> y = runif(100)
 +> plot(x,y)
 +</code>
 +
 +O objetivo é obter as **distâncias** entre as plantas duas-a-duas.  Primeiro consideremos uma solução através de loop:
 +<code rsplus>
 +inter.edist = function(x, y)
 +{
 + n = length(x)
 + dist  <- c()
 + for(i in 1:(n-1))
 + {
 + for(j in (i+1):n)
 + {
 + dist  <- c(dist, sqrt( (x[i] - x[j])^2 + (y[i] - y[j])^2 ))
 + }
 + }
 + dist
 +}
 +</code>
 +
 +Consideremos agora uma solução vetorial:
 +<code rsplus>
 +inter.edist.v = function(x, y)
 +{
 + xd <- outer( x, x, "-" )
 + yd <- outer( y, y, "-" )
 + z <- sqrt( xd^2 + yd^2 )
 + dist <- z[ row(z) > col(z) ]
 + dist
 +}
 +</code>
 +
 +Qual dessas soluções é mais eficiente em termos do uso do tempo?
 +<code rsplus>
 +> x = runif(100)
 +> y = runif(100)
 +>
 +> system.time( inter.edist( x, y ) )
 +[1] 0.140 0.008 0.149 0.000 0.000
 +>
 +> system.time( inter.edist.v( x, y ) )
 +[1] 0.008 0.000 0.009 0.000 0.000  
 +</code>
 +
 +**Não tente rodar o exemplo acima com 1000 ou mais observações**, pois o tempo fica **realmente longo** para versão em loop.
 +
 +**CONCLUSÃO:** use apenas **pequenos loops** no R!!!
 +
 +
 +=== Exercícios ===
 +
 +
 +
 +<box 100% left red | //**Exercícios:** Tabela de Fitossociologia  // >
 +Construa uma função que gera uma tabela de fitossociologia.  Utilize os dados de caixeta ([[dados:dados-caixeta]]) como teste.
 +</box>
 +
 +==== APÊNDICE: Tabela de Operadores do R ====
 +
 +Outro aspecto formal importante da linguagem R é a ordem de prioridade de seus operadores. Além das regras de precedência usuais para as operações matemáticas, é essencial conhecer a prioridade dos outros operadores:
 +
 +<box 80% red>
 +<code rsplus>
 +=================================================================
 + OPERADOR         DESCRIÇÃO                          PRIORIDADE
 +=================================================================
 +  $               seleção de componentes                ALTA
 +  [[            indexação                               |
 +                potência                                |
 +                menos unitário                          |
 + :                operador de seqüência                   |
 + %nome%           operadores especiais                    |
 +  /             multiplicação, divisão                  |
 +< > <= >= == !=   comparação                              |
 +                não                                     |
 + & &&  |  ||      e, ou                                   |
 +                fórmula estatística                     \/
 + <<- <- -> =      atribuição                            Baixa
 +=================================================================
 +</code>
 +</box>