Curso de estatística experimental com aplicações em R

12 à 14 de Novembro de 2014 - Manaus - AM
Prof. Dr. Walmes M. Zeviani
Embrapa Amazônia Ocidental
Lab. de Estatística e Geoinformação - LEG
Departamento de Estatística - UFPR

Trabalhando com objetos

Sequências, repetições e grides

##-----------------------------------------------------------------------------
## Sequências regulares.

1:5
## [1] 1 2 3 4 5
2*(1:5)-1
## [1] 1 3 5 7 9
3*(1:5)-2
## [1]  1  4  7 10 13
x <- seq(from=1, to=12, by=2); x
## [1]  1  3  5  7  9 11
x <- seq(from=1, to=12, length.out=5); x
## [1]  1.00  3.75  6.50  9.25 12.00
x <- seq(from=1, by=3, length.out=5); x
## [1]  1  4  7 10 13
x <- seq(to=20, by=3, length.out=6); x
## [1]  5  8 11 14 17 20
##-----------------------------------------------------------------------------
## Repetições regulares.

x <- rep(1, times=5); x
## [1] 1 1 1 1 1
x <- rep(1:3, times=3); x
## [1] 1 2 3 1 2 3 1 2 3
x <- rep(1:3, each=3); x
## [1] 1 1 1 2 2 2 3 3 3
##-----------------------------------------------------------------------------
## Grides.

## da <- expand.grid(x1=1:3, x2=1:3)
da <- expand.grid(##bloco=1:3,
                  vari=c("Carmen","Lucia","Teresa"),
    ## bloco=factor(1:3),
    bloco=gl(3,1),
                  nitro=seq(0, 100, by=20))

da
##      vari bloco nitro
## 1  Carmen     1     0
## 2   Lucia     1     0
## 3  Teresa     1     0
## 4  Carmen     2     0
## 5   Lucia     2     0
## 6  Teresa     2     0
## 7  Carmen     3     0
## 8   Lucia     3     0
## 9  Teresa     3     0
## 10 Carmen     1    20
## 11  Lucia     1    20
## 12 Teresa     1    20
## 13 Carmen     2    20
## 14  Lucia     2    20
## 15 Teresa     2    20
## 16 Carmen     3    20
## 17  Lucia     3    20
## 18 Teresa     3    20
## 19 Carmen     1    40
## 20  Lucia     1    40
## 21 Teresa     1    40
## 22 Carmen     2    40
## 23  Lucia     2    40
## 24 Teresa     2    40
## 25 Carmen     3    40
## 26  Lucia     3    40
## 27 Teresa     3    40
## 28 Carmen     1    60
## 29  Lucia     1    60
## 30 Teresa     1    60
## 31 Carmen     2    60
## 32  Lucia     2    60
## 33 Teresa     2    60
## 34 Carmen     3    60
## 35  Lucia     3    60
## 36 Teresa     3    60
## 37 Carmen     1    80
## 38  Lucia     1    80
## 39 Teresa     1    80
## 40 Carmen     2    80
## 41  Lucia     2    80
## 42 Teresa     2    80
## 43 Carmen     3    80
## 44  Lucia     3    80
## 45 Teresa     3    80
## 46 Carmen     1   100
## 47  Lucia     1   100
## 48 Teresa     1   100
## 49 Carmen     2   100
## 50  Lucia     2   100
## 51 Teresa     2   100
## 52 Carmen     3   100
## 53  Lucia     3   100
## 54 Teresa     3   100
str(da)
## 'data.frame':    54 obs. of  3 variables:
##  $ vari : Factor w/ 3 levels "Carmen","Lucia",..: 1 2 3 1 2 3 1 2 3 1 ...
##  $ bloco: Factor w/ 3 levels "1","2","3": 1 1 1 2 2 2 3 3 3 1 ...
##  $ nitro: num  0 0 0 0 0 0 0 0 0 20 ...
##  - attr(*, "out.attrs")=List of 2
##   ..$ dim     : Named int  3 3 6
##   .. ..- attr(*, "names")= chr  "vari" "bloco" "nitro"
##   ..$ dimnames:List of 3
##   .. ..$ vari : chr  "vari=Carmen" "vari=Lucia" "vari=Teresa"
##   .. ..$ bloco: chr  "bloco=1" "bloco=2" "bloco=3"
##   .. ..$ nitro: chr  "nitro=  0" "nitro= 20" "nitro= 40" "nitro= 60" ...
da <- expand.grid(trat=c("tratado","controle"),
                  bloco=c("I","II","III"))
da
##       trat bloco
## 1  tratado     I
## 2 controle     I
## 3  tratado    II
## 4 controle    II
## 5  tratado   III
## 6 controle   III

Números aleatórios

##-----------------------------------------------------------------------------
## Números uniformes.

x <- runif(10); x
##  [1] 0.005343402 0.163498536 0.468872580 0.896007781 0.026639577 0.550113728 0.219849132
##  [8] 0.300428519 0.901197906 0.656097755
##-----------------------------------------------------------------------------
## Números da distribuição normal padrão.

x <- rnorm(10, mean=0, sd=1)

## curve(dnorm(x, 0, 1), -4, 4)
## rug(x)

##-----------------------------------------------------------------------------
## Amostra aleatória de população discreta finita com e sem reposição.

u <- c("Superman","Batman","Aquaman","Flash","Green Lantern")
sample(u, size=3)
## [1] "Batman"        "Green Lantern" "Aquaman"
u <- c("Iron Man","Thor","Captain America","Hulk","Black Widow","Hawkeye")
sample(u, size=10, replace=TRUE)
##  [1] "Black Widow"     "Iron Man"        "Hulk"            "Captain America"
##  [5] "Black Widow"     "Hulk"            "Captain America" "Iron Man"       
##  [9] "Black Widow"     "Hawkeye"

Ordenar, inverter e aleatorizar

##-----------------------------------------------------------------------------
## Um vetor com número uniformes.

x <- runif(6)

## As posições do menor para o maior valor.
order(x)
## [1] 1 4 5 6 3 2
## O vetor ordenado do menor para o maior.
sort(x, decreasing=FALSE)
## [1] 0.4622079 0.4827947 0.7711735 0.9045427 0.9196033 0.9350125
x[order(x)]
## [1] 0.4622079 0.4827947 0.7711735 0.9045427 0.9196033 0.9350125
## Os valores em ordem inversa.
rev(x)
## [1] 0.9045427 0.7711735 0.4827947 0.9196033 0.9350125 0.4622079
## Ordenando um vetor por valores em outro.
u <- c("Iron Man","Thor","Captain America","Hulk","Black Widow","Hawkeye")
u[order(x)]
## [1] "Iron Man"        "Hulk"            "Black Widow"     "Hawkeye"        
## [5] "Captain America" "Thor"
## O vetor com os elementos aleatorizados.
sample(u)
## [1] "Black Widow"     "Hawkeye"         "Thor"            "Captain America"
## [5] "Iron Man"        "Hulk"

Estatísticas simples

##-----------------------------------------------------------------------------
## Um vetor com dados de precipitação.

precip
##              Mobile              Juneau             Phoenix         Little Rock 
##                67.0                54.7                 7.0                48.5 
##         Los Angeles          Sacramento       San Francisco              Denver 
##                14.0                17.2                20.7                13.0 
##            Hartford          Wilmington          Washington        Jacksonville 
##                43.4                40.2                38.9                54.5 
##               Miami             Atlanta            Honolulu               Boise 
##                59.8                48.3                22.9                11.5 
##             Chicago              Peoria        Indianapolis          Des Moines 
##                34.4                35.1                38.7                30.8 
##             Wichita          Louisville         New Orleans            Portland 
##                30.6                43.1                56.8                40.8 
##           Baltimore              Boston             Detroit    Sault Ste. Marie 
##                41.8                42.5                31.0                31.7 
##              Duluth Minneapolis/St Paul             Jackson         Kansas City 
##                30.2                25.9                49.2                37.0 
##            St Louis         Great Falls               Omaha                Reno 
##                35.9                15.0                30.2                 7.2 
##             Concord       Atlantic City         Albuquerque              Albany 
##                36.2                45.5                 7.8                33.4 
##             Buffalo            New York           Charlotte             Raleigh 
##                36.1                40.2                42.7                42.5 
##             Bismark           Cincinati           Cleveland            Columbus 
##                16.2                39.0                35.0                37.0 
##       Oklahoma City            Portland        Philadelphia           Pittsburg 
##                31.4                37.6                39.9                36.2 
##          Providence            Columbia         Sioux Falls             Memphis 
##                42.8                46.4                24.7                49.1 
##           Nashville              Dallas             El Paso             Houston 
##                46.0                35.9                 7.8                48.2 
##      Salt Lake City          Burlington             Norfolk            Richmond 
##                15.2                32.5                44.7                42.6 
##      Seattle Tacoma             Spokane          Charleston           Milwaukee 
##                38.8                17.4                40.8                29.1 
##            Cheyenne            San Juan 
##                14.6                59.2
x <- precip

sum(x)
## [1] 2442
mean(x)
## [1] 34.88571
median(x)
## [1] 36.6
min(x)
## [1] 7
max(x)
## [1] 67
range(x)
## [1]  7 67
fivenum(x)
##    Phoenix  Milwaukee  Pittsburg Providence     Mobile 
##        7.0       29.1       36.6       42.8       67.0
IQR(x)
## [1] 13.4
quantile(x, probs=c(0.05, 0.95))
##     5%    95% 
##  9.465 55.855
var(x)
## [1] 187.8723
sd(x)
## [1] 13.70665
mad(x)
## [1] 9.56277
diff(range(x))
## [1] 60
100*sd(x)/mean(x)
## [1] 39.29015
require(fBasics)
## Loading required package: fBasics
## Loading required package: timeDate
## Loading required package: methods
## Loading required package: timeSeries
## 
## 
## Rmetrics Package fBasics
## Analysing Markets and calculating Basic Statistics
## Copyright (C) 2005-2014 Rmetrics Association Zurich
## Educational Software for Financial Engineering and Computational Science
## Rmetrics is free software and comes with ABSOLUTELY NO WARRANTY.
## https://www.rmetrics.org --- Mail to: info@rmetrics.org
skewness(x)
## [1] -0.2852747
## attr(,"method")
## [1] "moment"
kurtosis(x)
## [1] -0.38499
## attr(,"method")
## [1] "excess"
require(EnvStats)
## Loading required package: EnvStats
## 
## Attaching package: 'EnvStats'
## 
## The following objects are masked from 'package:timeDate':
## 
##     kurtosis, skewness
## 
## The following object is masked from 'package:stats':
## 
##     predict.lm
## Algumas funções são substituídas.

skewness(x)
## [1] -0.2979212
kurtosis(x)
## [1] -0.2410105
cv(x)
## [1] 0.3929015
summaryStats(x)
##    N    Mean      SD Median Min Max
## x 70 34.8857 13.7067   36.6   7  67
sx <- summaryFull(x)
sx
##                              x      
## N                            70     
## Mean                         34.89  
## Median                       36.6   
## 10% Trimmed Mean             35.22  
## Geometric Mean               31.26  
## Skew                         -0.2979
## Kurtosis                     -0.241 
## Min                           7     
## Max                          67     
## Range                        60     
## 1st Quartile                 29.38  
## 3rd Quartile                 42.77  
## Standard Deviation           13.71  
## Geometric Standard Deviation  1.696 
## Interquartile Range          13.39  
## Median Absolute Deviation     9.563 
## Coefficient of Variation      0.3929
str(sx)
##  summaryStats [1:17, 1] 70 34.9 36.6 35.2 31.3 ...
##  - attr(*, "dimnames")=List of 2
##   ..$ : chr [1:17] "N" "Mean" "Median" "10% Trimmed Mean" ...
##   ..$ : chr "x"
##  - attr(*, "stats.in.rows")= logi TRUE
##  - attr(*, "drop0trailing")= logi TRUE
sx["10% Trimmed Mean",]
## [1] 35.22

Família apply

A família *apply e agregados representa um conjunto de funções destinadas à tarefas por estrato e/ou margem (índice). Tarefas assim foram recentemente batizadas de SAC (split-apply-combine). São essas funções do pacote básico do R que permiter obter médias por tratamento, coeficientes de variação por resposta (por coluna). Isoladamente cada uma delas têm seu papel e juntas resolvem uma série de problemas.

##-----------------------------------------------------------------------------
## Os membros da família *apply.

## De uso simples e frequente.
##  apply  : on Arrays margins (não é aaply para evitar cacofonia).
##  lapply : on Lists itens or vector elements or data.frame columns.
##  sapply : lapply that Simplifies when possible.
##  tapply : on a ragged array, return as Tabular format.

## De uso menos frequente.
##  mapply : lapply over Multiple list or vector arguments.
##  eapply : on Environments.
##  rapply : Recursive.
##  vapply : Vectorized.
##  dendrapply : related to dendrogramns.
##  kernapply : related kernel.

## Além destas, tem-se outras funções que são os agregados da família.
##  by(): divide de acordo com estrato e aplica algo.
##  aggragate(): divide por estrato e aplica por coluna.
##  sweep(): operações entre matrizes e vetores.

##-----------------------------------------------------------------------------
## tapply.

str(npk)
## 'data.frame':    24 obs. of  5 variables:
##  $ block: Factor w/ 6 levels "1","2","3","4",..: 1 1 1 1 2 2 2 2 3 3 ...
##  $ N    : Factor w/ 2 levels "0","1": 1 2 1 2 2 2 1 1 1 2 ...
##  $ P    : Factor w/ 2 levels "0","1": 2 2 1 1 1 2 1 2 2 2 ...
##  $ K    : Factor w/ 2 levels "0","1": 2 1 1 2 1 2 2 1 1 2 ...
##  $ yield: num  49.5 62.8 46.8 57 59.8 58.5 55.5 56 62.8 55.8 ...
## Média de yield para cada nível de N.
r <- tapply(npk$yield, npk$N, mean, na.rm=TRUE)
r
##        0        1 
## 52.06667 57.68333
class(r)
## [1] "array"
## Média de yield para combinando os níveis de N e P.
r <- tapply(npk$yield, list(npk$N, npk$P), mean)
r
##          0        1
## 0 51.71667 52.41667
## 1 59.21667 56.15000
## Melhor usa com with() para simplificar a declaração.
r <- with(npk, tapply(yield, list(N, P), mean))
r
##          0        1
## 0 51.71667 52.41667
## 1 59.21667 56.15000
## O mesmo considerando N, P e K.
r <- with(npk, tapply(yield, list(N, P, K), mean))
r
## , , 0
## 
##          0        1
## 0 51.43333 54.33333
## 1 63.76667 57.93333
## 
## , , 1
## 
##          0        1
## 0 52.00000 50.50000
## 1 54.66667 54.36667
## Nomes na lista geram nomes para as dimensões do array.
r <- with(npk, tapply(yield, list(Nitro=N, Phos=P, Pot=K), mean))
r
## , , Pot = 0
## 
##      Phos
## Nitro        0        1
##     0 51.43333 54.33333
##     1 63.76667 57.93333
## 
## , , Pot = 1
## 
##      Phos
## Nitro        0        1
##     0 52.00000 50.50000
##     1 54.66667 54.36667
##-----------------------------------------------------------------------------
## aggregate.

## A aggragate funciona com uso de formula, além de poder ser usada como a
## tapply(). O resultado é em data.frame.

s <- with(npk,
          aggregate(cbind(Y=yield), list(Nitro=N, Phos=P, Pot=K), mean))
s
##   Nitro Phos Pot        Y
## 1     0    0   0 51.43333
## 2     1    0   0 63.76667
## 3     0    1   0 54.33333
## 4     1    1   0 57.93333
## 5     0    0   1 52.00000
## 6     1    0   1 54.66667
## 7     0    1   1 50.50000
## 8     1    1   1 54.36667
## Será obtido o mesmo, mas usando uma fórmula para representar o que se
## deseja.

s <- aggregate(yield~N+P+K, data=npk, mean)
s
##   N P K    yield
## 1 0 0 0 51.43333
## 2 1 0 0 63.76667
## 3 0 1 0 54.33333
## 4 1 1 0 57.93333
## 5 0 0 1 52.00000
## 6 1 0 1 54.66667
## 7 0 1 1 50.50000
## 8 1 1 1 54.36667
## Diferente da tapply, a aggregate pode ter mais de uma variáveis
## resposta. Por falta de outra variável resposta, será usando o log de
## yield.

s <- aggregate(cbind(y=yield, log.y=log(yield))~N+P+K, data=npk, mean)
s
##   N P K        y    log.y
## 1 0 0 0 51.43333 3.937606
## 2 1 0 0 63.76667 4.153156
## 3 0 1 0 54.33333 3.984677
## 4 1 1 0 57.93333 4.056245
## 5 0 0 1 52.00000 3.947143
## 6 1 0 1 54.66667 3.999207
## 7 0 1 1 50.50000 3.921254
## 8 1 1 1 54.36667 3.992844
##-----------------------------------------------------------------------------
## by.

by(data=npk, INDICES=with(npk, N), FUN=nrow)
## with(npk, N): 0
## [1] 12
## ------------------------------------------------------------------- 
## with(npk, N): 1
## [1] 12
r <- with(npk, by(yield, INDICES=N, FUN=mean)); r
## N: 0
## [1] 52.06667
## ------------------------------------------------------------------- 
## N: 1
## [1] 57.68333
str(r)
##  by [1:2(1d)] 52.1 57.7
##  - attr(*, "dimnames")=List of 1
##   ..$ N: chr [1:2] "0" "1"
##  - attr(*, "call")= language by.default(data = yield, INDICES = N, FUN = mean)
c(is.list(r), is.array(r))
## [1] FALSE  TRUE
r <- with(npk, by(yield, INDICES=list(N=N, P=P, K=K), FUN=mean)); r
## N: 0
## P: 0
## K: 0
## [1] 51.43333
## ------------------------------------------------------------------- 
## N: 1
## P: 0
## K: 0
## [1] 63.76667
## ------------------------------------------------------------------- 
## N: 0
## P: 1
## K: 0
## [1] 54.33333
## ------------------------------------------------------------------- 
## N: 1
## P: 1
## K: 0
## [1] 57.93333
## ------------------------------------------------------------------- 
## N: 0
## P: 0
## K: 1
## [1] 52
## ------------------------------------------------------------------- 
## N: 1
## P: 0
## K: 1
## [1] 54.66667
## ------------------------------------------------------------------- 
## N: 0
## P: 1
## K: 1
## [1] 50.5
## ------------------------------------------------------------------- 
## N: 1
## P: 1
## K: 1
## [1] 54.36667
str(r)
##  by [1:2, 1:2, 1:2] 51.4 63.8 54.3 57.9 52 ...
##  - attr(*, "dimnames")=List of 3
##   ..$ N: chr [1:2] "0" "1"
##   ..$ P: chr [1:2] "0" "1"
##   ..$ K: chr [1:2] "0" "1"
##  - attr(*, "call")= language by.default(data = yield, INDICES = list(N = N, P = P, K = K), FUN = mean)
c(is.list(r), is.array(r))
## [1] FALSE  TRUE
class(r)   ## Como é de classe by ele é mostrado de forma diferente.
## [1] "by"
unclass(r) ## Se a classe é removida, então é mostrado como array comum.
## , , K = 0
## 
##    P
## N          0        1
##   0 51.43333 54.33333
##   1 63.76667 57.93333
## 
## , , K = 1
## 
##    P
## N          0        1
##   0 52.00000 50.50000
##   1 54.66667 54.36667
## 
## attr(,"call")
## by.default(data = yield, INDICES = list(N = N, P = P, K = K), 
##     FUN = mean)

Em resumo, as funções tapply, aggregate e by fazem tarefas por estrato. Em outras palavras, separam os valores em um (ou mais) vetores respeitando valores em outro (ou mais) e em seguida aplicam uma função. A diferença é como declarar e o que é retornado.

##-----------------------------------------------------------------------------
## apply.

Titanic
## , , Age = Child, Survived = No
## 
##       Sex
## Class  Male Female
##   1st     0      0
##   2nd     0      0
##   3rd    35     17
##   Crew    0      0
## 
## , , Age = Adult, Survived = No
## 
##       Sex
## Class  Male Female
##   1st   118      4
##   2nd   154     13
##   3rd   387     89
##   Crew  670      3
## 
## , , Age = Child, Survived = Yes
## 
##       Sex
## Class  Male Female
##   1st     5      1
##   2nd    11     13
##   3rd    13     14
##   Crew    0      0
## 
## , , Age = Adult, Survived = Yes
## 
##       Sex
## Class  Male Female
##   1st    57    140
##   2nd    14     80
##   3rd    75     76
##   Crew  192     20
str(Titanic)
##  table [1:4, 1:2, 1:2, 1:2] 0 0 35 0 0 0 17 0 118 154 ...
##  - attr(*, "dimnames")=List of 4
##   ..$ Class   : chr [1:4] "1st" "2nd" "3rd" "Crew"
##   ..$ Sex     : chr [1:2] "Male" "Female"
##   ..$ Age     : chr [1:2] "Child" "Adult"
##   ..$ Survived: chr [1:2] "No" "Yes"
is.array(Titanic)
## [1] TRUE
dimnames(Titanic)
## $Class
## [1] "1st"  "2nd"  "3rd"  "Crew"
## 
## $Sex
## [1] "Male"   "Female"
## 
## $Age
## [1] "Child" "Adult"
## 
## $Survived
## [1] "No"  "Yes"
sum(Titanic[ ,1, , ]) ## Total de homens.
## [1] 1731
sum(Titanic[ ,2, , ]) ## Total de mulheres.
## [1] 470
apply(Titanic, MARGIN=2, sum) ## Totais das margens para Sex.
##   Male Female 
##   1731    470
apply(Titanic, MARGIN=1, sum) ## Para Class.
##  1st  2nd  3rd Crew 
##  325  285  706  885
apply(Titanic, MARGIN=c(1,2), sum) ## Class e Sex.
##       Sex
## Class  Male Female
##   1st   180    145
##   2nd   179    106
##   3rd   510    196
##   Crew  862     23
apply(Titanic, MARGIN=c(2,4), sum) ## Sex e Survived.
##         Survived
## Sex        No Yes
##   Male   1364 367
##   Female  126 344
apply(Titanic, MARGIN=c(3,4), sum) ## Age e Survived.
##        Survived
## Age       No Yes
##   Child   52  57
##   Adult 1438 654
str(HairEyeColor)
##  table [1:4, 1:4, 1:2] 32 53 10 3 11 50 10 30 10 25 ...
##  - attr(*, "dimnames")=List of 3
##   ..$ Hair: chr [1:4] "Black" "Brown" "Red" "Blond"
##   ..$ Eye : chr [1:4] "Brown" "Blue" "Hazel" "Green"
##   ..$ Sex : chr [1:2] "Male" "Female"
dimnames(HairEyeColor)
## $Hair
## [1] "Black" "Brown" "Red"   "Blond"
## 
## $Eye
## [1] "Brown" "Blue"  "Hazel" "Green"
## 
## $Sex
## [1] "Male"   "Female"
apply(HairEyeColor, MARGIN=1, sum) ## Por cor de cabelo.
## Black Brown   Red Blond 
##   108   286    71   127
apply(HairEyeColor, MARGIN=2, sum) ## Por cor de olhos.
## Brown  Blue Hazel Green 
##   220   215    93    64
apply(HairEyeColor, MARGIN=3, sum) ## Por cor de sexo.
##   Male Female 
##    279    313
apply(HairEyeColor, MARGIN=c(1,2), sum) ## Por cor de cabelo.
##        Eye
## Hair    Brown Blue Hazel Green
##   Black    68   20    15     5
##   Brown   119   84    54    29
##   Red      26   17    14    14
##   Blond     7   94    10    16
##-----------------------------------------------------------------------------
## lapply e sapply.

is.list(rock)
## [1] TRUE
str(rock) ## Todas as colunas tem conteúdo numérico.
## 'data.frame':    48 obs. of  4 variables:
##  $ area : int  4990 7002 7558 7352 7943 7979 9333 8209 8393 6425 ...
##  $ peri : num  2792 3893 3931 3869 3949 ...
##  $ shape: num  0.0903 0.1486 0.1833 0.1171 0.1224 ...
##  $ perm : num  6.3 6.3 6.3 6.3 17.1 17.1 17.1 17.1 119 119 ...
lapply(rock, mean)  ## Média
## $area
## [1] 7187.729
## 
## $peri
## [1] 2682.212
## 
## $shape
## [1] 0.2181104
## 
## $perm
## [1] 415.45
lapply(rock, range) ## Extremos.
## $area
## [1]  1016 12212
## 
## $peri
## [1]  308.642 4864.220
## 
## $shape
## [1] 0.0903296 0.4641250
## 
## $perm
## [1]    6.3 1300.0
## Porque trata-se de um data.frame, dá pra usar apply também.
apply(rock, MARGIN=2, mean)
##         area         peri        shape         perm 
## 7187.7291667 2682.2119375    0.2181104  415.4500000
apply(rock, MARGIN=2, range)
##       area     peri     shape   perm
## [1,]  1016  308.642 0.0903296    6.3
## [2,] 12212 4864.220 0.4641250 1300.0
sapply(rock, mean)  ## Foi possível simplificar para um vetor.
##         area         peri        shape         perm 
## 7187.7291667 2682.2119375    0.2181104  415.4500000
sapply(rock, range) ## Foi possível simplificar para uma matriz.
##       area     peri     shape   perm
## [1,]  1016  308.642 0.0903296    6.3
## [2,] 12212 4864.220 0.4641250 1300.0
str(iris)
## 'data.frame':    150 obs. of  5 variables:
##  $ Sepal.Length: num  5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...
##  $ Sepal.Width : num  3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ...
##  $ Petal.Length: num  1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ...
##  $ Petal.Width : num  0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ...
##  $ Species     : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ...
sapply(iris, mean)
## Warning in mean.default(X[[5L]], ...): argument is not numeric or logical: returning NA
## Sepal.Length  Sepal.Width Petal.Length  Petal.Width      Species 
##     5.843333     3.057333     3.758000     1.199333           NA
sapply(iris, summary)
## $Sepal.Length
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   4.300   5.100   5.800   5.843   6.400   7.900 
## 
## $Sepal.Width
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   2.000   2.800   3.000   3.057   3.300   4.400 
## 
## $Petal.Length
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   1.000   1.600   4.350   3.758   5.100   6.900 
## 
## $Petal.Width
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   0.100   0.300   1.300   1.199   1.800   2.500 
## 
## $Species
##     setosa versicolor  virginica 
##         50         50         50
lapply(iris, is.numeric) ## Quais colunas tem conteúdo numérico?
## $Sepal.Length
## [1] TRUE
## 
## $Sepal.Width
## [1] TRUE
## 
## $Petal.Length
## [1] TRUE
## 
## $Petal.Width
## [1] TRUE
## 
## $Species
## [1] FALSE
lapply(iris, class)      ## Qual a classe?
## $Sepal.Length
## [1] "numeric"
## 
## $Sepal.Width
## [1] "numeric"
## 
## $Petal.Length
## [1] "numeric"
## 
## $Petal.Width
## [1] "numeric"
## 
## $Species
## [1] "factor"
## Também se pode usar apply pois iris é um data.frame.
apply(iris, MARGIN=2, is.numeric)
## Sepal.Length  Sepal.Width Petal.Length  Petal.Width      Species 
##        FALSE        FALSE        FALSE        FALSE        FALSE
sapply(iris, class) ## Foi possível simplificar.
## Sepal.Length  Sepal.Width Petal.Length  Petal.Width      Species 
##    "numeric"    "numeric"    "numeric"    "numeric"     "factor"
## Não foi possível simplificar.
sapply(iris, summary)
## $Sepal.Length
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   4.300   5.100   5.800   5.843   6.400   7.900 
## 
## $Sepal.Width
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   2.000   2.800   3.000   3.057   3.300   4.400 
## 
## $Petal.Length
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   1.000   1.600   4.350   3.758   5.100   6.900 
## 
## $Petal.Width
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   0.100   0.300   1.300   1.199   1.800   2.500 
## 
## $Species
##     setosa versicolor  virginica 
##         50         50         50
## Separar as colunas que são númericas e então pedir o summary.
i <- sapply(iris, is.numeric); i
## Sepal.Length  Sepal.Width Petal.Length  Petal.Width      Species 
##         TRUE         TRUE         TRUE         TRUE        FALSE
sapply(iris[,i], summary) ## Simplificou.
##         Sepal.Length Sepal.Width Petal.Length Petal.Width
## Min.           4.300       2.000        1.000       0.100
## 1st Qu.        5.100       2.800        1.600       0.300
## Median         5.800       3.000        4.350       1.300
## Mean           5.843       3.057        3.758       1.199
## 3rd Qu.        6.400       3.300        5.100       1.800
## Max.           7.900       4.400        6.900       2.500

Em resumo, as funções apply, lapply e sapply aplicam funções sobre índices, ou seja, em arranjos as operações são varrendo linhas, colunas, etc e em listas são varrendo os ítens. A diferença de lapply e sapply é que a última tenta simplificar o resultado acomodanto em um tipo de objeto mais simples que uma lista quando possível.

Funções

##-----------------------------------------------------------------------------
## Função para calcular a hipotenusa de um triângulo retângulo.

hipo <- function(a, b){ ## Argumentos.
    h <- sqrt(a^2+b^2)  ## Processo/procedimento.
    return(h)           ## Retorno.
}

## Explorando o objeto.
class(hipo)
mode(hipo)
args(hipo)
body(hipo)
str(hipo)

## Usando a função.
hipo(3, 4)
hipo(3, 4.6)
hipo(3, 3)

## Note que ela opera vetorialmente.
hipo(a=3, b=c(4, 4.6, 3))

##-----------------------------------------------------------------------------
## Abrindo algumas funções.

body(plot)                       ## Indica que é uma função genérica.
methods(generic.function="plot") ## As várias 'faces' da plot.
methods(generic.function="summary") ## As várias 'faces' da plot.

## Abrindo a função.
plot.default

plot.ecdf
## plot.ts

## As com asteriscos podem ser abertas assim.
getAnywhere(plot.histogram)
## getS3method(f="plot", class="histogram")

## Abrindo a função sequência.
methods(generic.function="seq")
getAnywhere(seq.default)

## Abrindo a matrix.
matrix

runif ## Chama uma função escrita em C.

##-----------------------------------------------------------------------------
## Incluindo o argumento ângulo.

hipo2 <- function(a, b, angle){
    h2 <- a^2+b^2-2*cos(angle)
    return(sqrt(h2))
}

hipo2(3, 4, angle=pi/2)
hipo(3, 4)

hipo2(3, 4, angle=pi/2+0.3)
hipo2(3, 4, angle=pi/2-0.3)

##-----------------------------------------------------------------------------
## Ângulo com valor default de 90 graus (pi/2 radianos).

hipo3 <- function(a, b, angle=pi/2){
    h2 <- a^2+b^2-2*cos(angle)
    return(sqrt(h2))
}

hipo3(3, 4)
hipo3(3, 4, angle=pi/2+0.5)

##-----------------------------------------------------------------------------
## Três implementações.

baskara1 <- function(a, b, c){
    x1 <- (-b-sqrt(b^2-4*a*c))/(2*a)
    x2 <- (-b+sqrt(b^2-4*a*c))/(2*a)
    return(c(x1, x2))
}

baskara2 <- function(a, b, c){
    s <- sqrt(b^2-4*a*c)
    d <- 2*a
    x1 <- (-b-s)/d
    x2 <- (-b+s)/d
    return(c(x1, x2))
}

baskara3 <- function(a, b, c){
    x <- (-b+c(-1,1)*sqrt(b^2-4*a*c))/(2*a)
    return(x)
}

a <- 2; b <- 1; c <- -3
curve(a*x^2+b*x+c, -3, 3)
abline(h=0, lty=2)

baskara1(a, b, c)
baskara2(a, b, c)
baskara3(a, b, c)

##-----------------------------------------------------------------------------
## Tempo para 50 mil excussões de cada uma.

system.time(replicate(50000, baskara1(a, b, c)))
system.time(replicate(50000, baskara2(a, b, c)))
system.time(replicate(50000, baskara3(a, b, c)))

## As implementação diferentes implicam em custos diferentes.

##-----------------------------------------------------------------------------
## Parábola sem raízes.

a <- 2; b <- 1; c <- 3
curve(a*x^2+b*x+c, -5, 5)
abline(h=0, lty=2)
baskara1(a, b, c)

##-----------------------------------------------------------------------------
## a==0, então não tem curvatura.

a <- 0; b <- 1; c <- 3
curve(a*x^2+b*x+c, -5, 5)
baskara1(a, b, c)

## Como notificar da origem desses erros?

##-----------------------------------------------------------------------------
## Colocando mensagens de erro para testes feitos nos argumentos.

baskara4 <- function(a, b, c){
    if (a==0){
        stop("O argumento `a` tem que ser diferente de zero.")
    }
    delta <- b^2-4*a*c
    if (delta<=0) {
        stop("Função sem raíz pois `delta` é não positivo.")
    }
    x <- (-b+c(-1,1)*sqrt(delta))/(2*a)
    return(x)
}

baskara4(2, 1, -3)
baskara4(0, 1, -3)
baskara4(2, 1, 3)

##-----------------------------------------------------------------------------
## Função que calcula as raízes da equação e ainda os valores no ponto
## crítico (x, y). O ponto crítico sempre existe se a!=0. As raízes
## podem não existir.

baskara5 <- function(a, b, c){
    if (a==0){
        stop("O argumento `a` tem que ser diferente de zero.")
    }
    d <- 2*a
    delta <- b^2-4*a*c
    if (delta<=0){
        warning("Função sem raíz pois `delta` é não positivo.")
        r <- c(NA, NA)
    } else {
        r <- (-b+c(-1,1)*sqrt(delta))/d
    }
    x <- -b/d
    y <- a*x^2+b*x+c
    L <- list(x=x, y=y, r=r)
    class(L) <- "baskara"
    return(L)
}

a <- baskara5(2, 1, -3)
str(a)

curve(2*x^2+1*x-3, -2, 2)
abline(v=a$x, h=a$y, col=2, lty=2)
abline(v=a$r, h=0, col=3, lty=2)

plot.baskara <- function(a){
    abline(v=a$x, h=a$y, col=2, lty=2)
    abline(v=a$r, h=0, col=3, lty=2)
}

curve(2*x^2+1*x-3, -2, 2)
plot(a)

##-----------------------------------------------------------------------------
## Argumentos como vetores, usa posição.

baskara6 <- function(abc){
    if (length(abc)==3L){
        x <- (-abc[2]+c(-1,1)*sqrt(abc[2]^2-4*abc[1]*abc[3]))/(2*abc[1])
        return(x)
    } else {
        stop("O vetor `abc` deve ter comprimento 3.")
    }
}

baskara6(c(2,1,-3))
baskara6(c(2,1,-3,500))
baskara6(c(2,1))

##-----------------------------------------------------------------------------
## Argumentos como vetores nomeados.

baskara7 <- function(abc){
    if (length(abc)==3L & all(names(abc)%in%c("a","b","c"))){
        x <- (-abc["b"]+c(-1,1)*
              sqrt(abc["b"]^2-4*abc["a"]*abc["c"]))/(2*abc["a"])
        return(x)
    } else {
        stop("O vetor `abc` deve ter comprimento 3 e ser nomeado.")
    }
}

baskara7(c(a=2, b=1, c=-3))
baskara7(c(b=1, a=2, c=-3))
baskara7(c(b=1, a=2, m=-3))

##-----------------------------------------------------------------------------
## Argumentos como vetores ou lista nomeados.

baskara8 <- function(abc){
    if (is.vector(abc)) abc <- as.list(abc)
    if (is.list(abc) & length(abc)==3L & all(names(abc)%in%c("a","b","c"))){
        x <- with(abc,
                  (-b+c(-1,1)*sqrt(b^2-4*a*c))/(2*a))
        return(x)
    } else {
        stop("O objeto `abc` deve ser vetor/lista nomeado de 3 elementos.")
    }
}

baskara8(c(a=2, b=1, c=-3))
baskara8(list(a=2, b=1, c=-3))
baskara8(data.frame(a=2, b=1, c=-3))

print(sessionInfo(), locale=FALSE)
## R version 3.1.1 (2014-07-10)
## Platform: i686-pc-linux-gnu (32-bit)
## 
## attached base packages:
## [1] methods   stats     graphics  grDevices utils     datasets  base     
## 
## other attached packages:
## [1] EnvStats_1.0.3     fBasics_3011.87    timeSeries_3010.97 timeDate_3010.98  
## [5] rmarkdown_0.3.3    knitr_1.7         
## 
## loaded via a namespace (and not attached):
## [1] digest_0.6.4    evaluate_0.5.5  formatR_1.0     htmltools_0.2.6 stringr_0.6.2  
## [6] tools_3.1.1     yaml_2.1.13
Sys.time()
## [1] "2014-11-12 22:04:40 BRST"