chesteR - reunião 09

Operações por agrupamentos

Abaixo está o data.frame que seguiremos utilizando (nativo do R):

names(iris)

[1] "Sepal.Length" "Sepal.Width"

[3] "Petal.Length" "Petal.Width"

[5] "Species"

Como vimos no encontro anterior tapply pode realizar algumas operações por agrupamento. Exemplo:

tapply(X = iris$Petal.Width, INDEX = iris$Species, FUN = mean)

setosa versicolor virginica

0.246      1.326      2.026      

Outra forma de fazer isso seria recebendo o resultado em forma de tabela:

aggregate(Petal.Width ~ Species, data = iris, FUN = mean)

     Species      Petal.Width

1      setosa           0.246

2      versicolor      1.326

3      virginica        2.026

A função aggregate é designada para trabalhar com várias colunas e retornar um data.frame com uma linha para cada categoria, enquanto a tapply é designada para ser usada com vetores (uma única coluna) retornando uma matriz.

Dentre essas funções, qual seria a opção mais rápida?

Para descobrir, foi construída a seguinte função, com as especificações do passo a passo dentro dela:

clock <- function(f) {
  
  # registro do tempo inicial
  tic <- Sys.time()
  
  # função que iremos testar
  f
  
  # registro do tempo final
  toc <- Sys.time()
  
  # tempo que a função gastou para rodar (tf-ti)
  time <- toc - tic
  
  # retornando o resultado da função e o tempo que ela levou, através de uma lista
  list(f, time)
  
}

Aplicando a função nos 2 métodos:

clock(tapply(X = iris$Petal.Width, INDEX = iris$Species, FUN = mean))

[[1]]

setosa versicolor virginica

0.246      1.326      2.026      

[[2]]

Time difference of 0.0009338856 secs

clock(aggregate(Petal.Width ~ Species, data = iris, FUN = mean))

[[1]]

     Species      Petal.Width

1      setosa           0.246

2      versicolor      1.326

3      virginica        2.026

[[2]]

Time difference of 0.002429008 secs

Logo, como foi visto acima, a função tapply é mais rápida! Isso no geral irá ocorrer, ou seja, operações com vetores tendem a ser mais rápidas do que aquelas que envolvem tabelas.

Obs.: Existem outras maneiras mais eficientes de se obter o exato tempo que leva cada função, mas essa é bastante clara e aborda o tópico de funções que começamos a ver no último encontro.

Outros usos da função aggregate, que explicitam suas vantagens:

aggregate(cbind(iris$Petal.Length, iris$Petal.Width), by = list(iris$Species), FUN = mean)

     Group.1              V1      V2

1      setosa           1.462 0.246

2      versicolor      4.260 1.326

3      virginica        5.552 2.026

Existe outra maneira de escrever o mesmo código de maneira simplificada, e o resultado será apresentado abaixo com uma pequena diferença, pois esse método já retorna o nome original das colunas (o que facilita a compreensão do resultado):

aggregate(cbind(Petal.Length, Petal.Width) ~ Species, data = iris, FUN = mean)

     Species        Petal.Length      Petal.Width

1      setosa            1.462                    0.246

2      versicolor       4.260                    1.326

3      virginica         5.552                    2.026

Nas 2 funções acima nós combinamos as colunas através da função cbind gerando a média por espécies das variáveis especificadas (Petal.Length e Petal.Width). Perceba que as funções se diferem no modo de chamar as variáveis. A primeira função exige que o agrupamento seja feito por lista através do argumento by. A segunda função utiliza o formato de fórmula que vimos no sexto encontro.

Exemplo contando o número de vezes que ocorre cada espécie:

aggregate(iris$Species, by = list(iris$Species), FUN = length)

     Group.1            x

1      setosa           50

2      versicolor      50

3      virginica        50

No entanto, a forma mais eficiente e fácil de se fazer isso seria através da função table:

table(iris$Species)

setosa versicolor virginica

50            50            50      

Com isso, podemos analisar tabelas e vetores que possuem categorias de forma rápida e eficiente!

CC BY-SA 4.0 Gabriel de Freitas Pereira. Last modified: June 16, 2022. Website built with Franklin.jl and the Julia programming language.