0Pricing
R Academy · Aula

Vetorização para obter velocidade

Substitua laços explícitos por operações vetorizadas para obter grandes ganhos de velocidade.

Vetorização para obter velocidade é uma aula grátis de R Academy no CoddyKit. Esta é a aula 3 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de R Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de R Academy inclui 4 aulas no total.

Por que a vetorização é importante

R é uma linguagem interpretada, portanto loops for têm sobrecarga em cada iteração — despacho de chamadas de função, verificação de limites e coerção de tipos. Operações vetorizadas transferem esse trabalho para código C compilado, que é executado muitas vezes mais rapidamente.

A vetorização é a otimização de maior impacto disponível no R básico.

Exemplo: loop versus cumsum()

Calcular um total acumulado com um loop for em comparação com a função integrada cumsum() evidencia claramente a diferença. cumsum() chama código compilado no nível C e processa todo o vetor em uma única passagem.

n <- 500000
x <- rnorm(n)

t_loop <- system.time({
  result <- numeric(n)
  result[1] <- x[1]
  for (i in 2:n) result[i] <- result[i-1] + x[i]
})['elapsed']

t_vec <- system.time({
  result2 <- cumsum(x)
})['elapsed']

cat('Loop  :', t_loop, 's
')
cat('cumsum:', t_vec, 's
')

ifelse() versus for + if

ifelse(condition, yes, no) é uma condicional vetorizada que avalia a condição em todo um vetor de uma só vez. Ela substitui loops for + if elemento a elemento por uma única passagem no nível C.

n <- 300000
x <- rnorm(n)

t_loop <- system.time({
  result <- numeric(n)
  for (i in seq_len(n)) result[i] <- if (x[i] > 0) x[i] else -x[i]
})['elapsed']

t_vec <- system.time({
  result2 <- ifelse(x > 0, x, -x)
})['elapsed']

cat('for+if :', t_loop, 's
')
cat('ifelse :', t_vec, 's
')

Pré-alocando vetores de resultados

Quando um loop é inevitável, pré-aloque o vetor de resultados antes do loop. Aumentar um vetor com c(result, new_val) dentro de um loop copia o vetor inteiro a cada iteração — O(n^2) operações totais de memória.

n <- 20000

t_grow <- system.time({
  result <- c()
  for (i in seq_len(n)) result <- c(result, i^2)
})['elapsed']

t_prealloc <- system.time({
  result2 <- numeric(n)
  for (i in seq_len(n)) result2[i] <- i^2
})['elapsed']

cat('Growing vector:', t_grow, 's
')
cat('Pre-allocated :', t_prealloc, 's
')

Tipos corretos para pré-alocação

Use o construtor tipado correspondente aos seus dados para evitar coerção implícita durante a pré-alocação:

  • numeric(n) — números de ponto flutuante de precisão dupla
  • integer(n) — números inteiros
  • character(n) — cadeias de caracteres vazias
  • logical(n) — valores FALSE
  • vector('list', n) — lista de valores NULL
n <- 5
cat('numeric  :', numeric(n), '
')
cat('integer  :', integer(n), '
')
cat('logical  :', logical(n), '
')
cat('character:', character(n), '
')
cat('list len :', length(vector('list', n)), '
')

colSums() e rowSums() versus apply()

Para operações com matrizes, colSums(m), rowSums(m), colMeans(m) e rowMeans(m) são rotinas C altamente otimizadas. Elas são consistentemente mais rápidas que apply(m, 1, sum), que despacha a função R sum uma vez por linha.

m <- matrix(rnorm(1000 * 2000), nrow = 1000)

t_apply <- system.time(apply(m, 2, sum))['elapsed']
t_colsums <- system.time(colSums(m))['elapsed']

cat('apply(m,2,sum):', t_apply, 's
')
cat('colSums(m)    :', t_colsums, 's
')

A aritmética vetorizada é sempre rápida

Operações aritméticas básicas em vetores — +, -, *, /, ^, sqrt(), log(), exp() — são todas vetorizadas. Elas operam elemento a elemento em todo um vetor em uma única chamada C. Prefira-as sempre aos loops.

x <- 1:1000000

t1 <- system.time(y <- x^2 + 2*x + 1)['elapsed']

t2 <- system.time({
  y2 <- numeric(length(x))
  for (i in seq_along(x)) y2[i] <- x[i]^2 + 2*x[i] + 1
})['elapsed']

cat('Vectorized:', t1, 's
')
cat('Loop      :', t2, 's
')

Subconjunto lógico em vez de loops

Filtrar um vetor com uma condição lógica é vetorizado. Em vez de percorrer o vetor e adicionar elementos condicionalmente, crie um índice lógico e faça o subconjunto uma única vez — o código C subjacente faz uma passagem.

x <- rnorm(500000)

t_loop <- system.time({
  pos <- c()
  for (v in x) if (v > 0) pos <- c(pos, v)
})['elapsed']

t_vec <- system.time({
  pos2 <- x[x > 0]
})['elapsed']

cat('Loop filter:', t_loop, 's
')
cat('Logical idx:', t_vec, 's
')

which() e tabulate() para trabalhar com índices

Quando precisar das posições dos valores TRUE, which(condition) é vetorizado e rápido. tabulate(bin_vector) conta ocorrências de inteiros mais rapidamente do que table() para intervalos densos de inteiros.

x <- sample(1:10, 100000, replace = TRUE)

t_table    <- system.time(table(x))['elapsed']
t_tabulate <- system.time(tabulate(x, nbins = 10))['elapsed']

cat('table()   :', t_table, 's
')
cat('tabulate():', t_tabulate, 's
')

idx <- which(x == 5)
cat('Positions of 5: first 5 =', head(idx, 5), '
')

Quando os loops ainda são aceitáveis

Nem todo loop é ruim. Loops são aceitáveis quando:

  • Cada iteração depende do resultado anterior (dependência sequencial)
  • O número de iterações é pequeno (< 1000)
  • O corpo do loop chama uma função complexa sem equivalente vetorizado

Nesses casos, concentre-se na pré-alocação e evite aumentar estruturas dentro do loop.

# Sequential dependency -- loop is correct here
fib <- function(n) {
  result <- integer(n)
  result[1] <- 1L
  if (n >= 2) result[2] <- 1L
  for (i in seq_len(n)[-c(1,2)]) result[i] <- result[i-1] + result[i-2]
  result
}
cat('Fibonacci:', fib(10), '
')

Resumo da vetorização

Principais regras de vetorização para obter código R rápido:

  • Use cumsum/cumprod/diff para acumulação sequencial
  • Use ifelse() para condicionais elemento a elemento
  • Faça a pré-alocação com numeric(n) / vector('list',n)
  • Prefira colSums/rowSums/colMeans/rowMeans a apply()
  • O subconjunto lógico é melhor do que loops de filtragem

Verificação rápida: pré-alocação

Por que aumentar um vetor com result <- c(result, new_val) dentro de um loop é tão lento para valores grandes de n?

Recapitulação da vetorização

A vetorização é o principal recurso de desempenho do R:

  • Funções vetorizadas (cumsum, ifelse, operadores aritméticos) chamam código C compilado — são de 10 a 100 vezes mais rápidas do que loops R equivalentes
  • Faça a pré-alocação dos contêineres de resultados antes de qualquer loop inevitável para evitar cópias O(n^2)
  • colSums/rowSums são melhores do que apply() para agregações de matrizes
  • O subconjunto lógico substitui loops de filtragem de forma simples e rápida

Perguntas Frequentes

A aula “Vetorização para obter velocidade” é grátis?

Sim — o texto completo de “Vetorização para obter velocidade” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de R Academy, atualize para CoddyKit PRO. O curso de R Academy inclui 4 aulas no total.

O que vou aprender em “Vetorização para obter velocidade”?

Substitua laços explícitos por operações vetorizadas para obter grandes ganhos de velocidade. Você pratica R Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar R Academy?

Nenhuma experiência prévia é necessária. R Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 3 de 4.

Quanto tempo leva a aula “Vetorização para obter velocidade”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de R Academy?

Sim. Cada aula de R Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. system.time() e proc.time()
  2. Criação de perfis de código com Rprof e profvis
  3. Vetorização para obter velocidade
  4. Avaliação de desempenho com microbenchmark
← Voltar para R Academy