6.1 Funções da família apply()

Algumas funções da família apply() são muito úteis na manipulação de dados e descrição de dados. Essas funções são muito poderosas, porque permitem você fazer iterações de forma simples, ou seja, você pode aplicar uma função a vários objetos simultaneamente com funções dessa família. O que você faz com essas funções você também faz com as iterações que fazem uso da expressão for(){} (veja seção 6.3), mas essas funções simplificam e aceleram o processo.

6.1.1 Em uma matriz

A função apply() poderia ser traduzida como:

aplique uma função (FUN) a todas as linhas ou colunas (MARGIN) de uma matriz (X):

?apply # Veja o help
# os argumentos dessa função são:
# X = matrix
# MAGRIN = 1 indica linha, 2 indica colunas
# FUN = a função que você deseja aplicar
# ... ARGUMENTOS DESSA FUNCAO SE FOR O CASO

# TOTAIS MARGINAIS
# crie uma matriz
X <- matrix(1:36, nrow = 4, ncol = 9)
colnames(X) <- paste("col", 1:ncol(X))
rownames(X) <- paste("ln", 1:nrow(X))
head(X) # cabeça da matriz criada
col 1 col 2 col 3 col 4 col 5 col 6 col 7 col 8 col 9
ln 1 1 5 9 13 17 21 25 29 33
ln 2 2 6 10 14 18 22 26 30 34
ln 3 3 7 11 15 19 23 27 31 35
ln 4 4 8 12 16 20 24 28 32 36
# calcule para todas as linhas:
# a soma dos valores
apply(X, MARGIN = 1, FUN = sum)
## ln 1 ln 2 ln 3 ln 4 
##  153  162  171  180
# o valor máximo
apply(X, MARGIN = 1, FUN = max)
## ln 1 ln 2 ln 3 ln 4 
##   33   34   35   36
# a média
apply(X, MARGIN = 1, FUN = mean)
## ln 1 ln 2 ln 3 ln 4 
##   17   18   19   20
# o desvio padrão
apply(X, MARGIN = 1, FUN = sd)
##     ln 1     ln 2     ln 3     ln 4 
## 10.95445 10.95445 10.95445 10.95445
# para todas as colunas
# a soma dos valores
apply(X, MARGIN = 2, FUN = sum)
## col 1 col 2 col 3 col 4 col 5 col 6 col 7 col 8 col 9 
##    10    26    42    58    74    90   106   122   138
# o valor máximo
apply(X, MARGIN = 2, FUN = max)
## col 1 col 2 col 3 col 4 col 5 col 6 col 7 col 8 col 9 
##     4     8    12    16    20    24    28    32    36
# a média
apply(X, MARGIN = 2, FUN = mean)
## col 1 col 2 col 3 col 4 col 5 col 6 col 7 col 8 col 9 
##   2.5   6.5  10.5  14.5  18.5  22.5  26.5  30.5  34.5
# o desvio padrão
apply(X, MARGIN = 2, FUN = sd)
##    col 1    col 2    col 3    col 4    col 5    col 6    col 7    col 8 
## 1.290994 1.290994 1.290994 1.290994 1.290994 1.290994 1.290994 1.290994 
##    col 9 
## 1.290994

As funções rowSums(), rowMeans(), colSums(), ou colMeans() são equivalentes à função apply(). Elas simplificam o uso para somas (em inglês, sum) e médias (em inglês, mean) de linhas (em inglês, rows) e colunas (em inglês, columns). Se você conhece bem a função apply(), você pode fazer o que essas funções fazem e muito mais. Portanto, ao dominar a função apply(), você acaba por não precisar se preocupar em aprender essas funções mais específicas.

?rowSums
rowSums(X) # soma de cada linha
## ln 1 ln 2 ln 3 ln 4 
##  153  162  171  180
rowMeans(X) # media de cada linha
## ln 1 ln 2 ln 3 ln 4 
##   17   18   19   20
colSums(X) # soma de cada coluna
## col 1 col 2 col 3 col 4 col 5 col 6 col 7 col 8 col 9 
##    10    26    42    58    74    90   106   122   138
colMeans(X) # média de cada coluna
## col 1 col 2 col 3 col 4 col 5 col 6 col 7 col 8 col 9 
##   2.5   6.5  10.5  14.5  18.5  22.5  26.5  30.5  34.5

6.1.2 Em um vetor ou lista

A função lapply() aplica uma função FUN para cada elemento de um vetor ou de uma lista, e retorna um objeto de classe list.

# muito simples, imprime algo linha por linha
ll <- lapply(LETTERS, print)
## [1] "A"
## [1] "B"
## [1] "C"
## [1] "D"
## [1] "E"
## [1] "F"
## [1] "G"
## [1] "H"
## [1] "I"
## [1] "J"
## [1] "K"
## [1] "L"
## [1] "M"
## [1] "N"
## [1] "O"
## [1] "P"
## [1] "Q"
## [1] "R"
## [1] "S"
## [1] "T"
## [1] "U"
## [1] "V"
## [1] "W"
## [1] "X"
## [1] "Y"
## [1] "Z"
class(ll)
## [1] "list"
str(ll)
## List of 26
##  $ : chr "A"
##  $ : chr "B"
##  $ : chr "C"
##  $ : chr "D"
##  $ : chr "E"
##  $ : chr "F"
##  $ : chr "G"
##  $ : chr "H"
##  $ : chr "I"
##  $ : chr "J"
##  $ : chr "K"
##  $ : chr "L"
##  $ : chr "M"
##  $ : chr "N"
##  $ : chr "O"
##  $ : chr "P"
##  $ : chr "Q"
##  $ : chr "R"
##  $ : chr "S"
##  $ : chr "T"
##  $ : chr "U"
##  $ : chr "V"
##  $ : chr "W"
##  $ : chr "X"
##  $ : chr "Y"
##  $ : chr "Z"
# suponha três vetores de tamanhos diferentes
v1 <- sample(1:1000, 50)
length(v1)
## [1] 50
v2 <- sample(1:100, 30)
length(v2)
## [1] 30
v3 <- sample(1000:2000, 90)
length(v3)
## [1] 90
# imagina que isso esteja numa lista
ml <- list(v1, v2, v3)
class(ml)
## [1] "list"
length(ml)
## [1] 3
# posso usar lapply para calcular a media desses vetores
lapply(ml, mean) # note que retorna uma lista
## [[1]]
## [1] 549.86
## 
## [[2]]
## [1] 49.73333
## 
## [[3]]
## [1] 1526.333
lt <- lapply(ml, mean) # podemos guardar
lt <- as.vector(lt, mode = "numeric") # e transformar num vetor. MODE neste caso é fundamental usar
lt
## [1]  549.86000   49.73333 1526.33333

6.1.3 Por categoria de um fator

A função tapply() aplica uma função FUN em uma coluna numérica individualizando os resultados para cada categoria de um determinado fator.

# vamos usar os dados de Iris novamente
?iris
# calculando o comprimento médio de sepálas pelas categorias de um fator (especies)
class(iris$Sepal.Length) # variavel numerica
## [1] "numeric"
class(iris$Species) # fator com categorias que correspondem a especies
## [1] "factor"
tapply(iris$Sepal.Length, iris$Species, FUN = mean)
##     setosa versicolor  virginica 
##      5.006      5.936      6.588
# calculando o comprimento máximo por especie
tapply(iris$Sepal.Length, iris$Species, FUN = max)
##     setosa versicolor  virginica 
##        5.8        7.0        7.9
# a amplitude de variacao
tapply(iris$Sepal.Length, iris$Species, FUN = range)
## $setosa
## [1] 4.3 5.8
## 
## $versicolor
## [1] 4.9 7.0
## 
## $virginica
## [1] 4.9 7.9
# note que essa funcao sempre retorna um array (que é uma lista de fato, neste caso)
tm <- tapply(iris$Sepal.Length, iris$Species, FUN = min)
class(tm)
## [1] "array"
names(tm)
## [1] "setosa"     "versicolor" "virginica"
tm[["setosa"]] # indexadores de lista
## [1] 4.3
tr <- tapply(iris$Sepal.Length, iris$Species, FUN = range)
class(tr)
## [1] "array"
names(tr)
## [1] "setosa"     "versicolor" "virginica"
tr[["setosa"]]
## [1] 4.3 5.8