7.3 Operações com vetores

Como o R é uma linguagem vetorizada, as operações são aplicadas a cada elemento do vetor automaticamente, sem a necessidade de laços (ou loopings) ao longo do vetor. Esta é uma das grandes vantagens do .

Operações aritméticas podem ser aplicadas diretamente entre vetores.

# desvios da prec em relação a média climatológica
prec - prec_clim
#>  jan  fev  mar  abr  mai  jun  jul  ago  set  out  nov  dez 
#>   70   -5   50  -88  -60  -30  -28  -38  -10  -45 -190   60
# anomalia em % relativa
prec/prec_clim * 100
#>       jan       fev       mar       abr       mai       jun       jul       ago 
#> 130.43478  97.56098 131.25000  12.00000   0.00000   0.00000  30.00000  36.66667 
#>       set       out       nov       dez 
#>  90.90909  72.72727   5.00000 127.27273
# transformação boxcox da prec com alpha = 0.335
((prec^0.335 - 1)/0.335)
#>       jan       fev       mar       abr       mai       jun       jul       ago 
#> 17.188869 14.626583 14.916806  3.877403 -2.985075 -2.985075  3.877403  5.422424 
#>       set       out       nov       dez 
#> 10.977168 11.856532  3.470802 16.727944
# cte^intervalo
mean(prec)^(1/2:5)
#> [1] 10.271319  4.725171  3.204890  2.538929

Uma peculiaridade do é o tratamento de operações com vetores de tamanhos diferentes. O vetor menor é reciclado, de forma que seus elementos sejam repetidos em ordem até atingirem o tamanho do vetor mais longo envolvido na operação.

# velocidades em m s-1
(vel_ms <- c(1.5, 0.3, 1.4, 2.0))
#> [1] 1.5 0.3 1.4 2.0
# fator de conversão para km h-1
fator_conv <- 3.6
vel_ms * fator_conv
#> [1] 5.40 1.08 5.04 7.20
# equivalência
fator_conv <- c(3.6, 3.6, 3.6, 3.6)
vel_ms * fator_conv
#> [1] 5.40 1.08 5.04 7.20

A constante fator_conv = 3.6 nesse caso é reciclada 4 vezes (tamanho do vetor vel_ms) e então multiplicada por cada elemento de vetor_dbl. Por isso os resultados no código acima são idênticos. Essa funcionalidade de fazer um vetor do mesmo tamanho de outro é conhecida como reciclagem. Se o vetor mais longo não tem tamanho múltiplo do mais curto, o realiza a operação com uma mensagem de aviso.

1:10 * 1:2
#>  [1]  1  4  3  8  5 12  7 16  9 20
1:10 * 1:3
#> Warning in 1:10 * 1:3: longer object length is not a multiple of shorter object
#> length
#>  [1]  1  4  9  4 10 18  7 16 27 10

A reciclagem é um recurso útil, mas também perigoso. Seu código pode ficar mais elegante ou gerar resultados inesperados.

Operações aritméticas podem ser feitas com vetores lógicos, como nos exemplos abaixo:

FALSE - TRUE
#> [1] -1
prec_clim >= 100
#>  [1]  TRUE  TRUE  TRUE  TRUE FALSE FALSE FALSE FALSE  TRUE  TRUE  TRUE  TRUE
(prec_clim >= 100) * 1:12
#>  [1]  1  2  3  4  0  0  0  0  9 10 11 12

7.3.1 Comparações

Vetores lógicos resultam da comparação de números ou caracteres. A Tabela 7.1 apresenta os principais operadores lógicos para comparações.

Tabela 7.1: Operadores Lógicos
Operador Descrição
< menor que
<= menor ou igual a
> maior que
>= maior ou igual
== idêntico
!= diferente
!x não é x (negação)
x | y x ou y
x & y x e y
isTRUE(x) teste se x é verdadeiro
%in% está contido em

Este conjunto de operadores permite diversas comparações entre vetores, por exemplo:

  • quais meses de prec foram abaixo do normal?
prec
#> jan fev mar abr mai jun jul ago set out nov dez 
#> 300 200 210  12   0   0  12  22 100 120  10 280
prec_clim
#>  [1] 230 205 160 100  60  30  40  60 110 165 200 220
prec - prec_clim < 0
#>   jan   fev   mar   abr   mai   jun   jul   ago   set   out   nov   dez 
#> FALSE  TRUE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE FALSE

O operador %in% serve para verificar se um vetor está contido parcial ou totalmente em outro vetor.

# operador está contido em
c(200, 150, 100) %in% prec
#> [1]  TRUE FALSE  TRUE
# 2:4 são elementos de x?
is.element(c(200, 150, 100), prec)
#> [1]  TRUE FALSE  TRUE

Nos exemplos acima, vimos como buscar os os elementos de um vetor para apenas uma condição. Entretanto, frequentemente precisamos testar mais condições, ou seja, combinar comparações. Por exemplo, para condições do tipo:

  • \(0 < prec \leq 100\)
  • \(prec < 50\) ou \(prec \geq 150\)

precisamos usar os operadores relacionais:

  • & e && ("e")

  • | e || ("ou")

# prec entre 0 e 100 mm
prec > 0 & prec <= 100
#>   jan   fev   mar   abr   mai   jun   jul   ago   set   out   nov   dez 
#> FALSE FALSE FALSE  TRUE FALSE FALSE  TRUE  TRUE  TRUE FALSE  TRUE FALSE
# prec abaixo de 50 e acima de 150 mm
prec < 50 | prec >= 150
#>   jan   fev   mar   abr   mai   jun   jul   ago   set   out   nov   dez 
#>  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE FALSE FALSE  TRUE  TRUE

A ordem das operações pode ser controlada por parênteses. Os operadores & e | são vetorizados (retornam vetores de mesmo tamanho que os vetores testados).

A forma dupla (&& ou ||) compara somente um elemento de cada lado, enquanto a forma normal (& e |), compara cada elemento dos vetores em cada lado.

a <- c(1, 1, 0, 1)
b <- c(2, 1, 0, 1)
# forma normal verifica cada elemento de a e cada elemento de b
a == 1 & b == 1
#> [1] FALSE  TRUE FALSE  TRUE
# forma dupla verifica somente o primeiro elemento de a e o primeiro elemento de b
# retornando somente um resultado
a == 1 && b == 1
#> [1] FALSE
Demonstração da diferença entre & e &&.
a b a==1 b==1 a == 1 & b == 1 a == 1 && b == 1
1 2 TRUE FALSE FALSE FALSE
1 1 TRUE TRUE TRUE
0 0 FALSE FALSE FALSE
1 1 TRUE TRUE TRUE

Podem haver mais que duas condições a serem testadas. As condições podem ser combinadas usando múltiplos & ou |. As diferentes condições podem ser agrupadas por parênteses assim como feito nas operações matemáticas.

7.3.1.1 Testes de igualdade

A comparação de igualdade no pode ser meio confusa devido as forma de armazenamento diferentes dos números.

0.6 - 0.3
#> [1] 0.3
0.9 - 0.6
#> [1] 0.3
0.3 == 0.3
#> [1] TRUE

Tudo normal, mas ao comparar operações com valores decimais, você pode se surpreender:

(0.6 - 0.3) == (0.9 - 0.6)
#> [1] FALSE

Isso ocorre por imprecisão no final da parte decimal que pode ser arrendondada incorretamente. Isso não acarreta problema na maioria dos cálculos. Para evitar esse problema é melhor comparar os resultados usando a função all.equal().

all.equal(
  target = 0.6 - 0.3,
  current = 0.9 - 0.6
)
#> [1] TRUE

A all.equal() inclui uma tolerância na comparação (\(1,5\times10^{-8}\)) fazendo com aquela imprecisão seja ignorada. Para mais detalhes consulte ?all.equal.

7.3.2 Funções any e all

Estas funções fornecem um único valor (vetor lógico de tamanho 1) para resumir ou descrever o resultado da condição aplicada ao vetor.

vetor <- c(0, 1, -1, -2, 3, 5, -5)
all(vetor < 0) # todas as posições são maiores que 0 ?
#> [1] FALSE
any(vetor > 0) # alguma posição é maior que 0?
#> [1] TRUE
  • all() verifica se a condição avaliada é válida para todos elementos de um vetor;

  • any() verifica se a condição avaliada é válida para pelo menos um dos elementos de um vetor;