Tabela de conteúdos
Objetivo
O objetivo desse curso é apresentar os procedimentos básicos necessários ao processamento de dados para realizar os cálculos de cubagem rigorosa do tronco de árvores pela técnica mais simples.
Ao final desse curso você deverá ser capaz de:
- saber o que são vetores no R, bem como os seus atributos básicos;
- saber construir data frames a partir de diferentes vetores ou de leitura de dados externos;
- conseguir executar as seguintes operações com data frames:
- indexação,
- agregação,
- junção;
- saber processar dados de secção de tronco para realizar os cálculos de cubagem rigorosa de um conjunto de árvores.
Vetores e seus Atributos
VETORES é um conjunto de observações do mesmo tipo de variável, isto é, de mesma escala.
No R, podemos criar vetores na linha de comando utilizando a função c
:
x = c(10, 1, 3, 4, -5, 235) x a = c("maça", "peira", "mamão", "abacaxi") a
Podemos criar uma sequência de números inteiros como o operador :
:
y = 1:10 y
As colunas de um data frame funcionam como vetores. Vejamos um exemplo utilizando os dados do arquivo exemplo-caixeta.csv:
cax = read.csv("exemplo-caixeta.csv",head=TRUE) head(cax) cax$cap cax$local
Operações Matemáticas
Quando realizamos uma operação matemática sobre um vetor ela se aplica a cada elemento do vetor individualmente:
2*x y/3 log(y) sqrt(y) sin(x) x cax$cap / (10*pi) cax$h / 10
Podemos também realizar operações lógicas sobre os vetores:
x < 0 x < 200 y > 5
Classes de Vetores
Como em cada vetor todos os elementos são observações de uma mesma variável, para cada tipo de variável teremos uma classe de vetores:
class(y) class(x) class(a)
Também podemos ter vetores que contém as operações lógicas:
op1 = x < 0 op1 class(op1) op2 = y > 5 op2 class(op2)
Em resulo, as classes de vetores no R são:
integer
: vetor de números inteiros;numeric
: vetor de números reais;character
: vetor de variáveis alfa-numéricas;logical
: vetor resultante de operações lógicas.
É importante lembrar que as colunas de um data frame (variáveis), quando evocadas individualmente, são vetores com as suas respectivas classes.
class(cax$arvore) class(cax$cap) class(cax$local) class(cax$especie)
Mas por que as variáveis local
e especie
aparecem como factor
e não como character
?
O R, sendo um ambiente para análise estatística de dados, assume que toda variável alfa-numérica terá uma função na modelagem estatística dos dados. Assim, ao ler um arquivo, ele transforma toda variável alfa-numérica na classe factor
, que tem as propriedades estatísticas de um fator experimental.
Leitura de Arquivos CSV
Para o processamento dos dados, é geralmente mais fácil trabalharmos com a classe character
, então para evitar que o R faça essa transformação automaticamente, utiliza-se o argumento as.is=TRUE
na leitura dos dados.
cax = read.csv("exemplo-caixeta.csv",head=TRUE,as.is=TRUE) class(cax$local) class(cax$especie)
Comprimento de Vetores
Outro atributo essencial de todo vetor é o seu comprimento (length
):
length(y) length(x) length(a) length(cax$cap) length(cax$arvore) length(cax$local) length(cax$especie) length(op1) length(op2)
A Estrutura dos Data Frames
Os data frames são tabelas de dados onde:
- cada linha representa uma observação e
- cada coluna representa uma variável medida na observação.
No exemplo dos dados de caxeta:
head(cax)
cada linha (observação) representa um fuste de árvore medido no campo. A cada fuste foram “associadas” diversas variáveis.
- As variáveis
local
,parcela
,arvore
efuste
são variáveis identificadoras, pois simplesmente identificam cada observação (fuste). - As variáveis
cap
,h
eespecie
são as variáveis efetivamente “medidas” em cada fuste.
Mas para compreendermos o processamento básico de dados no R devemos pensar os data frames de uma outra forma. Um data frame deve ser visto como uma junção de vetores que podem ter classes diferentes. Mas há dois aspectos essenciais nessa junção:
- os vetores tem o mesmo comprimento,
- os elementos dos vetores estão igualmente ordenados, segundo as observações que eles representam.
Vejamos mais um exemplo de data frame a partir do arquivo exemplo-cubagem.csv:
cuba = read.csv("exemplo-cubagem.csv",header=T,as.is=T) head(cuba)
O data frame cuba
contem dados de cubagem de árvores de Eucalyptus grandis de diferentes regiões do Estado de São Paulo. Os seus vetores componentes devem ser entendidos como:
regiao
- vetor que identifica a região de onde as árvores vieram,arvore
- vetor que identifica cada uma das árvores,h_d
- vetor das alturas ao longo do tronco onde os diâmetros das secções foram medidos, ed_h
- vetor dos diâmetros das secções nas respectivas alturas (h_d
).
Para evitar pontos decimais, a altura é apresentada em decímetros (dm) e o diâmetro em milímetros (mm).
Note que nesse data frame as observações são as secções do tronco onde altura (h_d
) e diâmetro (d_h
) foram medidos.
Atributos dos Data Frames
Assim como os vetores que os compõem, os data frames também tem seus atributos.
A classe de um data frame pode ser obtida da mesma forma que a classe dos vetores:
class(cax) class(cuba)
Naturalmente, a classe de um data frame é data.frame
!!
O tamanho de um data frame, no entanto, deve ser obtido de uma forma diferente dos vetores. Se tentarmos obter o comprimento de um data frame teremos:
length(cuba) head(cuba)
Note que o data frame cuba
tem quatro vetores.
Os data frame são objetos bidimensionais, isto é, possuem colunas (vetores) e linhas (observações). A função length
simplesmente retorna o número de colunas do data frame. Para saber adequadamente o tamanho de um data frame devemos perguntar pelas suas DIMENSÕES:
dim(cax) dim(cuba) prod(dim(cax))
Se quisermos saber o número total de elementos num data frame, basta multiplicarmos suas dimensões:
prod(dim(cax)) prod(dim(cuba))
Operações com Data Frames
No R, a organização dos dados em data frames é a forma mais apropriada tanto para o processamento básico dos dados quanto para análise e modelagem dos dados.
Para se realizar o processamento de dados de modo eficiente é necessário se dominar algumas operações com os data frames.
Indexação de Data Frames
Chamamos de INDEXAÇÃO a operação de extrair linhas (observações) e/ou colunas (variáveis) de um data frame.
O operador de indexação no R são os colchetes na seguinte forma: [ , ]
. A vírgula dentro do colchetes separa a indexação de linhas da indexação de colunas. Vejamos alguns exemplos de indexação:
# Indexação de LINHAS cax[ 10, ] # Retorna a décima observação do data frame cuba[ 182, ] # Retorna a observação 182 do data frame cax[ 10:23, ] # Retorna as observações 10 a 23 do data frame cuba[ c(18, 23, 26, 192, 200) , ] # Retorna a observação 182 do data frame # Indexação de LINHAS cax[ , 5] # Retorna a variável 5 ( **''cap''**) do data frame. cuba[ , 2 ] # Retorna a segunda variável (**''regiao''**) do data frame. cax[ , 5:6] # Retorna as variáveis 5 e 6 ( **''cap''** e **''h''**) do data frame. # Indexação de LINHAS E COLUNAS cax[ 1:5 , 5:6] # Retorna as observações 1 a 5 das variáveis 5 e 6 do data frame. cuba[ 107:112 , 3:4 ] # Retorna as observações 107 a 112 das variáveis 3 e 4 do data frame.
Note que a indexação pode ser realizada por vetores.
Os números não são a única forma de indexação no R. Há quatro tipos de índices no R. Cada um deles produz uma forma de indexação diferente:
Vetor de Número Inteiros Positivos
O R retorna os elementos correspondente aos números, sejam linhas ou colunas. Todos os exemplos acima são desse tipo.
Vetor de Número Inteiros Negativos
Nesse caso, o R EXCLUI os elementos correspondentes (linhas ou colunas) e retorna os dados sem elas:
cuba[ -(12:219), ] cuba[ -(12:219), -1 ] cax[ -(15:198), -(1:4) ] cuba[ 1:5, -3] cax[ 1:5, -c(4, 7)]
Vetor "Character"
O vetor character
funciona como NOME dos elementos (linhas ou colunas). Esse tipo de indexação é mais comumente utilizado com as colunas, uma vez que as variáveis sempre terão seus nomes:
colnames(cax) # Nomes das colunas (variáveis) cax[ 1:5, "cap"] cax[ 1:5, c("cap","h")] colnames(cuba) # Nomes das colunas (variáveis) cuba[ 1:5 , "h_d" ] cuba[ 1:5 , c("regiao","d_h") ]
Note que o valor de uma variável caracter devem ser sempre apresentado dentro de aspas duplas (“).
Embora menos comum, essa forma de indexação também pode ser utilizado para seleção de observações (linhas):
rownames(cuba) # Nomes das linhas (observações) cuba2 = cuba[ 1:10, 3:4] rownames(cuba2) paste( "posicao", 1:10 ) # Cola a palavra "posicao" aos números de 1 a 10 rownames(cuba2) = paste( "posicao", 1:10 ) cuba2 cuba2[ "posicao 7", ] cuba2[ paste("posicao", 5:9), ]
Vetor Lógico
Quando um vetor lógico é utilizado como índice, o R retorna aquele elementos correspondentes ao valor TRUE
do vetor lógico.
cax$dap = cax$cap / (pi * 10) cax$ht = cax$h / 10 cax[ cax$dap < 5 , ] cax[ cax$dap >= 10 & cax$dap <= 10.5 , ] cax[ cax$ht < 3, ] cax[ cax$ht > 17, ] cax[ cax$local == "jureia" & cax$dap < 8, ] cax[ cax$local == "chauas" & cax$dap > 18, ]
A tabela abaixo apresenta os símbolos utilizados nas operações lógicas:
Símbolo | Operação |
---|---|
== | Igualdade |
> | Maior |
< | Menor |
>= | Maior ou igual |
⇐ | Menor ou igual |
! | Negação |
!= | Não igual, i.e., diferente |
& | E para junção de duas operações lógicas |
| | OU para junção de duas operações lógicas |
Exercício
Constura dois data frames a partir do data frame cuba
:
- Um data frame contendo a variável
arvore
mas apenas com o DAP das árvores. - Um data frame contendo a variável
arvore
mas apenas com a altura total das árvores
Agregação de Dados em Data Frames
O termo AGREGAÇÃO é empregado para definir a operação de aplicar uma operação matemática num conjunto de dados num nível MAIS detalhado para obter os resultados num nível MENOS detalhado.
Por exemplo, no conjunto de dados dos caixetais, deseja-se saber a área basal das parcelas. Esse resultado é obtido numa sequência de passos:
(1) Calcular a área transversal de cada fuste1).
cax$g = (pi/4) * (cax$dap/100)^2
(2) As áreas transversais dos fustes devem ser somadas para cada parcela, ou seja,
- devemos agregar os dados de área transversal do nível de fuste (= variável a ser agregada)
- para o nível de parcela (= variável índice ou de agregação)
- somando (= função ou operação de agregação).
Esses três elementos compõem os argumentos da função aggregate
utilizada na operação:
cax.parc = aggregate(x = cax$g, by = list(cax$parcela), FUN=sum) head(cax.parc) colnames(cax.parc) = c("parcela","g") # nomeia as variáveis head(cax.parc) # G em m2 cax.parc$g = cax.parc$g * 10000/200 # as parcelas são de 200 m2 head(cax.parc) # G em m2/ha
A função de agregação pode ser definida dentro do comando para facilitar os cálculos:
cax.parc = aggregate(x = cax$g, by = list(cax$parcela), FUN= function(x){sum(x)*10000/200} ) colnames(cax.parc) = c("parcela","g") # nomeia as variáveis head(cax.parc) # G em m2/ha
A agregação pode ser realizada utilizando mais de uma variável de agregação. Por exemplo, deseja-se calcular a densidade das espécies dos caixetais por local:
cax.den = aggregate(x = cax$arvore, by = list(cax$especie, cax$local), FUN= function(x){length(unique(x))*10000/200} ) colnames(cax.den) = c("especie","local","den") # nomeia as variáveis cax.den # densidade em 1/ha
Exercício
Utilizando a equação de volume abaixo, encontre o volume para cada parcela dos caixetais em metros cúbicos por hectare.
v = -0.4448 + 0.0320 * (dap^2) * ht
v
em dm3,dap
em cm, eht
em m.
Exercício
Encontre a dominância das espécies dos caixetais para cada local.
Junção de Data Frames
A junção de data frames pode ser realizada de duas formas:
- alinhando-se as variáveis (colunas) correspondentes, ou
- alinhando-se as observações (linhas) correspondentes.
Na junção de data frames pelas variáveis, os data frames devem ter exatamente as mesmas variáveis. Vejamos um exemplo. Primeiramente vamos separar as observações de um data frame:
cha = cax[ cax$local == "chauas", ] jur = cax[ cax$local == "jureia", ] ret = cax[ cax$local == "retiro", ] head(cha) head(jur) head(ret)
Agora, podemos juntar esses data frames utilizando a função rbind
:
cax.jun = rbind(cha, jur, ret) dim(char) dim(jur) dim(ret) dim(cax.jun) dim(cax)
Na segunda forma de junção, as variáveis diferentes são juntadas segundo as observações correspondentes. Exemplo: caixetais. Deseja-se obter as seguintes informações por espécie:
- DAP e altura médios,
- DAP mínimo e máximo, e
- número de fustes.
dh.m = aggregate(cax[, c("dap","ht")], list(cax$especie), mean) colnames(dh.m) = c("especie","mdap","mht") head(dh.m) d.min = aggregate(cax$dap, list(cax$especie), min) colnames(d.min) = c("especie","dap.min") d.max = aggregate(cax$dap, list(cax$especie), max) colnames(d.max) = c("especie","dap.max") d.nf = aggregate(cax$dap, list(cax$especie), length) colnames(d.nf) = c("especie","nfuste") cax.sp = merge(dh.m, d.min) head(cax.sp) cax.sp = merge(cax.sp, d.max) head(cax.sp) cax.sp = merge(cax.sp, d.nf) head(cax.sp)
Exercício
Utilizando os dados dos caixetais, construa um data frame com as seguintes informações por parcela:
- área basal
- volume
- número de fustes
Exercício
Utilizando os dados dos caixetais, construa um data frame com as seguintes informações por local:
- número de espécies (riqueza),
- índice de diversidade de shannon,
- número de espécies raras (= espécies com somente um fuste na amostra), e
- proporção de espécies raras.
Procedimentos para Cubagem Rigorosa
Os procedimentos apresentados constiuem a base para o processamento de dados no R. Tais procedimentos são suficientes para se realizar os cálculos de cubagem rigorosa de árvores, quando as medições da secção do tronco são realizadas com intervalo constante.
Vejamos os passos necessários para a cubagem rigorosa do volume total do tronco:
(1) Colocar as Variáveis em Unidades Convenientes
Utilizaremos os dados do data frame cuba
. Coloquemos os dados de diâmetro e altura em unidades convenientes:
head(cuba) cuba$hd = cuba$h_d / 10 # altura de dm para m cuba$dh = cuba$d_h / 10 # diametro de mm para cm head(cuba)
(2) Separação da Informação da Ponta do Tronco
Note que a última secção tem diâmetro zero, logo a altura dessa secção é a altura total da árvore.
cuba[ cuba$arvore == 1, ]
Essa secção deve ser separada, pois a ponta do tronco será cubada de forma diferente das demais seções:
cuba.toras = cuba[ cuba$dh != 0, ] cuba.toras[ cuba.toras$arvore == 1, ] cuba.ponta = aggregate(cuba.toras[ , c("hd","dh")], list(regiao=cuba.toras$regiao, arvore=cuba.toras$arvore), function(x) x[length(x)] ) cuba.ponta
(3) Separação das Informação de DAP e Altura Total
Primeiro, separaremos o DAP:
cuba.d = cuba[ cuba$hd == 1.3, c("regiao","arvore","dh")] colnames(cuba.d)[3] = "dap" head(cuba.d)
Segundo, a altura total
cuba.h = cuba[ cuba$dh == 0, c("regiao","arvore","hd")] colnames(cuba.h)[3] = "ht" head(cuba.h)
Terceiro, se junta os dados:
cuba.dh = merge(cuba.d, cuba.h) head(cuba.dh) cuba.dh = merge(cuba.dh, cuba.ponta) head(cuba.dh) rm(cuba.d, cuba.h, cuba.ponta) # Limpando a área
(4) Cubagem Rigorosa das Toras por Smalian
Primeiro é necessário definir uma função para realizar a cubagem rigorosa por Smalian para toras de mesmo comprimento.
A função abaixo realiza a cubagem rigorosa para o tronco inteiro (exceto a ponta) numa única expressão matemática que depende do diâmetro das secções (argumento x
) e do comprimento constante da tora (argumento l
):
smalian.cr = function(x, l) { l*(pi/8)*sum( x[c(1,length(x))]^2, 2*x[-c(1,length(x))]^2) }
Para realizar a cubagem basta aplicá-la na agregação dos dados de toras:
cuba.vol1 = aggregate(cuba.toras$dh/100, list(cuba.toras$regiao, cuba.toras$arvore), smalian.cr, l=1) colnames(cuba.vol1) = c("regiao","arvore","volume") cuba.vol1
Podemos agora juntar os dados de volume com os demais dados das árvores:
cuba.v = merge(cuba.dh, cuba.vol1) cuba.v
(5) Volume Total das Árvores
Assumindo que as pontas tem volume de um cone, podemos calcular esse último volume por árvore:
cuba.v$vp = (1/3) * (pi/4) * (cuba.v$dh/100)^2 * (cuba.v$ht - cuba.v$hd) cuba.v
Assim podemos obter o volume total de cada árvore:
cuba.v$voltot = cuba.v$volume + cuba.v$vp cuba.v
Concluímos a operação, mantendo apenas as variáveis de interesse:
cuba.arv = cuba.v[ , c("regiao","arvore","dap","ht","voltot")] cuba.arv plot( voltot ~ I(dap^2*ht), data = cuba.arv)
Exercício
Repita a operação de cubagem rigorosa com os dados do arquivo exemplo-cubagem-2.csv. Encontre:
- o volume total com casca e
- o volume total sem casca.
Autor
João Luís Ferreira Batista
Laboratório de Biometria Ecológica
Centro de Métodos Quantitativos
Departamento de Ciências Florestais
Escola Superior de Agricultura "Luiz de Queiroz"
UNIVERSIDADE DE SÃO PAULO