Organizando dados: de dados brutos a dados para análise, em R

Semana passada eu escrevi sobre algumas funções para organização de dados em Excel; e ontem no Sobrevivendo na Ciência foi publicado um ótimo texto sobre organização de dados; linkando inclusive para esse texto excelente, sensacional, incrível do Brian McGill; o qual também link para um post do mesmo autor mostrando como fazer algumas coisas em R. Algo em que parece não haver discordância é: existe uma planilha de dados brutos, onde todos seus dados ficam armazenado, e uma ou mais planilhas para análise, uma específica para cada tipo de análise a ser feita; e idealmente a planilha de dados brutos deve ser transformada na planilha de análise via script, não via funções que ensinei semana passada (mas se você não sabe programar, tudo bem, pode usar as funções, eu deixo. rs) Se você quer aprender a de fato organizar dados usando R, recomendo estudar o material do Brian. Mas se você estiver com preguiça ou achar aquilo complexo demais, bom, tem este post aqui 🙂

Desta vez vou usar dados reais como exemplo, eles podem ser baixados aqui – são os arquivos começando com dataOrganization. Temos dois arquivos de dados, um arquivo de metadados e um arquivo com o script.

Mas Pav, por que dois arquivos de dados?

Simples, jovem Padawan. Estou seguindo o que Brian chama de normalizar os dados, reduzindo um pouco a redundância. Os dados dizem respeito a plantinhas encontradas em parcelinhas de 1×1 m que eu amostrei no meu doutorado. Então temos uma planilha, a da esquerda abaixo, mostando a parcela (distância ao longo do transecto, em metros), a espécie e a altura máxima dessa espécie na parcela. E a outra planilha, a da direita, mostra características das espécies: família, forma de vida (que não é exatamente forma de vida, eu sei) e síndrome de dispersão (por vento, animal, autocoria, ou se aquela espécie foi plantada lá – no caso dos eucaliptos).

Legal, mas não parece um pouquinho complicado?

Parece! Por isso que também criei uma planilha com metadados, explicando resumidamente esses paranauê aí – na parte inferior da figura abaixo.

 

fig1.png

Três planilhas: dados por parcela; dados por espécie; metadados explicando as duas outras. A coluna Species une as duas primeiras planilhas.

Legal! Mas Pav, por que você não tirou da imagem os menus etc?

Uai, pra mostrar meu Ubuntu e meu Libre Office em toda sua glória! Não é óbvio?

Não…

…… Enfim, voltando ao assunto…

Eu salvei as planilhas de dados em formato .csv (separado por vírgula) e a de metadados em formato .txt e coloquei no meu GitHub, link acima. Arquivos .csv e .txt são mais facilmente transferíveis entre computadores Tendo salvo as nossas e sistemas do que arquivos .xls ou .ods. Além disso, salvar os dados em formato de texto te obriga a pensar um pouco mais em como organizar eles.

Bora pro R!

Tendo salvo nossos dados a partir do Excel ou do Calc, vamos pro R! O nosso objetivo é ver como algumas variáveis variam entre as parcelas (distâncias). Especificamente, queremos ver como o 1) o número de espécies, 2) o número de espécies por síndrome de dispersão, 3) o número de espécies por forma de vida, 4) o número de famílias e 5) a altura máxima varia por parcela. Porque sim.

Então… Vamos por passos.

Inserindo os dados.

Primeiro temos que definir o diretórico de trabalho. Esta é a pasta no seu computador onde ficam os arquivos. É legal deixar os arquivos bem organizadinhos dentro de uma pasta, com nomes relativamente claros – o seu eu-futuro vai agradecer!

> setwd(“/home/pavel/Profissional/Extensao/Blogs/AnotherEcoBlog/dataOrganization”)

E a seguir abrimos o arquivo usando o comando read.table (read.csv também seria uma opção. Depois de abrir o arquivo, usamos o comando str para ver a estrutura dele e conferir se está tudo certo.

> data_quad = read.table(“dataOrganization_Quadrats.csv”, header=T, sep=”,”)
> str(data_quad)
‘data.frame’: 1808 obs. of 3 variables:
$ Distance: int 4 4 4 4 5 5 5 5 5 6 …
$ Species : Factor w/ 124 levels “Acosmium subelegans”,..: 121 64 8 105 121 8 67 73 3 8 …
$ Hmax : num 66 44 63 350 38 34 71 79 19 NA …
> data_spec = read.table(“dataOrganization_Species.csv”, header=T, sep=”,”)
> str(data_spec)
‘data.frame’: 169 obs. of 4 variables:
$ Species : Factor w/ 169 levels “Achyrocline sp”,..: 5 13 14 15 61 167 18 24 59 75 …
$ Family : Factor w/ 49 levels “Anacardiaceae”,..: 1 2 2 2 2 2 3 3 3 3 …
$ Lifeform: Factor w/ 6 levels “Fern”,”Graminoid”,..: 4 6 6 4 6 6 6 5 5 5 …
$ Disp : Factor w/ 4 levels “Animal”,”Planted”,..: 1 1 1 1 1 1 4 4 4 4 …

Criamos um objeto chamado data_quad, no qual teremos os dados por parcela (quadrate). Para isso usamos o comando read.table, no qual inserimos: o nome do arquivo contendo os dados; um argumento indicando que a primeira linha é o cabeçalho; e um argumento indicando que as colunas são separadas por vírgula.

O comando str então mostra a estrutura deste objeto: temos a variável Distance, que assume vlalores inteiros; Species, que é uma variável categórica com 124 níveis (ou seja, 124 espécies diferentes); Hmax, que é uma variável numérica correspondente à altura máxima. O NA – valor ausente – provvelmente indica que esqueci de medir alguma altura em campo. No outro objeto (data_spec – species), temos quatro variáveis categóricas: Species, Family, Lifeform, Disp (pra síndrome de dispersão).

Podemos usar o comando View pra ver esses dados como planilhas:

> View(data_quad)
> View(data_spec)

 

fig2

O que o comando View nos mostra.

Juntando as duas planilhas

Bom. Temos duas planilhas e precisamos  juntar elas numa só que contenha, pra cada indivíduo, a sua espécie, sua altura máxima, sua família, sua síndrome de dispersão e sua forma de vida – além da parcela na qual se encontra. Mas Pav, não fica uma planilha cheia de redundâncias? – Sim, fica, e isso não é nenhum problema! Confie em mim*.

Como fazer isso? Em Excel ou Calc, usaríamos o VLOOKUP/PROCV. Até que é bem rápido – mas não é reprodutível, no sentido de se mudarmos alguma coisa na planilha, teríamos que fazer tuuudo de novo, e dá uma preguiiiiça quanto mais a gente faz procedimentos manuais, maior a probabilidade de introduzirmos erros.

Solução usamos o comando merge. Existem outros que fazem isso melhor e que eu não sei usar mas uma vantagem do merge é eu acho que sei como usa não precisa instalar nenhum pacote pra usar ele e às vezes não temos internet pra instalar pacotes…

> data_all = merge(x=data_quad, y=data_spec, by=”Species”, all.x=T, all.y=F, sort=T)
> str(data_all)
‘data.frame’: 1808 obs. of 6 variables:
$ Species : Factor w/ 124 levels “Acosmium subelegans”,..: 1 1 1 1 1 1 1 1 1 1 …
$ Distance: int 219 156 186 298 271 253 259 297 296 282 …
$ Hmax : num 14 38 18 60 40 315 58 57 194 16 …
$ Family : Factor w/ 49 levels “Anacardiaceae”,..: 21 21 21 21 21 21 21 21 21 21 …
$ Lifeform: Factor w/ 6 levels “Fern”,”Graminoid”,..: 6 6 6 6 6 6 6 6 6 6 …
$ Disp : Factor w/ 4 levels “Animal”,”Planted”,..: 4 4 4 4 4 4 4 4 4 4 …
> View(data_all)

Criamos um objeto chamado data_all que é uma combinação da nossa primeira matriz (x=data_quad) e da segunda matriz (y=data_spec), juntadas com base nas espécies (by=Species), mantendo todas as espécies da primeira planilha mesmo que elas não estejam na segunda (all.x=T – fazemos isso porque vai que esqueci de colocar as informações de alguma das espécies; e também temos valores “indet” – espécie indeterminada que não está presente na segunda planilha), mas excluindo informações da segunda planilha que não estejam na primeira (all.y=F – porque não nos interessa uma espécie que não esteja em nenhuma parcela), e ordenando o objeto final pelos nomes das espécies (sort=T).

fig3.png

A matriz combinada – não é linda?

Se quisermos, podemos reordenar ela ficar em ordem de distância e mudar a ordem das colunas; isso não faz diferença pras análises, mas pode facilitar a exploração dos dados:

> data_all = data_all[order(data_all$Distance), c(“Distance”, “Species”, “Family”, “Lifeform”, “Disp”, “Hmax”)]
> str(data_all)
‘data.frame’: 1808 obs. of 6 variables:
$ Distance: int 4 4 4 4 5 5 5 5 5 6 …
$ Species : Factor w/ 124 levels “Acosmium subelegans”,..: 8 64 105 121 3 8 67 73 121 8 …
$ Family : Factor w/ 49 levels “Anacardiaceae”,..: 35 NA 4 35 40 35 28 28 35 35 …
$ Lifeform: Factor w/ 6 levels “Fern”,”Graminoid”,..: 2 NA 6 2 6 2 6 6 2 2 …
$ Disp : Factor w/ 4 levels “Animal”,”Planted”,..: 4 NA 1 1 1 4 1 1 1 4 …
$ Hmax : num 63 44 350 66 19 34 71 79 38 NA …
> View(data_all)

Ordenamos as linhas pelas distâncias e as colunas pela ordem que está entre parênteses. Fica assim:

fig4.png

Planilha reordenada. Os nomes das linhas estão numa ordem estranha, mas isso não importa.

Resumindo dados por parcela

Os passos seguintes seriam o equivalente a uma tabela dinâmica. Cada espécie só pode aparecer uma vez por parcela (porque foi assim que eu medi). Então, pra contar o número de espécies por parcela, precisamos simplesmente contar quantas vezes aquela parcela (distância) aparece. Quem faz isso é o comando table. E pra ver o número de espécies com diferentes síndromes de dispersão ou formas de vida, precisamos contar quantas vezes cada combinação parcela – forma de vida ou parcela – síndrome de dispersão aparece. Novamente, usamos o comando table:

> Nsp_temp = table(data_all$Distance)
> Ndisp_temp = table(data_all$Distance, data_all$Disp)
> Nlife_temp = table(data_all$Distance, data_all$Lifeform)

Coloquei _temp no nome dos objetos porque são temporários, não vou precisar deles depois. O cifrão $ diz o nome da coluna. Então, primeiro contamos quantas vezes cada distância aparece, e depois quantas vezes cada combinação de distância e síndrome ou forma de vida aparece. O comando View não funciona tão bem pros resultados, mas vocês podem olhar eles no seu próprio R.

Pra altura máxima, usamos o comando aggregate:

> Hmax_temp = aggregate(Hmax ~ Distance, data=data_all, FUN=max)

E pra número de famílias, é um pouco mais complicado mas pode ser feito em três linhas (é provável que haja uma solução mais simples que não achei):

> Nfam_temp = table(data_all$Distance, data_all$Family)
> Nfam_temp[Nfam_temp >1] = 1
> Nfam_temp = apply(Nfam_temp, 1, sum)

A primeira linha mostra quantas espécies de cada família tem em cada parcela; a segunda transforma essa tabela em uma de presença/ausência; a terceira soma as presenças, dizendo assim quantas famílias temos em cada parcela.

Juntando tudo isso numa coisa só

E agora temos objetos mostrando as diferentes informações que queremos. Vamos juntar eles num objeto só? Antes, vamos conferir se todos eles têm os mesmos nomes de linhas ou mesmos valores de distância:

> all(rownames(Nsp_temp) == rownames(Ndisp_temp))
[1] TRUE
> all(rownames(Nsp_temp) == rownames(Nlife_temp))
[1] TRUE
> all(rownames(Nsp_temp) == Hmax_temp$Distance)
[1] TRUE
> all(rownames(Nsp_temp) == rownames(Nfam_temp))
[1] TRUE

Sim, tudo em ordem.

Transformamos o objeto Hmax_temp (que é um data frame) em uma matriz e juntamos tudo usando cbind, criando um novo objeto chamado data_an (dados para análise); depois mudamos o nome de uma coluna e vollá:

> Hmax_temp = as.matrix(Hmax_temp)
> data_an = cbind(Hmax_temp, Nsp_temp, Ndisp_temp, Nlife_temp, Nfam_temp)
> str(data_an)
num [1:292, 1:14] 4 5 6 7 8 9 10 11 12 13 …
– attr(*, “dimnames”)=List of 2
..$ : chr [1:292] “4” “5” “6” “7” …
..$ : chr [1:14] “Distance” “Hmax” “Nsp_temp” “Animal” …
> # We can rename the third column:
> colnames(data_an)[3] = “Nsp”
> View(data_an)

fig6.png

A planilha final, mostrando todas as nossas variáveis pra cada parcela, pronta pra análise!

Se quisermos podemos salvar ela. Eu gosto de salvar as planilhas de análise, mas tendo o scipt, não há necessidade.

 

write.table(data_an, file=”data_analysis.txt”, quote=F, sep=”,”, row.names=F)

Usamos o comando write.table, especificando qual objeto iremos salvar (data_an), o nome do arquivo criado (“data_analysis.txt”), que não queremos aspas em variáveis de texto (quote=F), que as colunas serão separadas por vírgula (sep=”,”) e que não queremos nomes das linhas (row.names=F).

Acabou! o/

* Eu quaaase escrevi “Confie em mim. Eu tenho doutorado.” – mas essa seria péssima demais até pra mim…

 

 

Anúncios

8 pensamentos sobre “Organizando dados: de dados brutos a dados para análise, em R

  1. Pingback: Como organizar uma planilha de dados – Sobrevivendo na Ciência

  2. Muito bom, Pavel.

    Obrigada por compartilhar. Vou ler e estudar tudo, pois irá me ajudar muito no projeto do R que desenvolvo com meus discentes do curso de Ciências Biológicas.

  3. Ótimo post, Pavel. Muito obrigado!
    Essa coisa de mostrar que está usando uma distro Linux se parece com os meus pensamentos ao fazer prints para trabalhos de disciplinas. É quase uma forma de resistência, haha.
    Um abraço.

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair /  Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair /  Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair /  Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair /  Alterar )

w

Conectando a %s