Capítulo 2 (Básico da) Manipulação de data frames
Ainda que seja possivel criar um data frame entrando diretamente com os dados via linha de comando, é mais comum importamos tabelas a partir de arquivos .csv
, .txt
ou outros formatos. Ao importar estes tipos de arquivo, o R os lê como data.frames
.
Inicialmente vamos introduzir métodos de preparação de uma nova seção em R e importação/exportação de tabelas.
2.1 Iniciando uma seção de trabalho
Seção no R, se refere ao ambiente em que ficam armazenados os objetos (vetores, matrizes, data frames, etc.) criados durante o processo de manipulação e análise de dados. Ao fechar uma seção do R (ex. ao sair do R Stúdio), esta pode ser salva guardando os objetos criados. O arquivo de uma seção é salvo com extensão .RData
.
Ao abrir um novo script (com extensão .r
) em um editor de texto é necessário definir o diretório em que iremos trabalhar. Este diretório de trabalho será o local de onde iremos importar dados, e para onde iremos salvar as figuras e tabelas criadas ao longo do trabalho. No R-Studio, um novo script pode ser aberto via menu Arquivo --> Novo script
. Ao iniciar o R-Studio abre-se uma nova seção. O diretório desta seção pode ser verificado pelo comando:
getwd()
Crie uma pasta \(\texttt{IntroR}\) e direcione a seção de trabalho para esta pasta utilizando a função setwd("C:/seu_caminho/IntroR")
e verifique se houve mudança com a função getwd()
setwd("C:/seu_caminho/IntroR")
getwd()
## [1] "C:/seu_caminho/IntroR"
A partir deste momento o R irá ler e salvar aquivos sempre neste diretório.
2.2 Importando arquivos .csv
Importe o conjunto dados dbenv.csv
. Abra o arquivo em algum editor de texto e veja as características deste arquivo. Você verá por exemplo que ele é composto por 11 variáveis (colunas) mensuradas em 30 pontos (linhas). Este conjunto de dados pode ser obtido Aqui em formato .csv. Após fazer o download, você pode importar o conjunto de dados por:
<- read.csv(file = "C:/seu_caminho/IntroR/dbenv.csv",
dbenv header = TRUE, dec = '.', sep = ',')
A função read.csv
possui diferentes argumentos. A argumento header
define se a primeira linha consiste do cabeçalho (TRUE
) ou não (FALSE
). O argumento dec
define se o separador decimal consiste de vírgula ou ponto e o argumento sep
informa sobre qual é o caracter separador de colunas utilizado no arquivo. No arquivo em questão as colunas são separadas por vírgulas. Outros tipos de separadores comuns são ponto-e-vírgula ou tabulações.
Veja os nomes das 11 variáveis (cabeçalho), a dimensão da tabela (número de linhas e colunas) e sua estrutura (um data.frame
formado por 11 vetores numéricos).
dbenv
## dfs alt slo flo pH har pho nit amm oxy bdo
## 1 3 934 6.176 84 79 45 1 20 0 122 27
## 2 22 932 3.434 100 80 40 2 20 10 103 19
## 3 102 914 3.638 180 83 52 5 22 5 105 35
## 4 185 854 3.497 253 80 72 10 21 0 110 13
## 5 215 849 3.178 264 81 84 38 52 20 80 62
## 6 324 846 3.497 286 79 60 20 15 0 102 53
## 7 268 841 4.205 400 81 88 7 15 0 111 22
## 8 491 792 3.258 130 81 94 20 41 12 70 81
## 9 705 752 2.565 480 80 90 30 82 12 72 52
## 10 990 617 4.605 1000 77 82 6 75 1 100 43
## 11 1234 483 3.738 1990 81 96 30 160 0 115 27
## 12 1324 477 2.833 2000 79 86 4 50 0 122 30
## 13 1436 450 3.091 2110 81 98 6 52 0 124 24
## 14 1522 434 2.565 2120 83 98 27 123 0 123 38
## 15 1645 415 1.792 2300 86 86 40 100 0 117 21
## 16 1859 375 3.045 1610 80 88 20 200 5 103 27
## 17 1985 348 1.792 2430 80 92 20 250 20 102 46
## 18 2110 332 2.197 2500 80 90 50 220 20 103 28
## 19 2246 310 1.792 2590 81 84 60 220 15 106 33
## 20 2477 286 2.197 2680 80 86 30 300 30 103 28
## 21 2812 262 2.398 2720 79 85 20 220 10 90 41
## 22 2940 254 2.708 2790 81 88 20 162 7 91 48
## 23 3043 246 2.565 2880 81 97 260 350 115 63 164
## 24 3147 241 1.386 2976 80 99 140 250 60 52 123
## 25 3278 231 1.792 3870 79 100 422 620 180 41 167
## 26 3579 214 1.792 3910 79 94 143 300 30 62 89
## 27 3732 206 2.565 3960 81 90 58 300 26 72 63
## 28 3947 195 1.386 4320 83 100 74 400 30 81 45
## 29 4220 183 1.946 6770 78 110 45 162 10 90 42
## 30 4530 172 1.099 6900 82 109 65 160 10 82 44
colnames(dbenv)
## [1] "dfs" "alt" "slo" "flo" "pH" "har" "pho" "nit" "amm" "oxy" "bdo"
dim(dbenv)
## [1] 30 11
Observação: arquivos .txt
podem ser lidos com a função read.table
. Veremos a frente funções para leitura de outros formatos.
2.3 Seleção de linhas e colunas em data frames
No data frame que importamos as colunas têm nomes que podem ser acessados por:
colnames(dbenv)
## [1] "dfs" "alt" "slo" "flo" "pH" "har" "pho" "nit" "amm" "oxy" "bdo"
O nome das linhas podem ser acessados por:
rownames(dbenv)
## [1] "1" "2" "3" "4" "5" "6" "7" "8" "9" "10" "11" "12" "13" "14" "15"
## [16] "16" "17" "18" "19" "20" "21" "22" "23" "24" "25" "26" "27" "28" "29" "30"
Os números “entre aspas” significam que o R está lendo os nomes das linhas não como números, mas como caracteres.
Podemos utilizar colunas específicas deste por meio de seus nomes:
<- c("dfs", "flo", "oxy")
colunas dbenv[,colunas]
## dfs flo oxy
## 1 3 84 122
## 2 22 100 103
## 3 102 180 105
## 4 185 253 110
## 5 215 264 80
## 6 324 286 102
## 7 268 400 111
## 8 491 130 70
## 9 705 480 72
## 10 990 1000 100
## 11 1234 1990 115
## 12 1324 2000 122
## 13 1436 2110 124
## 14 1522 2120 123
## 15 1645 2300 117
## 16 1859 1610 103
## 17 1985 2430 102
## 18 2110 2500 103
## 19 2246 2590 106
## 20 2477 2680 103
## 21 2812 2720 90
## 22 2940 2790 91
## 23 3043 2880 63
## 24 3147 2976 52
## 25 3278 3870 41
## 26 3579 3910 62
## 27 3732 3960 72
## 28 3947 4320 81
## 29 4220 6770 90
## 30 4530 6900 82
Também podemos acessá-las pela sua posição:
<- c(1, 3, 4)
colunas_num dbenv[,colunas_num]
## dfs slo flo
## 1 3 6.176 84
## 2 22 3.434 100
## 3 102 3.638 180
## 4 185 3.497 253
## 5 215 3.178 264
## 6 324 3.497 286
## 7 268 4.205 400
## 8 491 3.258 130
## 9 705 2.565 480
## 10 990 4.605 1000
## 11 1234 3.738 1990
## 12 1324 2.833 2000
## 13 1436 3.091 2110
## 14 1522 2.565 2120
## 15 1645 1.792 2300
## 16 1859 3.045 1610
## 17 1985 1.792 2430
## 18 2110 2.197 2500
## 19 2246 1.792 2590
## 20 2477 2.197 2680
## 21 2812 2.398 2720
## 22 2940 2.708 2790
## 23 3043 2.565 2880
## 24 3147 1.386 2976
## 25 3278 1.792 3870
## 26 3579 1.792 3910
## 27 3732 2.565 3960
## 28 3947 1.386 4320
## 29 4220 1.946 6770
## 30 4530 1.099 6900
O mesmo é válido para as linhas.
<- c("3", "7", "9")
linhas dbenv[linhas,]
## dfs alt slo flo pH har pho nit amm oxy bdo
## 3 102 914 3.638 180 83 52 5 22 5 105 35
## 7 268 841 4.205 400 81 88 7 15 0 111 22
## 9 705 752 2.565 480 80 90 30 82 12 72 52
Também podemos acessá-las pela sua posição:
<- c(3, 7, 9)
linhas_num dbenv[linhas_num,]
## dfs alt slo flo pH har pho nit amm oxy bdo
## 3 102 914 3.638 180 83 52 5 22 5 105 35
## 7 268 841 4.205 400 81 88 7 15 0 111 22
## 9 705 752 2.565 480 80 90 30 82 12 72 52
Finalmente, podemos combinar estes procedimentos para selecionar sub-conjunto de linhas e colunas.
dbenv[linhas,colunas]
## dfs flo oxy
## 3 102 180 105
## 7 268 400 111
## 9 705 480 72
2.4 Adicionando novas colunas a um data frame
Este conjunto de dados mostra medidas físicas e químicas obtidas em um riacho seguindo do trecho alto de cabeceira seguindo para os trechos baixos próximos à foz. O ponto mais alto (934 m de altitude) está a 3 km da cabeceira enquanto o ponto mais baixo está a 172 m de altitude e a 4530 km da cabeceira. Vamos criar uma nova variável categorizando os trechos do rio em “Alto,” “Medio” e “Baixo” assumindo a seguinte relação:
- 0 a 300 m: Baixo;
- 300 a 600 m: Médio;
- Acima de 600 m: Alto.
<- cut(dbenv$alt, breaks = c(0, 300, 600, 1000),
elv_cat labels = c("Baixo", "Medio", "Alto"))
A inserção do novo objeto elv_cat
no data frame pode ser feito simplesmente por:
$trecho <- elv_cat dbenv
Assim, inserimos assim, uma nova coluna denominada trecho
contendo uma variável categórica com três níveis.
head(dbenv)
## dfs alt slo flo pH har pho nit amm oxy bdo trecho
## 1 3 934 6.176 84 79 45 1 20 0 122 27 Alto
## 2 22 932 3.434 100 80 40 2 20 10 103 19 Alto
## 3 102 914 3.638 180 83 52 5 22 5 105 35 Alto
## 4 185 854 3.497 253 80 72 10 21 0 110 13 Alto
## 5 215 849 3.178 264 81 84 38 52 20 80 62 Alto
## 6 324 846 3.497 286 79 60 20 15 0 102 53 Alto
Poderíamos ter realizado exatamente o mesmo utilizando a função transform()
. Vamos utilizá-la a seguir como exemplo, criando uma nova variável categórica a partir do oxigênio dissolvido, considerando 3 níveis: pobre (0 a 5), médio (5 a 8), saturado (> 8).
<- transform(dbenv,
dbenv saturacao = cut(dbenv$oxy, breaks = c(0, 40, 109, 124),
labels = c("Pobre", "Medio", "Saturado")))
Veja agora o data frame
dbenv
## dfs alt slo flo pH har pho nit amm oxy bdo trecho saturacao
## 1 3 934 6.176 84 79 45 1 20 0 122 27 Alto Saturado
## 2 22 932 3.434 100 80 40 2 20 10 103 19 Alto Medio
## 3 102 914 3.638 180 83 52 5 22 5 105 35 Alto Medio
## 4 185 854 3.497 253 80 72 10 21 0 110 13 Alto Saturado
## 5 215 849 3.178 264 81 84 38 52 20 80 62 Alto Medio
## 6 324 846 3.497 286 79 60 20 15 0 102 53 Alto Medio
## 7 268 841 4.205 400 81 88 7 15 0 111 22 Alto Saturado
## 8 491 792 3.258 130 81 94 20 41 12 70 81 Alto Medio
## 9 705 752 2.565 480 80 90 30 82 12 72 52 Alto Medio
## 10 990 617 4.605 1000 77 82 6 75 1 100 43 Alto Medio
## 11 1234 483 3.738 1990 81 96 30 160 0 115 27 Medio Saturado
## 12 1324 477 2.833 2000 79 86 4 50 0 122 30 Medio Saturado
## 13 1436 450 3.091 2110 81 98 6 52 0 124 24 Medio Saturado
## 14 1522 434 2.565 2120 83 98 27 123 0 123 38 Medio Saturado
## 15 1645 415 1.792 2300 86 86 40 100 0 117 21 Medio Saturado
## 16 1859 375 3.045 1610 80 88 20 200 5 103 27 Medio Medio
## 17 1985 348 1.792 2430 80 92 20 250 20 102 46 Medio Medio
## 18 2110 332 2.197 2500 80 90 50 220 20 103 28 Medio Medio
## 19 2246 310 1.792 2590 81 84 60 220 15 106 33 Medio Medio
## 20 2477 286 2.197 2680 80 86 30 300 30 103 28 Baixo Medio
## 21 2812 262 2.398 2720 79 85 20 220 10 90 41 Baixo Medio
## 22 2940 254 2.708 2790 81 88 20 162 7 91 48 Baixo Medio
## 23 3043 246 2.565 2880 81 97 260 350 115 63 164 Baixo Medio
## 24 3147 241 1.386 2976 80 99 140 250 60 52 123 Baixo Medio
## 25 3278 231 1.792 3870 79 100 422 620 180 41 167 Baixo Medio
## 26 3579 214 1.792 3910 79 94 143 300 30 62 89 Baixo Medio
## 27 3732 206 2.565 3960 81 90 58 300 26 72 63 Baixo Medio
## 28 3947 195 1.386 4320 83 100 74 400 30 81 45 Baixo Medio
## 29 4220 183 1.946 6770 78 110 45 162 10 90 42 Baixo Medio
## 30 4530 172 1.099 6900 82 109 65 160 10 82 44 Baixo Medio
2.5 Aplicando uma função às linhas ou colunas de um data frame
2.5.1 Família de funções apply
Em muitas situações temos interesse aplicar um determinado cálculo a cada linha ou coluna de um data frame ou para grupos distintos.
Observação: o mesmo raciocínio servese aplica a objetos do tipo matrix
.
Observe por exemplo se extraímos a média aritmética da coluna pH
(\(\times\) 10).
mean(dbenv$pH) # média aritmética
## [1] 80.5
Função tapply
Podemos estar interessados em extrair as médias para cada categoria de elevação. A função tapply()
é útil nestas situações.
tapply(dbenv$pH, dbenv$trecho, mean)
## Baixo Medio Alto
## 80.27273 81.22222 80.10000
A função acima, pode ser lida do modo:
- Selecione a coluna
pH
; - Agrupe os elementos em função dos níveis em
trecho
(Baixo, Medio, Alto); - Calcule a média aritmética para cada sub-grupo.
Note que o resultado foi um vetor em que cada elemento corresponde à média de um sub-grupo. Funções que retornam mais de um valor resultam em um objeto no formato de lista
. A função range()
por exemplo, retorna dois valores (mínimo e máximo). Ao utilizá-la junto à função tapply()
termos como resultado uma lista composta por um vetor para cada subgrupo.
tapply(dbenv$pH, dbenv$trecho, range)
## $Baixo
## [1] 78 83
##
## $Medio
## [1] 79 86
##
## $Alto
## [1] 77 83
Função apply
Podemos aplicar uma determinada função a todas as linhas ou colunas de um data frame (ou matriz).
apply(dbenv[,1:5], MARGIN = 2, mean)
## dfs alt slo flo pH
## 1879.033333 481.500000 2.757733 2220.100000 80.500000
O argumento MARGIN = 2
diz que desejamos aplicar a função ás colunas da matriz. Com MARGIN = 1
aplicamos a função às linhas da matriz.
Função lapply
Se o objeto é do formato lista
, o comando lapply()
aplica uma função a cada elemento da lista. Considere a lista:
<- list(Ilha = c("Ilhabela", "Anchieta", "Cardoso"),
nossalista Areaskm2 = c(347.5, 8.3, 131),
Bioma = rep("Mata Atlantica",3),
Lat = c(23, 25, 23),
Long = c(45, 47, 45))
Veja os resultados dos comandos abaixo:
lapply(nossalista, sort)
## $Ilha
## [1] "Anchieta" "Cardoso" "Ilhabela"
##
## $Areaskm2
## [1] 8.3 131.0 347.5
##
## $Bioma
## [1] "Mata Atlantica" "Mata Atlantica" "Mata Atlantica"
##
## $Lat
## [1] 23 23 25
##
## $Long
## [1] 45 45 47
lapply(nossalista, sort)
## $Ilha
## [1] "Anchieta" "Cardoso" "Ilhabela"
##
## $Areaskm2
## [1] 8.3 131.0 347.5
##
## $Bioma
## [1] "Mata Atlantica" "Mata Atlantica" "Mata Atlantica"
##
## $Lat
## [1] 23 23 25
##
## $Long
## [1] 45 45 47
Obs.: Existem oitras funções neste grupo, Veja o help()
destas funções pois são extremamente úteis na manipulação de data frames e listas.
?tapply
?apply
?lapply
?mapply ?replicate
2.5.2 Função aggregate
A função tapply()
aplica uma função a subgrupos de uma única coluna. A função aggregate()
faz o mesmo, porém para multiplas colunas agrupadas de acordo com uma ou mais categorias. O comando abaixo calcula os valores médios das variáveis para os trechos alto, médio e baixo combinmados com níveis acima e abaixo de pH = 80.
<- aggregate(dbenv[, 1:11],
media.trecho by = list(TRECHO = dbenv$trecho,
ALCALINO = dbenv$pH >= 80),
FUN = mean)
media.trecho
## TRECHO ALCALINO dfs alt slo flo pH har
## 1 Baixo FALSE 3472.250 222.5000 1.982000 4317.5000 78.75000 97.25000
## 2 Medio FALSE 1324.000 477.0000 2.833000 2000.0000 79.00000 86.00000
## 3 Alto FALSE 439.000 799.0000 4.759333 456.6667 78.33333 62.33333
## 4 Baixo TRUE 3402.286 228.5714 1.986571 3786.5714 81.14286 95.57143
## 5 Medio TRUE 1754.625 393.3750 2.501500 2206.2500 81.50000 91.50000
## 6 Alto TRUE 284.000 847.7143 3.396429 258.1429 80.85714 74.28571
## pho nit amm oxy bdo
## 1 157.50000 325.50000 57.5000000 70.75000 84.75000
## 2 4.00000 50.00000 0.0000000 122.00000 30.00000
## 3 9.00000 36.66667 0.3333333 108.00000 41.00000
## 4 92.42857 274.57143 39.7142857 77.71429 73.57143
## 5 31.62500 165.62500 7.5000000 111.62500 30.50000
## 6 16.00000 36.14286 8.4285714 93.00000 40.57143
2.6 Exportando um data frame
Finalmente, podemos exportar um resultado para arquivos texto. Vamos exportar o data frame media.trecho
obtido acima para um arquivo .csv
.
write.table(media.trecho, file = "Mediaportecho.csv",
sep = ",", dec = '.', row.names = FALSE,
col.names = TRUE)
- Veja o
help()
sobre a funçãowrite.table
para mais informações. - O arquivo será salvo em seu diretório de trabalho, aquele que você definiu no início desta seção com o comando
setwd()
.