Diferenças
Aqui você vê as diferenças entre duas revisões dessa página.
| Próxima revisão | Revisão anterior | ||
| 03_apostila:programar_ale [2020/08/12 09:04] – edição externa 127.0.0.1 | 03_apostila:programar_ale [2020/09/23 20:13] (atual) – link adalardo | ||
|---|---|---|---|
| Linha 1: | Linha 1: | ||
| + | <WRAP tabs> | ||
| + | * [[02_tutoriais: | ||
| + | * [[01_curso_atual: | ||
| + | * [[03_apostila: | ||
| + | </ | ||
| + | ====== 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. | ||
| + | |||
| + | 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**, | ||
| + | |||
| + | Vejamos um exemplo. | ||
| + | <code rsplus> | ||
| + | > zoo | ||
| + | | ||
| + | 4 10 | ||
| + | > class( zoo ) | ||
| + | [1] " | ||
| + | > length( zoo ) | ||
| + | [1] 4 | ||
| + | > names( zoo ) | ||
| + | [1] " | ||
| + | > | ||
| + | </ | ||
| + | |||
| + | O vetor ''' | ||
| + | |||
| + | Qualquer vetor sempre terá uma classe e um comprimento, | ||
| + | <code rsplus> | ||
| + | > b | ||
| + | [1] 1 2 3 4 5 6 7 8 | ||
| + | > class( b ) | ||
| + | [1] " | ||
| + | > length( b ) | ||
| + | [1] 8 | ||
| + | > names( b ) | ||
| + | NULL | ||
| + | > | ||
| + | </ | ||
| + | |||
| + | A função ''' | ||
| + | <code rsplus> | ||
| + | > zoo | ||
| + | | ||
| + | 4 10 | ||
| + | > attributes( zoo ) | ||
| + | $names | ||
| + | [1] " | ||
| + | |||
| + | > b | ||
| + | [1] 1 2 3 4 5 6 7 8 | ||
| + | > attributes( b ) | ||
| + | NULL | ||
| + | > | ||
| + | </ | ||
| + | |||
| + | |||
| + | |||
| + | ==== Funções ==== | ||
| + | |||
| + | As funções do R também são objetos, mas da classe ''' | ||
| + | <code rsplus> | ||
| + | > class( ls ) | ||
| + | [1] " | ||
| + | > class( log ) | ||
| + | [1] " | ||
| + | > class( sin ) | ||
| + | [1] " | ||
| + | > | ||
| + | </ | ||
| + | |||
| + | 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), | ||
| + | pattern) | ||
| + | NULL | ||
| + | > args( log ) | ||
| + | function (x, base = exp(1)) | ||
| + | NULL | ||
| + | > | ||
| + | </ | ||
| + | |||
| + | Algumas funções matemáticas, | ||
| + | <code rsplus> | ||
| + | > args( sin ) | ||
| + | NULL | ||
| + | > sin | ||
| + | .Primitive(" | ||
| + | > | ||
| + | > args( exp ) | ||
| + | NULL | ||
| + | > exp | ||
| + | .Primitive(" | ||
| + | > | ||
| + | </ | ||
| + | |||
| + | |||
| + | |||
| + | |||
| + | |||
| + | |||
| + | |||
| + | |||
| + | |||
| + | ==== 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. | ||
| + | <code rsplus> | ||
| + | > length( zoo ) | ||
| + | [1] 4 | ||
| + | > zoo.comp = length( zoo ) | ||
| + | > zoo.comp | ||
| + | [1] 4 | ||
| + | > class( zoo ) | ||
| + | [1] " | ||
| + | > zoo.class = class( zoo ) | ||
| + | > zoo.class | ||
| + | [1] " | ||
| + | > class( zoo.class ) | ||
| + | [1] " | ||
| + | > names( zoo ) | ||
| + | [1] " | ||
| + | > class( names( zoo ) ) | ||
| + | [1] " | ||
| + | > length( names( zoo ) ) | ||
| + | [1] 4 | ||
| + | > | ||
| + | </ | ||
| + | |||
| + | |||
| + | Quando o R nos mostra, como resultado de uma operação, | ||
| + | <code rsplus> | ||
| + | > b | ||
| + | [1] 1 2 3 4 5 6 7 8 | ||
| + | > names( b ) | ||
| + | NULL | ||
| + | > b[ b > 10 ] | ||
| + | integer(0) | ||
| + | > | ||
| + | </ | ||
| + | |||
| + | Veja que o valor ''' | ||
| + | <code rsplus> | ||
| + | > zoo2 = zoo | ||
| + | > zoo2 | ||
| + | | ||
| + | 4 10 | ||
| + | > names( zoo2 ) | ||
| + | [1] " | ||
| + | > names( zoo2 ) = NULL | ||
| + | > zoo2 | ||
| + | [1] 4 10 2 45 | ||
| + | > names( zoo2 ) | ||
| + | NULL | ||
| + | > | ||
| + | </ | ||
| + | |||
| + | |||
| + | === Exercícios === | ||
| + | |||
| + | <box 100% left red | // | ||
| + | Considere o vetor com nome de espécies: | ||
| + | |||
| + | > sp | ||
| + | [1] " | ||
| + | [4] " | ||
| + | > | ||
| + | |||
| + | Para obter a freqüência das espécies podemos usar a função ''' | ||
| + | <code rsplus> | ||
| + | > table( sp ) | ||
| + | sp | ||
| + | | ||
| + | | ||
| + | > | ||
| + | </ | ||
| + | |||
| + | Qual a classe do objeto que a função ''' | ||
| + | </ | ||
| + | |||
| + | |||
| + | |||
| + | <box 100% left red | // | ||
| + | Qual a classe do objeto produzido pelo comando ''' | ||
| + | </ | ||
| + | |||
| + | |||
| + | |||
| + | |||
| + | |||
| + | |||
| + | |||
| + | |||
| + | ===== 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. | ||
| + | |||
| + | 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(" | ||
| + | } | ||
| + | |||
| + | </ | ||
| + | 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 " | ||
| + | * **entre os parênteses " | ||
| + | * **comando return(" | ||
| + | |||
| + | |||
| + | Vejamos alguns exemplos simples: | ||
| + | <code rsplus> | ||
| + | |||
| + | ##criar um vetor de dados com 20 valores aleatórios de uma distribuição Poisson | ||
| + | |||
| + | dados.dens< | ||
| + | |||
| + | ##funcão para calcular média | ||
| + | |||
| + | media.curso < | ||
| + | { | ||
| + | soma=sum(x) | ||
| + | nobs=length(x) | ||
| + | media=soma/ | ||
| + | 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 < | ||
| + | { | ||
| + | if(rmNA==TRUE) | ||
| + | { | ||
| + | dados=(na.omit(x)) | ||
| + | dif=length(x)-length(dados) | ||
| + | cat(" | ||
| + | } | ||
| + | else | ||
| + | { | ||
| + | dados=x | ||
| + | } | ||
| + | soma=sum(dados) | ||
| + | nobs=length(dados) | ||
| + | media=soma/ | ||
| + | return(media) | ||
| + | } | ||
| + | |||
| + | ###calcular a média do objeto dados | ||
| + | media.curso(dados.dens) | ||
| + | |||
| + | |||
| + | ########################################## | ||
| + | ###função para calcular variância | ||
| + | |||
| + | var.curso< | ||
| + | { | ||
| + | media=media.curso(x) | ||
| + | dados=na.omit(x) | ||
| + | disvquad=(dados-media)^2 | ||
| + | variancia=sum(disvquad)/ | ||
| + | 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< | ||
| + | { | ||
| + | id=var.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 | ||
| + | para verificar a significância dos dados | ||
| + | |||
| + | test.ID <- function(x) | ||
| + | { | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | { cat(" | ||
| + | else{} | ||
| + | if(qui < critico.qui[1]) | ||
| + | { cat(" | ||
| + | | ||
| + | if(qui> | ||
| + | { cat(" | ||
| + | | ||
| + | | ||
| + | | ||
| + | } | ||
| + | |||
| + | ############ | ||
| + | |||
| + | |||
| + | </ | ||
| + | === Exercícios === | ||
| + | |||
| + | <box 100% left red | // | ||
| + | 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 100% left red | // | ||
| + | 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: // | ||
| + | </ | ||
| + | |||
| + | |||
| + | <box 100% left red | // | ||
| + | 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**: | ||
| + | |||
| + | * **Coeficiente de Green**: IG = (ID-1)/ | ||
| + | |||
| + | * **Índice de Morisita**: | ||
| + | | ||
| + | onde: | ||
| + | |||
| + | n = tamanho da amostra; | ||
| + | |||
| + | |||
| + | Construa uma função para cada um desses índices, assumindo como argumento os valores de xi. | ||
| + | Aplique | ||
| + | |||
| + | </ | ||
| + | |||
| + | |||
| + | |||
| + | |||
| + | |||
| + | ==== 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=" | ||
| + | > plot( egr$dap, egr$ht ) | ||
| + | </ | ||
| + | |||
| + | |||
| + | Para qualquer argumento podemos definir um **valor default** apresentando esse valor junto com argumento na definição da função: | ||
| + | <code rsplus> | ||
| + | > myplot <- function(..., | ||
| + | > myplot( cax$dap, cax$h ) | ||
| + | > myplot( ht ~ dap, data=egr ) | ||
| + | </ | ||
| + | |||
| + | O exemplo acima também mostra a função do argumento **". . ." | ||
| + | |||
| + | |||
| + | |||
| + | === Exercícios === | ||
| + | |||
| + | <box 100% left red | // | ||
| + | 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. | ||
| + | </ | ||
| + | |||
| + | |||
| + | |||
| + | ===== 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(" | ||
| + | [1] " | ||
| + | > | ||
| + | </ | ||
| + | |||
| + | Para alterar o editor padrâo use o comando: | ||
| + | <code rsplus> | ||
| + | > options( editor= " | ||
| + | </ | ||
| + | |||
| + | |||
| + | No caso de editar sua função num editor externo ao R (p.ex., no arquivo ''' | ||
| + | <code rsplus> | ||
| + | > source( " | ||
| + | </ | ||
| + | É importante que o arquivo editado externamente (''' | ||
| + | |||
| + | |||
| + | === Exercícios === | ||
| + | |||
| + | <box 100% left red | // | ||
| + | Experimente definir um editor com o qual você consiga trabalhar (''' | ||
| + | </ | ||
| + | |||
| + | |||
| + | <box 100% left red | // | ||
| + | Construa funções para computar os seguintes índices de diversidade de espécies: | ||
| + | |||
| + | |||
| + | * Índice de Shannon: | ||
| + | |||
| + | * Índice de Simpson: | ||
| + | |||
| + | onde p// | ||
| + | |||
| + | 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. | ||
| + | </ | ||
| + | |||
| + | |||
| + | |||
| + | |||
| + | |||
| + | ==== Realizando " | ||
| + | |||
| + | 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( " | ||
| + | { | ||
| + | comando 1 | ||
| + | comando 2 | ||
| + | comando 3 | ||
| + | . . . | ||
| + | comando n | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | 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. | ||
| + | |||
| + | Vejamos um exemplo: // | ||
| + | <code rsplus> | ||
| + | > # | ||
| + | > # Convergência da distribuição t de Student para distribuição Normal Padronizada | ||
| + | > # | ||
| + | > curve(dnorm(x), | ||
| + | > for(gl in 1:200) | ||
| + | + { | ||
| + | + curve(dt(x, gl), -4, 4, add=TRUE, col=" | ||
| + | + } | ||
| + | > | ||
| + | </ | ||
| + | |||
| + | No exemplo acima temos: | ||
| + | * ''' | ||
| + | * ''' | ||
| + | |||
| + | |||
| + | |||
| + | |||
| + | === Exercícios === | ||
| + | |||
| + | <box 100% left red | // | ||
| + | Construa uma função para demonstrar o Teorema Central do Limite. | ||
| + | </ | ||
| + | |||
| + | ==== Solução Vetorial x Loop ==== | ||
| + | |||
| + | Sendo um **ambiente vetorial**, | ||
| + | |||
| + | |||
| + | Considere o problema o seguinte problema: temos a localização espacial de plantas num plano cartesiano com coordenadas **(x, | ||
| + | <code rsplus> | ||
| + | > x = runif(100) | ||
| + | > y = runif(100) | ||
| + | > plot(x,y) | ||
| + | </ | ||
| + | |||
| + | O objetivo é obter as **distâncias** entre as plantas duas-a-duas. | ||
| + | <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 | ||
| + | } | ||
| + | } | ||
| + | dist | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | 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 | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | 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 | ||
| + | </ | ||
| + | |||
| + | **Não tente rodar o exemplo acima com 1000 ou mais observações**, | ||
| + | |||
| + | **CONCLUSÃO: | ||
| + | |||
| + | |||
| + | === Exercícios === | ||
| + | |||
| + | |||
| + | |||
| + | <box 100% left red | // | ||
| + | Construa uma função que gera uma tabela de fitossociologia. | ||
| + | </ | ||
| + | |||
| + | ==== 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, | ||
| + | |||
| + | <box 80% red> | ||
| + | <code rsplus> | ||
| + | ================================================================= | ||
| + | | ||
| + | ================================================================= | ||
| + | $ | ||
| + | | ||
| + | | ||
| + | | ||
| + | : | ||
| + | | ||
| + | | ||
| + | < > <= >= == != | ||
| + | | ||
| + | & && | ||
| + | | ||
| + | << | ||
| + | ================================================================= | ||
| + | </ | ||
| + | </ | ||