* [[02_tutoriais:tutorial3:start|Tutorial]] * [[01_curso_atual:exercicios3| Exercícios]] * [[03_apostila:04-dados| Apostila]] ====== 3. Tutoriais de Leitura e Manipulação de dados no R ====== //**__Os 10 mandamentos do R__**// Agora que já tem alguma experiência com a linguagem, veja os 10 mandamentos do R! Ao final do curso revisite esses mandamentos e avalie quantos pecados deve confessar. * ** [[:dezmanda]] ** ====== Objetos de Dados ====== ===== Vetores como estrutura básica de dados ===== {{youtube>Q00jbbzCg6M}} Nos tutoriais anteriores, nós usamos uma classe de objetos que é a estrutura básica de armazenamento de dados no R, a classe de objetos vetores. Vamos revisitar alguns conceitos neste tópico, criando um vetor de dados numéricos, chamado ''num'', que seja uma sequência de valores de 0 a 15 divididos em 7 valores equidistantes. num <- seq(0, 15, len=7) Agora vamos olhar os valores do objeto criado, em seguida elevar cada valor ao quadrado, atribuindo o resultado ao objeto "num2". Em seguida tire a raiz-quadrada desse vetor. num length(num) class(num) num2 <- num^2 num2 sqrt(num2) num Agora vamos extrair apenas o quinto elemento e em seguida substituir esse elemento pela palavra "quinto_elemento". Em seguida vamos repetir as operações anteriores: num[5] num[5] <- "quinto_elemento" num num[-5] length(num) class(num) num^2 sqrt(num^2) O que aconteceu aqui? Por que não conseguimos mais operar o vetor ''num''? Vamos agora voltar o vetor para sua forma original e operar novamente: num[5] <- 10 num num^2 sqrt(num^2) Por que ainda não conseguimos? Vamos investigar o vetor e ajustá-lo. length(num) class(num) num <- as.numeric(num) sqrt(num^2) Como já havíamos visto, uma das característica do vetor é que **só armazena um tipo de natureza de dados** e o R faz a coerção da classe do objeto dependendo da característica desses dados. Incluir algo que não é dígito ou símbolo de decimal em um objeto da classe numérica faz com que a classe seja convertida automaticamente em ''character''. A raiz de um valor elevado ao quadrado é o próprio valor? O que aconteceria se o vetor fosse de números negativos? Veja a discussão sobre função quadrática e raiz quadrada como [[http://en.wikipedia.org/wiki/Inverse_function|funções inversas nesse link]] ===== Leitura de Dados ===== A principal função para a leitura de dados no R é ''read.table''. Ela é bem flexível e se aplica para a leitura de dados tabulares como uma planilha eletrônica usual, tendo colunas como variáveis e as linhas como observações. Esta estrutura é análoga a um conjunto de vetores lado a lado, de mesmo comprimento, como veremos a seguir. Antes da leitura de dados é importante garantir que temos eles bem organizados em uma planilha. O artigo [[https://doi.org/10.1080/00031305.2017.1375989|Data Organization in Spreedsheets (Broman & Woo, 2018)]] faz uma ótima síntese de boas práticas para estruturar dados brutos em uma planilha, sua leitura é rápida e irá poupar muito tempo futuro e evitar muitos erros comuns que usuários de planilhas cometem. Os exemplos de [[https://datacarpentry.org/spreadsheet-ecology-lesson/02-common-mistakes.html|erros comuns em planilhas de ecologia do datacarpentry]] são também muito bons, uma forma interessante de aprender é ser exposto ao que não devemos fazer. Tendo a planilha eletrônica com os dados brutos bem estruturados, precisamos exportá-la como arquivo texto puro para fazer a leitura no R. Os arquivos de texto são uma forma eficiente de armazenar dados que tem uma estrutura simples de linhas e colunas. Além de poderem ser abertos em qualquer programa simples de texto e sistema operacional, são reconhecidos nas planilhas eletrônicas como estrutura de dados. Normalmente, utilizamos as extensões ''.txt'' ou ''.csv'' para designar arquivos texto com campos de dados separados por tabulação e vírgula, respectivamente((existem muitos outros tipos de formatos de armazenamento de dados que incorporam dados mais complexos e georreferenciados)). Ao exportar os dados deve ficar atento para algumas opções de exportação da planilha, as principais são os caracteres para designar a separação de campo e o símbolo de decimal. Evite, sempre que possível, caracteres especiais como acentos e aspas ('' ' '', ''`'', ''"''), se houver a opção de escolher a codificação de caracteres ("enconding") opte pelo [[https://pt.wikipedia.org/wiki/UTF-8|UTF-8]]. Sabendo o formato que os dados foram salvos no arquivo texto, na maioria dos casos, precisamos apenas do seguintes argumentos para fazer a leitura dos dados no R ((''read.table'' é muito flexível, veja a documentação!)): **__Principais argumentos do__** ''read.table'' ^ Argumento ^ Descrição ^ Padrão ^ Alternativas^ | file | nome do arquivo ((incluíndo a extensão e o caminho, caso não esteja no diretório de trabalho)) | "nome_arquivo.txt"| "/caminho_dir/nome_arquivo.txt" | | header | nome das variáveis ((utiliza a primeira linha dos dados para o nome das colunas))| FALSE | TRUE | | sep | separador ((qual o símbolo separa os dados de uma mesma linha em colunas. Ex: "\t" é tabulação)) |" " | "," ";" "\t" | | dec | símbolo de decimal | "." | "," | | as.is| mantenha caracteres ((O padrão até a versão 4.0 do R era transformar caracteres em fator na leitura. A partir dessa versão o padrão mudou e a versão mais recente da função não faz essa transformação automática. )) | TRUE | FALSE | ==== Verificando a leitura ==== Logo após a leitura dos dados é recomendável fazer a verificação do objeto lido para ter certificar que os dados foram lidos corretamente. É possível retornar na tela todo o objeto criado, mas para conjunto de dados grandes, fica difícil a visualização. Para isso, usamos algumas funções acessórias que extraem atributos ou parte dos dados. As principais são: * ''str'': faz uma síntese da estrutura do objeto; * ''dim'': mostra as dimensões do objeto, primeiro o número de linhas (observações) e em seguida colunas (variáveis); * ''head'': mostra as primeiras linhas, por padrão as primeiras 6 observações; * ''names'': mostra o nome das variáveis (colunas). ==== Dados de Caixeta ==== Entre na página [[:dados:dados-caixeta|levantamento de espécies em caixetais]], leia a descrição dos dados e das variáveis e salve o arquivo de dados no diretório de trabalho. **Obs.**: Se o arquivo abrir em uma aba do navegador, clique com o botão direito do mouse no link e selecione "salvar link". Vamos fazer a leitura do arquivo com o padrão de leitura da função ''read.table'' e verificar em seguida a classe e a formatação do arquivo: caixeta <- read.table(file = "caixeta.csv") Esse código retornar o erro: Error in scan(file = file, what = what, sep = sep, quote = quote, dec = dec, : line 5 did not have 3 elements Indicando que tentou ler o arquivo, mas algumas linhas tinham dimensões diferentes, ou seja, o formato não era tabular. Isso ocorre, normalmente, devido ao tipo de separador de campo utilizado no arquivo que não é espaço, o padrão da função. No caso, o separador é '','' como relatado na documentação dos dados. Vamos usar o argumento ''sep'' para indicar o separador. Em seguida vamos verificar a classe do objeto. caixeta <- read.table(file = "caixeta.csv", sep = ",") class(caixeta) **__Leitura de dados Online__** A função ''read.table'' também funciona com endereço web como caminho para leitura de arquivos. Só precisamos fornecer a url do arquivo. No nosso caso, como os dados estão no nosso wiki, podemos usar: caixeta <- read.table(file = "http://ecor.ib.usp.br/lib/exe/fetch.php?media=dados:caixeta.csv", sep = ",") ===== Data Frames ===== A classe do objeto é um ''data.frame''. Esse é o segundo tipo de objeto para armazenar dados no R que apresentamos: o ''vetor'' tem apenas uma dimensão de dados, o ''data.frame'' tem duas. Os datas frames no R são conjuntos de vetores de mesmo tamanho, similares a uma planilha de dados. Todas as características que vimos do objeto ''vetor'', valem para as colunas do ''data.frame''. Uma outra forma de pensar o data frame é que são variáveis (colunas) de um conjunto de observações (linhas). Assim como deve ser uma planilha de dados bem estruturada. Vamos insistir em uma sugestão importante, que evita muitos transtornos para quem está iniciando no R é: depois de efetuar a leitura **sempre verificar a estrutura dos dados antes de iniciar as análises**, usando as funções indicadas acima. dim(caixeta) names(caixeta) str(caixeta) head(caixeta) Apesar do objeto ter sido lido, ele não parece o que deveria. A dimensão do objeto mostra que tem uma observação a mais, os nomes das variáveis não corresponde ao que está definido no metadado e as variáveis foram todas lidas com ''characters'' ou ''factor'' dependendo da versão do R. O ''head'' mostra exatamente o que aconteceu: a linha com os nomes das variáveis foi lida como sendo uma observação. Com isso, todas as variáveis foram classificadas como caracteres. Vamos agora usar o argumento ''header'' e fazer novamente a verificação: caixeta <- read.table(file = "caixeta.csv", sep = ",", header = TRUE) dim(caixeta) names(caixeta) str(caixeta) head(caixeta) No código acima temos resultados que podem variar dependendo da versão do R. Isso não é muito comum, pois a equipe de desenvolvedores busca manter a compatibilidade dos scripts entre versões. **__stringsAsFactors__** Por padrão, até a versão anterior a 4.0.0 de abril de 2020, o padrão das funções ''read.table'' e ''data.frame'' era classificar as variáveis com caracteres como sendo um fator. Isso era definido com os padrões dos argumentos ''stringsAsFactors = TRUE'' ou ''as.is = FALSE''. Desde da versão 4.0.0 o padrão é classificar as variáveis que contém caracteres como sendo ''character''. O que acontece é que a partir dessa versão o padrão para ''as.is = !stringAsFactor'' e a função ''read.table'' incorporou o argumento ''stringAsFactors = TRUE''. Ou seja, por padrão o ''stringAsFactor'' diz para a função transformar caracteres em fator, mas é sobreposto pelo argumento ''as.is'' que inverte o valor lógico com ''!''. Essa conversão automática para fator é um legado da linguagem S((veja artigo sobre essa mudança em [[https://developer.r-project.org/Blog/public/2020/02/16/stringsasfactors/index.html| developer blog]])). ==== Incluir Variáveis ==== Vamos então transformar as variáveis ''local'' e ''especie'' para fator, assim independente da versão do R instalada, estaremos todos com a mesma estrutura de objeto. caixeta$local <- factor(caixeta$local) caixeta$ssp <- factor(caixeta$especie) str(caixeta) Percebam que na primeira linha de comando estamos sobrescrevendo a variável ''local'' como fator para a mesma coluna. No caso da conversão de ''especie'' em fator, criamos uma nova variável no nosso ''data.frame'' chamada ''spp'', um fator, e preservamos a variável ''especie'' que continua como caracteres. **Incluir Variáveis no ''data.frame''** Para incluir novas variáveis no ''data.frame'' só é preciso fornecer os valores e indicar a coluna onde esses valores devem ser atribuídos, tomando o cuidado de indicar um nome diferente das variável existentes caso não queira sobrescrever. O vetor da nova variável deve ter o mesmo tamanho do número de linhas do ''data.frame''. A regra de ciclagem vale aqui também, veja o que acontece com o código: caixeta$dap <- NA str(caixeta) No quadro acima criamos uma variável chamada ''dap'' que contém só ''NA''s (not available). Vamos incluir agora, nessa coluna, os valores de [[https://www.ibflorestas.org.br/conteudo/o-que-e-dap-de-uma-arvore|diâmetro à altura do peito]]. Para isso, vamos usar o valor de ''cap'' (circunferência à altura do peito) e a relação: $$ dap = \frac{cap}{pi} $$ caixeta$dap <- caixeta$cap/pi str(caixeta) Aqui também temos a regra da ciclagem com o valor da constante ''pi'' sendo ciclado para operar todos os elementos da variável ''cap''. ==== Indexação ==== Acima usamos a indexação da coluna do ''data.frame'' pelo nome da variável, usando o operador ''$''. Veja o que temos ao pedir a estrutura de uma variável do ''data.frame'' str(caixeta$especie) str(caixeta$cap) O que temos é a estrutura básica de armazenamento de dados: vetores das classes básicas de dado. Portanto, para indexar as posições nesse vetores, podemos usar a indexação básica de vetores: caixeta$dap[1] caixeta$dap[c(1, 3, 5, 7, 9)] caixeta$dap[seq(1, 19, by= 2)] Uma outra forma de indexar é pelas posições da linha e coluna. No caso do ''data.frame'' isso é feito pela indicação das duas posições separadas por vírgula entre colchetes ''[ , ]''. Sempre o valor antes da vírgula se refere a primeira dimensão do ''data.frame'' que são as linhas (observações) e o valor depois refere-se a coluna (variável). caixeta[1, 9] caixeta[c(1, 3, 5, 7, 9), 9] caixeta[seq(1, 19, by= 2), 9] Por fim, é possível também combinar nomes das variáveis com as posições das observações: caixeta[1, "dap"] caixeta[c(1, 3, 5, 7, 9), "dap"] caixeta[seq(1, 19, by= 2), "dap"] Inclusive, combinar nomes de variáveis: caixeta[1, c("dap", "cap")] caixeta[c(1, 3, 5, 7, 9), c("dap", "cap")] caixeta[seq(1, 19, by= 2), c("dap", "cap")] ==== Indexação com Lógica ==== Para apresentar essa última forma de indexação, vamos construir um ''data.frame'' sem fazer a leitura, usando a função ''data.frame'' que recebe os vetores de dados de mesmo tamanho. trapalhoes <- data.frame(nomes = c("Didi","Dedé","Mussum","Zacarias"), ano.nasc = c(1936, 1936, 1941, 1934), vive = c("V", "V", "F", "F")) Vamos agora calcular a idade dos meninos: ano.atual <- as.numeric(format(Sys.Date(), "%Y")) ano.atual - trapalhoes$ano.nasc trapalhoes$idade <- ano.atual - trapalhoes$ano.nasc Tá bom! Vou explicar a primeira linha de comando, ao mesmo tempo, indicar o caminho para entender comandos mais complicados em geral. Primeiro temos a característica da sintaxe aninhada, padrão do R. Para entender o que está sendo feito, pegue a função mais interna e veja o que ela está retornando, em seguida veja o que função externa a ela está fazendo com esse resultado, e assim por diante! Sys.Date() format(Sys.Date(), "%Y") as.numeric(format(Sys.Date(), "%Y")) **Por que?** Pois bem, estamos primeiro pegando a data atual armazenada no computador, depois pegando apenas o ano e em seguida transformando o ano em número. Ué? Não seria mais fácil digitar o ano diretamente? Sim, mas depois teria que atualizar o código todos os anos antes do curso! {{:02_tutoriais:tutorial3:porquesim.gif?600|}} Para extrair informações específicas do ''data.frame'' usamos a indexação com um vetor lógico. Por exemplo, podemos nos perguntar: Quais os nomes dos trapalhões que nasceram antes de 1940? antes40 <- trapalhoes$ano.nasc < 1940 antes40 O resultado desse teste lógico é um vetor de ''TRUE'' e ''FALSE'': [1] TRUE TRUE FALSE TRUE Ele nos diz que a condição é verdadeira para todas as posições menos para a terceira. Como o vetor lógico tem o mesmo comprimento do número de linhas, podemos então indexar o nosso ''data.frame'' com esse vetor, da seguinte forma: trapalhoes[antes40, ] ou diretamente, sem o objeto intermediário: trapalhoes[trapalhoes$ano.nasc < 1940, ] Note que fizemos a indexação pelas linhas, deixando a indexação da coluna vazia, ou seja, solicitando retornar todas as colunas para as linhas em que o vetor ''antes40'' é ''TRUE''. Como ''data.frame'' tem duas dimensões, a vírgula é mandatória para a indexação. Nossa pergunta foi mais específica, perguntamos o nome e não pedimos as outras informações: trapalhoes[antes40, "nomes" ] Nesse caso, a indexação da coluna pode ser feita pelo nome da variável ou pela posição e também pode ser combinada. E se quisermos o inverso, o nome e a idade dos que nasceram depois de 1940? Precisamos só inverter o vetor de ''TRUE'' e ''FALSE'' usando o operador ''!'': trapalhoes[!antes40, c("nomes","idade") ] [[https://pt.wikipedia.org/wiki/Mussum|{{ :02_tutoriais:tutorial3:wecreu.jpg?200 | }}]] Essas são as principais instrumentações de indexação no R. Aplicadas em um ''data.frame'' com quatro observações não parece muito vantajoso. Vamos nos perguntar algo então para os dados das ''caixeta'' que tem mais de mil observações: Quais árvores, na amostra da Juréia, tem mais de 100 mm de dap? jureiaVF <- caixeta$local == "jureia" bigtree <- caixeta$dap > 100 caixeta[jureiaVF & bigtree, ] Aqui utilizamos o operador lógico ''&'' para perguntar para o R quais posições de ''jureiaVF'' e ''bigtree'' são verdadeiras em ambos os vetores. E para saber quantas árvores tem na amostra da Juréia, quantas dessas são grandes e em que proporção? Lembra que o ''TRUE'' é operado algebricamente como sendo o valor ''1''? sum(jureiaVF) sum(bigtree & jureiaVF) sum(bigtree & jureiaVF)/sum(jureiaVF) ==== Salvando Data Frame ==== Após manipular os dados no R podemos salvar uma nova versão em um arquivo texto. Para salvar a nossa nova versão dos dados de caixetais, que incorpora o ''dap'', usamos a função ''write.table''. Os parâmetros são parecidos com a função de leitura, só que precisamos indicar qual o objeto a ser salvo e nome do arquivo no qual ele será gravado. Caso queira salvar em um local diferente do diretório de trabalho deve também fornecer o caminho das pastas do computador. Abaixo estamos salvando os dados no arquivo ''caixeta.txt'', com os campos separados por tabulação (''\t'') e indicando que não queremos salvar nomes de linhas((Por padrão a função ''write.table'' salvará o valor de indexação da linha como o nome da observação)) (''row.names= FALSE'') write.table(caixeta, file = "dados/caixeta.txt", sep = "\t", dec = ",", row.names = FALSE) Caso receba a mensagem de erro: Error in file(file, ifelse(append, "a", "w")) : cannot open the connection In addition: Warning message: In file(file, ifelse(append, "a", "w")) : cannot open file 'dados/caixeta.txt': No such file or directory Significa que o caminho para gravar o arquivo tem algum problema, no caso não há a pasta ''dados'' subordinada ao seu diretório de trabalho. Para criar uma pasta pelo R, use o comando abaixo: dir.create("dados") dir.exists("dados") dir() Agora podemos rodar novamente a linha de comando do ''write.table'' e gravar o nosso arquivo ''caixeta.txt'' no diretório ''dados'', subordinado ao diretório de trabalho que a sessão do R está associado. **__Formato de Arquivo de Dados__** Arquivos de dados no formato de texto são uma forma segura de salvar conjunto de dados pequenos ou medianos ( ~100 mil registros). Os formatos mais usados são os com campo separados por espaço (padrão do ''read.table''), separados por vírgula ou ponto e vírgula, normalmente com extensão ''.csv'', ou tabulação, normalmente com extensão ''.txt''. A extensão é apenas uma indicação de formato e como é possível salvar o arquivo com qualquer extensão, precisamos saber qual estrutura foi utilizada para salvar os dados. O excel em sistemas operacionais em português salva arquivos ''csv'' separados por '';'', com símbolo de decimal '','', o que causa bastante confusão. Nossa sugestão é que configure seu computador para decimal com ''.'' e estabeleça o seu padrão de separação de campo, deixando indicado em um arquivo acessório de metadados. Antes de ler um arquivo de dados de texto que desconheça a formatação, abra em um arquivo de edição de texto simples, como o bloco de notas, para verificar os símbolos de separação de campo e decimal. ===== Matrix e Array ===== {{youtube>PlApQqRTdDw}} ===== Matrizes ===== Outro tipo de objeto no R com estrutura tabular é a ''matrix'', que está associado à álgebra linear. A principal diferença com ''data.frame'' é que ''matrix'' só aceita uma classe de dados, assim como ''vector''. A ''matrix'' é usada no sentido de matrizes da álgebra linear e operações matriciais. Vamos aprender o objeto ''matrix'' associada ao estudo de dinâmica populacional. ==== Operações Matriciais ==== {{:02_tutoriais:tutorial3:matrizestruturada.jpeg?400 |}}As matrizes de transição são uma maneira conveniente de modelar o crescimento de uma população dividida em faixas etárias, ou estágios de desenvolvimento ((para saber mais veja o [[http://ecovirtual.ib.usp.br/doku.php?id=ecovirt:roteiro:pop_str:pstr_mtr| roteiro de população estruturada]] em nosso projeto **EcoVirtual**)). Uma forma de representar essas populações estruturadas((apresentam estágios diferentes)) é com diagramas mostrando as transições e permanências entre estados. Uma forma compacta de representar matematicamente essas transições e permanência é utilizando a forma de matriz, que nesse caso se chama **//matriz de transição//**, como na figura abaixo: {{:02_tutoriais:tutorial3:matrizestruturada1.jpeg?150|}} Uma população de //Escobaria robbinsiorum// (Cactaceae) no deserto do Arizona, com três estágios de desenvolvimento, tinha a seguinte a matriz de transição: **//Escobaria robbinsiorum//** {{ :02_tutoriais:tutorial3:escRobbins.jpg?300 |}} 0,43 0 0,56 0,33 0,61 0 0 0,30 0,96 Os elementos da matriz, com exceção da fecundidade (F2 e F3 no diagrama), são as probabilidades de transição, num intervalo de tempo, do estágio correspondente ao número da coluna para o estágio correspondente ao número da linha. Por exemplo, a chance de um indivíduo passar do estágio 1 (plântula) para o 2 (jovem) é 0,33, e de permanecer em 1 é de 0,43. A fecundidade, representada nessa matriz como o elemento da primeira linha e terceira coluna (0,56) é o único que não é uma probabilidade e representa a contribuição, em número de jovens do estágio 1, que um adulto produz em média a cada ciclo. Vamos criar um objeto da classe matriz com esses valores. Isso nos permitirá realizar operações matriciais para prever o tamanho da população. matCory <- matrix( c(0.43, 0.33, 0, 0, 0.61, 0.3, 0.52, 0, 0.96), nrow = 3, ncol = 3) matCory A indexação da ''matrix'' é similar ao ''data.frame'' quando usamos o ''[''. A indexação utilizando ''$'' não se aplica nesse caso. Por exemplo, a fecundidade foi digitada errada no código acima e precisamos ajustá-la: matCory[1, 3] matCory[1, 3] <- 0.56 matCory Aqui estamos usando uma regra básica dos objetos de dados no R: se consegue extrair um elemento de um objeto é possível atribuir algo a essa posição. Agora crie um vetor com as abundâncias iniciais de indivíduos em cada classe. Vamos começar com uma população de 50 plântulas , 25 jovens e 10 adultos. popN0 <- c(50, 25, 10) popN0 Para calcular o número de indivíduos em cada estágio após um intervalo de tempo, basta multiplicar a matriz de transição pelas abundâncias dos indivíduos em cada estágio. Usamos o operador de multiplicação matricial ''%*%'' para isso. Qual será o número de plantas em cada estágio após três intervalos? popN1 <- matCory %*% popN0 popN1 popN2 <- matCory %*% popN1 popN2 popN3 <- matCory %*% popN2 popN3 Vamos agora armazenar a trajetória do tamanho dos estágios na população em uma matrix: pop <- matrix(c(popN0, popN1, popN2, popN3), ncol = 3, byrow = TRUE) colnames(pop) <- c("plântula", "jovem", "adulto") pop pop <- rbind(pop, t(matCory %*% pop[nrow(pop),])) No código acima, fazemos a multiplicação matricial ''%*%'' de duas matrizes: ''matCory'' e a última linha do objeto ''pop''. Em seguida transpomos((ou seja, trocamos as linhas pelas colunas)) a matriz resultante com a função ''t'' para depois combinar o resultado transposto com o objeto ''pop''. Para isso, usamos a função ''rbind'' que combina as linhas de dois objetos tabulares. Por último, sobrescrevemos o objeto ''pop'' com essa nova combinação. Veja como funciona o código acima executando cada passo separadamente, do mais interno para o mais externo: nrow(pop) pop[nrow(pop),] matCory %*% pop[nrow(pop),] t(matCory %*% pop[nrow(pop),]) rbind(pop, t(matCory %*% pop[nrow(pop),])) Podemos fazer mais algumas multiplicações, guardando o resultado diretamente no objeto ''pop'', usando somente a mesma linha de comando novamente. pop <- rbind(pop, t(matCory %*% pop[nrow(pop),])) pop <- rbind(pop, t(matCory %*% pop[nrow(pop),])) pop <- rbind(pop, t(matCory %*% pop[nrow(pop),])) pop <- rbind(pop, t(matCory %*% pop[nrow(pop),])) pop <- rbind(pop, t(matCory %*% pop[nrow(pop),])) ## ... Vamos agora nomear essas linhas usando a função ''paste'' que combina caracteres. rownames(pop) <- paste("t", seq(from = 0, to = (nrow(pop) - 1)), sep = "") A função paste junta caracteres de dois vetores com os princípios da equivalência de posição e ciclagem, próprios das operações com vetores. Caso não tenha entendido o código acima, faça a separação de cada passo e veja a documentação das funções. Esse é um procedimento básico para entender códigos quando estamos iniciando no aprendizado de uma linguagem computacional. Por fim, vamos olhar esses dados em um gráfico no objeto ''pop'' . O código abaixo vai ser abordado na aula de gráficos, por enquanto apenas copie e execute o código no R: matplot(x = 0:(nrow(pop)-1), pop, type = "l", xlab = "Tempo", ylab = "Número de indivíduos", lty = 2, lwd = 2, col = c("red", "blue", "green"), cex.lab = 1.2, cex.axis = 1.2, las = 1) legend("topleft", legend = colnames(pop), bty = "n", lty = 1, col = c("red", "blue", "green")) **__Modelos Matriciais de Dinâmica Populacional__** Com um pouco mais de álgebra linear você pode obter muito mais informações sobre características da população biológica, apenas a partir das informações intrínsecas da matriz de transição (autovalores e autovetores). Por exemplo, a taxa de crescimento (λ) da população é o primeiro autovalor da matriz de transição, enquanto que o valor reprodutivo e a distribuição da proporção dos estágios no equilíbrio estão relacionados aos autovetores. Esses valores podem ser obtidos com a função ''eigen''((consulte a ajuda para interpretar o resultados dessa função)). Para saber como calcular esses valores veja o [[http://ecologia.ib.usp.br/ecopop/doku.php?id=roteiros:matriz|roteiro da disciplina de ecologia de populações]] na qual esse tópico foi baseado. eigen(matCory) ==== Matrix de comunidade ==== Um formato de dados clássico em ecologia de comunidades é o de espécies por localidade, como a ocorrência ou a contagem de indivíduos. Já usamos a função ''table'' para contagem de uma variável tipo ''fator''. Vamos construir essa nova estrutura de dados a partir do objeto ''caixeta'' e fazer a coerção para a classe matrix. str(caixeta) caixTable <- table(caixeta$especie, caixeta$local) str(caixTable) class(caixTable) caixTable[,"chauas"] caixMatrix <- as.matrix(caixTable) str(caixMatrix) identical(caixMatrix, caixTable) class(caixMatrix) Apesar de parecer que a coerção do objeto ''table'' para ''matrix'' não tenha funcionado, a coerção funcionou como deveria. Os objetos da classe ''table'' são matrizes especiais de tabelas de contingência((tabelas de contagem)) usadas para os testes de dependência entre variáveis categóricas. Para o R é um objeto subordinado à classe ''matrix''. Vamos agora fazer a manipulação desses dados para saber quantos indivíduos e espécies temos na localidade ''jureia''. Primeiro precisamos manipular o objeto ''caixMatrix'' para que ela tenha apenas a informação de ocorrência caixMatrix[caixTable > 0 ] <- 1 head(caixTable) head(caixMatrix) Agora podemos contar a coluna ''jureia'' em cada uma dos objetos: sum(caixTable[, "jureia"]) sum(caixMatrix[, "jureia"]) Poderíamos usar a função ''apply'' para fazer a contagem de todas as colunas de uma vez. A função ''apply'' aplica uma função para alguma dimensão dos dados, no caso, coluna ou linhas, e cicla a função para todas as posições dessa dimensão. apply(caixTable, MARGIN = 2, FUN = sum) apply(caixMatrix, 2, sum) ===== Combinando Dados Tabulares ==== É comum termos informações que estão em formato de dados tabulares e precisam ser agrupadas com outro conjunto de dados. Vamos olhar algumas das ferramentas para fazer isso. Em construção === Combinando colunas ou linhas === As funções ''rbind'' e ''cbind'' são utilizadas para concatenar dados tabulares pelas linhas ou colunas. Entretanto, só funcionam se a estrutura é a mesma, ou seja as variáveis são as mesmas e na mesma posição para acrescentar novas observações, ou as observações estão nas mesmas linhas para acrescentar novas variáveis. trapa <- read.table("http://ecor.ib.usp.br/lib/exe/fetch.php?media=dados:trapa.csv", header = TRUE, sep = ",") str(trapa) trapaNome <- read.table("http://ecor.ib.usp.br/lib/exe/fetch.php?media=dados:trapa_nome.txt", header = TRUE, sep = ",") str(trapaNome) trapaNome trapa rbind(trapa, trapa) trapabind <- cbind(trapa, trapaNome) ==== Outras formas de combinar ==== Quando colunas ou linhas não podem ser combinadas diretamente, porque as posições não são compatíveis, podemos usar as funções ''merge'' e ''match''. O ''merge'' combina dois objetos por uma coluna que é a referência comum, combinando as variáveis de ambos ''dataframe''. O ''match'' funciona também a partir de uma variável comum a ambos objetos e produz um índice de posição que ordena um dos objetos na mesma posição que o outro. O ''match'' é um pouco mais difícil de entender, mas é uma ferramenta poderosa para manipular dados tabulares. Abaixo apresentamos ambas funções manipulando dados muito simples para demonstrar como funcionam. ## merge merge(trapa, trapaNome, by = "codinome") trapa$codinome trapaNome$codinome merge(trapa, trapaNome, by = "codinome", all = TRUE) trapa$codinome[2] <- trapaNome$codinome[3] trapa$codinome merge(trapa, trapaNome, by = "codinome") ## match (matchtrap <- match(trapa$codinome, trapaNome$codinome)) trapaNome[matchtrap, ] trapa$nome <- trapaNome[matchtrap, "nome"] trapa ===== Array ===== O objeto ''matrix'' por sua vez é apenas um objeto da classe ''array'' com apenas duas dimensões, assim como o ''vector'' é um array de uma dimensão. Veja a classe do objeto ''pop'' que criamos na sessão de multiplicação de matrizes: class(pop) A classe é ''matrix'' mas a classe parental é ''array''. Essa possibilidade de um ''array'' ter muitas dimensões permite efetuarmos operações e análises em múltiplas dimensões. As características e operações que fizemos em ''matrix'' se aplicam também para ''array''. Vamos avaliar um objeto dessa classe chamado ''Titanic''. Primeiro vamos entender onde está esse objeto. A função ''search'' mostra o caminho de busca nos compartimentos de memória da sessão do R. Nele há um pacote chamado ''datasets'' que é carregado por padrão ao abrirmos uma sessão do R. search() ls("package:datasets") ls("package:datasets", pattern = "Tit") Isso significa que esse objeto está disponível para uso sem a necessidade de carregá-lo. Vamos investigar alguns atributos dele: is.array(Titanic) dim(Titanic) dimnames(Titanic) Um tanto mais complicado de visualizar os dados do que uma planilha. Imagine os quatro níveis de ''Class'' como sendo as linhas de um planilha, ''sex'' como as colunas, ''age'' como sendo a repetição dessa estrutura para ''Child'' e ''Adult'', por fim essa estrutura replicada para ''Survived'' igual a ''No'' e ''Yes''. Como as quatro dimensões tem tamanhos pequenos é possível visualizar todos dados: str(Titanic) Titanic Essa estrutura permite operar qualquer dimensão, ou mesmo algumas dimensões ao mesmo tempo. Vamos usar o ''apply'' para obter algumas informações interessantes sobre as vítimas do naufrágio. Será que crianças e adultos tiveram a mesma proporção de vítimas? apply(Titanic, c("Age", "Survived"), sum) Será que a proporção de vítimas entre homens e mulheres foi similar? apply(Titanic, c("Sex", "Survived"), sum) E entre os passageiros de diferentes classes? apply(Titanic, c("Class", "Survived"), sum) **__Mistério do Titanic__**: mulheres e crianças primeiro {{:02_tutoriais:tutorial3:women&childrenFirst.jpg?200 | }} Os grupos com maior sobrevivência no desastre do Titanic foram as mulheres e crianças da primeira classe. Analisando dados de múltiplos acidentes marinhos o artigo [[https://www.pnas.org/content/109/33/13220|''Gender, social norms, and survival in maritime disasters'', Elinder & Erixson (2012)]] verifica que a distribuição de sobrevivência do Titanic é uma exceção. As evidências nos dados desse artigo mostram que a maior sobrevivência está entre os homens da tripulação e a menor entre as crianças. ====== Listas ====== Listas são os objetos mais versáteis para armazenar informação no R. Apesar de ter uma única dimensão, suas posições comportam qualquer outra classe de objeto que vimos até então. Normalmente os objetos mais complexos no R, como por exemplo resultados de modelos estatísticos, são casos especiais de listas padronizadas. Vamos criar a nossa primeira lista com alguns objetos desse tutorial: minhaLista <- list(vectorNum = num, dfTrapa = trapalhoes, matPop = pop, arrayTit = Titanic) str(minhaLista) A indexação da lista é um misto das classes de objetos que vimos anteriormente. Na sua primeira dimensão aceita tanto o nome com ''$'' como um ''data.frame'' quanto um novo indexador que é o ''[''''['' colchete duplo. minhaLista <- list(vectorNum = num, dfTrapa = trapalhoes, matPop = pop, arrayTit = Titanic) str(minhaLista) minhaLista$dfTrapa minhaLista[[3]] minhaLista[["vectorNum"]] Os elementos de cada posição podem ser acessados usando as indexações correspondentes a cada classe! minhaLista$dfTrapa[, "nomes"] minhaLista[[3]][1,] minhaLista[["vectorNum"]] [7] Lembre-se sempre de olhar o ''help''. Não cometa o 7º pecado da lista do início desse tutorial, acostume-se com a documentação e como a sua estrutura. Todas as funções nesse tutorial apresentam um hiperlink que leva à sua documentação. ====== Um Exemplo ====== No vídeo abaixo apresento um exemplo de manipulação de dados de um estudo sobre dinâmica de população de uma espécie de árvore (//Guapira opposita//) da floresta atlântica, utilizando matrizes e arrays. {{youtube>iCJ57zlHPrI}}