1 of 18

Usando apply()

Ricardo Buscariolli - UFABC

ricardo.buscariolli@ufabc.edu.br

2 of 18

Introdução

  • A função apply() é o modelo básico da família de funções apply no R
    • Ela inclui funções específicas como lapply(), sapply(), tapply(), mapply(), vapply(), rapply(), bapply(), eapply(), entre outras.

  • Todas essas funções nos permitem iterar sobre uma estrutura de dados
    • lista, matriz, array, DataFrame ou um recorte selecionado de uma determinada estrutura de dados — e realizar a mesma operação em cada elemento.

  • Essas operações podem envolver
    • Agregação: cálculo de estatísticas descritivas como média, máximo, mínimo, soma, etc.
    • Transformação
    • Qualquer outra função vetorizada, seja ela simples ou complexa, embutida no R ou personalizada.

3 of 18

Introdução

  • A diferença entre as funções da família apply está nos tipos de entrada e saída das estruturas de dados e na forma como cada função realiza a operação.

  • Comparação com loops: a função apply() e suas variações oferecem uma execução de programa significativamente mais rápida e uma sintaxe compacta, de uma única linha, em vez de um bloco de código que ocuparia várias linhas.

  • Isso se torna especialmente importante ao trabalhar com conjuntos de dados de grande porte.

4 of 18

Como usar apply()

  • Vamos explorar algumas das variações mais úteis das funções apply no R.

  • Vamos começar com a principal função do grupo apply: a apply().

  • Ela recebe como entrada um DataFrame, uma matriz ou um array multidimensional e, dependendo do tipo do objeto de entrada e da função passada, retorna um vetor, uma lista, uma matriz ou um array.

5 of 18

Como usar apply()

  • A sintaxe da função apply() é muito simples e possui apenas três parâmetros:

apply(X, MARGIN, FUN)

  • X é o objeto de entrada (um DataFrame, uma matriz ou um array);

  • MARGIN é o parâmetro que determina como a função será aplicada (pode receber os valores 1, 2 ou c(1, 2), o que significa que a função será aplicada por linha, por coluna ou em ambos — linhas e colunas — respectivamente);

  • FUN é a função (embutida ou personalizada) que será aplicada aos dados de entrada.

6 of 18

Como usar apply()

  • Vamos criar uma matriz com 3 linhas e 4 colunas com números indo de 1 a 12

my_matrix <- matrix((1:12), nrow=3)

print(my_matrix)

  • Por exemplo, podemos querer encontrar o valor máximo de cada linha da nossa matriz. Para isso, vamos definir 1 como valor do parâmetro MARGIN e passar a função max:

print(apply(my_matrix, 1, max))

7 of 18

Como usar apply()

  • Agora, vamos calcular a média de cada linha:

apply(my_matrix, 1, mean)

  • Se quisermos calcular a média por coluna, usamos 2

  • No código acima, nós implementamos, na prática, uma agregação na matriz de entrada (que é uma estrutura de dados bidimensional). Como resultado, a saída é um vetor (que é uma estrutura de dados unidimensional) contendo os valores máximos correspondentes de cada linha.

print(apply(my_matrix, 2, mean))

8 of 18

Como usar apply()

  • Agora, vamos calcular a soma dos valores da matriz por coluna (MARGIN=2):

apply(my_matrix, 2, sum)

  • A estrutura de dados de saída é, novamente, um vetor. A função sum é outro exemplo de função de agregação que reduz a dimensionalidade de um objeto de entrada em 1.

9 of 18

Como usar apply()

  • É possível fornecer qualquer função personalizada para o apply(). Vamos definir uma função que calcula a média dos valores ao quadrado para cada entrada:

mean_squared_vals <- function(x) mean(x**2)

  • Assim como fizemos anteriormente, podemos aplicar esta função por linha (MARGIN=1):

print(apply(my_matrix, 1, mean_squared_vals))

  • Também podemos aplicar a função por coluna (MARGIN=2):

print(apply(my_matrix, 2, mean_squared_vals))

10 of 18

Como usar lapply()

  • A função lapply() é uma variação da apply() que aceita como entrada um vetor, uma lista ou um DataFrame, e sempre retorna uma lista (o "l" no nome da função vem de "list").

  • A função especificada é aplicada a cada elemento do objeto de entrada, por isso o comprimento da lista resultante é sempre igual ao comprimento do objeto de entrada.

  • A sintaxe dessa função é semelhante à da apply(), mas aqui não há necessidade do parâmetro MARGIN, já que a função é aplicada elemento por elemento em listas e vetores, e coluna por coluna nos DataFrames:

apply(X, MARGIN, FUN)

11 of 18

Como usar lapply()

  • Vamos ver como ela funciona com vetores, listas e DataFrames.
  • Primeiro, vamos criar uma função simples que soma 1 a um valor de entrada:

CopiarEditaradd_one <- function(x) x+1

  • Vamos testar essa função em um vetor:

CopiarEditarmy_vector = c(1, 2, 3)

print(lapply(my_vector, add_one))

12 of 18

Como usar lapply()

  • Agora, vamos criar uma lista:

my_list = list(TRUE, c(1, 2, 3), 10)

print(my_list)

  • Agora vamos aplicar nossa função nela:

print(lapply(my_list, add_one))

13 of 18

Como usar lapply()

  • Por fim, vamos usar o lapply() em um DataFrame:

my_df <- data.frame(a=1:3, b=4:6, c=7:9, d=10:12)

print(my_df)

  • Agora vamos aplicar nossa função nela:

print(lapply(my_df, add_one))

  • Como mencionamos anteriormente, a função lapply() é aplicada coluna por coluna quando usada com DataFrames.

14 of 18

Como usar sapply()

  • A função sapply() é uma forma simplificada da lapply() (o "s" no nome da função vem de "simplified", ou seja, "simplificada").

  • Ela tem a mesma sintaxe da lapply() (ou seja, sapply(X, FUN))

  • aceita como entrada um vetor, uma lista ou um DataFrame, assim como a lapply(), e tenta reduzir o objeto de saída para a estrutura de dados mais simples possível.

  • Isso significa que, por padrão, a função sapply() retorna:
    • Um vetor, quando a entrada é um vetor;
    • Uma lista, quando a entrada é uma lista cujos elementos têm tamanhos diferentes;
    • Uma matriz, quando a entrada é um DataFrame com colunas de mesmo comprimento.

15 of 18

Como usar sapply()

print(sapply(my_vector, add_one))

print(sapply(my_list, add_one))

print(sapply(my_df, add_one))

16 of 18

Como usar tapply()

  • Usamos a função tapply() para calcular estatísticas descritivas (como média, mediana, mínimo, máximo, soma, etc.) para diferentes fatores (ou seja, categorias).

  • Ela possui a seguinte sintaxe:

tapply(X, INDEX, FUN)

  • X é um objeto no R, normalmente um vetor contendo dados numéricos;
  • INDEX é um objeto no R, geralmente um vetor ou uma lista contendo fatores (as categorias);
  • FUN é a função que será aplicada sobre X.

17 of 18

Como usar tapply()

  • Vamos imaginar que temos informações sobre os salários de um grupo de pessoas com profissões relacionadas a dados: Cientista de Dados (DS), Analista de Dados (DA) e Engenheiro de Dados (DE).
  • Usando a função tapply(), podemos calcular o salário médio por cargo.
  • (Observação: como referência aproximada, usamos aqui informações do site Indeed para estimar a média salarial por função nos EUA, em fevereiro de 2022.)

salaries <- c(80000, 62000, 113000, 68000, 75000, 79000, 112000, 118000, 65000, 117000)

jobs <- c('DS', 'DA', 'DE', 'DA', 'DS', 'DS', 'DE', 'DE', 'DA', 'DE')

print(tapply(salaries, jobs, mean))

18 of 18

Como usar tapply()

  • Vamos imaginar que temos informações sobre os salários de um grupo de pessoas com profissões relacionadas a dados: Cientista de Dados (DS), Analista de Dados (DA) e Engenheiro de Dados (DE).
  • Usando a função tapply(), podemos calcular o salário médio por cargo.
  • (Observação: como referência aproximada, usamos aqui informações do site Indeed para estimar a média salarial por função nos EUA, em fevereiro de 2022.)

salaries <- c(80000, 62000, 113000, 68000, 75000, 79000, 112000, 118000, 65000, 117000)

jobs <- c('DS', 'DA', 'DE', 'DA', 'DS', 'DS', 'DE', 'DE', 'DA', 'DE')

print(tapply(salaries, jobs, mean))