Extracci o N de Informaci o N Tem A Tica de Im A Genes Usando - V.0.3
Extracci o N de Informaci o N Tem A Tica de Im A Genes Usando - V.0.3
usando R - V.0.3
Ivan Lizarazo
Abril de 2013
Resumen
Este documento muestra las posibilidades de realizar análisis de ima-
genes usando el software estadı́stico R. Se ilustra, paso a paso, el uso de
tres técnicas diferentes, distancia Mahalanobis, árboles de decisión y má-
quinas de soporte vectorial, para realizar una clasificación supervisada de
la cobertura del suelo. En su desarrollo, se utiliza una imagen de juguete
(144 pixeles) que consta de cuatro bandas espectrales. Se simula un mapa
raster con las clases de cobertura existentes en el terreno con el objeto de
obtener muestras de entrenamiento y de validación. La exactitud tematica
de los resultados se evalua usando la matriz de error. El lector puede usar
este tutorial como referencia para realizar sus propios análisis basados en
imágenes reales.
1. Introducción
Este tutorial se realizó utilizando la versión 2.15.3 del software R instalada
en una máquina con sistema operativo Linux (Ubuntu 12.04). Para el desarrollo
de los ejercicios prácticos se instalaron previamente las siguientes librerı́as:
rgdal
sp
raster
scatterplot3d
1
mda
vcd
Este tutorial no describe conceptos básicos de procesamiento de imágenes
ni explica los fundamentos teóricos de las diferentes técnicas de clasificación
utilizadas, es decir distancia Mahalanobis, árboles de decision ni máquinas de
soporte vectorial. El autor asume que el lector ha revisado previamente dichos
conceptos y técnicas y que, por tanto, entiende de manera general los supues-
tos y algoritmos asociados a cada técnica y está listo para realizar actividades
prácticas.
2. Imagen de trabajo
Este tutorial utiliza como datos básicos una imagen obtenida con un sensor
de juguete, con cuatro bandas espectrales. Cada una de las bandas comprende
12 filas y 12 columnas.
Las bandas inviduales se pueden descargar de los siguientes enlaces a su di-
rectorio de trabajo:
[Link]
sharing
[Link]
sharing
[Link]
sharing
[Link]
sharing
> library(raster)
> # lectura de banda 1
> b1 <- raster("[Link]")
> # descripcion del objeto b1
> b1
class : RasterLayer
dimensions : 12, 12, 144 (nrow, ncol, ncell)
resolution : 1, 1 (x, y)
extent : 0, 12, 0, 12 (xmin, xmax, ymin, ymax)
coord. ref. : +proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0
data source : /home/ivan/ud/pdi avanzado/R/[Link]
names : band1
values : 43, 79 (min, max)
2
> # lectura de las tres bandas adicionales
> b2 <- raster("[Link]")
> b3 <- raster("[Link]")
> b4 <- raster("[Link]")
> # creacion de una imagen que agrupa las cuatro bandas
> toy <- stack(b1,b2,b3,b4)
> # asignacion de nombres especificos a cada banda
> names(toy) <- c("band1","band2","band3","band4")
> toy
class : RasterStack
dimensions : 12, 12, 144, 4 (nrow, ncol, ncell, nlayers)
resolution : 1, 1 (x, y)
extent : 0, 12, 0, 12 (xmin, xmax, ymin, ymax)
coord. ref. : +proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0
names : band1, band2, band3, band4
min values : 43, 20, 10, 1
max values : 79, 44, 69, 25
band1 band2
12
10
75 40
8
70
65 35
6
60 30
55
4
50 25
45 20
2
0
band3 band4
12
10
25
60 20
8
50
15
40
6
30 10
4
20 5
10
2
0
0 2 4 6 8 10 12 0 2 4 6 8 10 12
3
Visualice los histogramas de cada banda de la imagen usando la siguiente
instruccion:
> hist(toy)
band1 band2
30
25
20
Frequency
Frequency
15
5 10
0 5
0
40 50 60 70 80 20 25 30 35 40
v v
band3 band4
35
30
25
Frequency
Frequency
20
15
10
0 5
0
10 20 30 40 50 60 70 0 5 10 15 20 25
v v
4
Las estadı́sticas de la imagen se pueden obtener usando las siguientes ins-
trucciones:
> # estadisticas unibanda
> resumen <- summary(toy)
> resumen
band1 band2 band3 band4
Min. 43 20.00 10 1
1st Qu. 51 28.00 15 3
Median 57 30.00 42 13
3rd Qu. 64 33.25 51 18
Max. 79 44.00 69 25
NA's 0 0.00 0 0
> # matriz de covarianza
> covar <- cov([Link](toy))
> covar
band1 band2 band3 band4
band1 69.830420 -4.409091 129.0871 51.37675
band2 -4.409091 19.447552 -34.4120 -12.78147
band3 129.087121 -34.412005 314.5361 128.63097
band4 51.376748 -12.781469 128.6310 56.46460
5
> # matriz de correlacion
> corr <- cor([Link](toy))
> corr
20 30 40 5 10 20
75
band1
65
0.12
0.87 0.82
55
45
●
band2
●
40
●
●
●
● ● ● ●
● ●●
● ●● ●
●●● ●
● ● ●●● ● ● ●
●● ● ●
● ●● ● ● ●● ●●● ●
0.44 0.39
30
● ●● ● ● ●
●● ●●● ● ●● ●●● ●●●● ●● ●●
● ●● ●●●●● ● ●
●●● ●●●●● ● ● ●
● ● ● ● ●●
● ●● ● ●
● ● ●●● ● ●
● ●
● ● ● ●
● ●
20
●
70
● ●
●● ● ● ●
band3
● ● ● ●
● ●
● ● ● ● ● ● ● ●
● ●●● ●● ● ●
● ●
● ●● ●● ●●● ●
● ● ● ●
●
● ● ●
● ● ● ● ●
50
● ●
● ● ● ● ● ● ● ● ● ●
●● ●● ●●● ●●●
● ●
● ● ●
● ●
● ● ●
● ● ●● ●
● ● ● ● ●
● ●●●● ●●●●●●● ● ● ● ● ● ● ●
● ●
●
● ● ● ●
0.97
●●
●●● ● ● ● ●
●●●● ● ● ● ●
● ● ●
● ● ● ●● ● ● ● ● ●
● ●
●● ● ●
● ● ● ●
●● ● ●
30
● ●
● ● ● ●
● ● ● ● ●
● ● ●
● ●
● ●●
●●●
●●●
●●●●●●● ● ● ●
● ●
● ● ● ●
● ● ● ● ● ● ● ●
● ●●●●
●
●●● ●● ● ● ●
● ● ● ●
10
● ● ● ● ●
● ●
● ● ● ● ●●
● ● ● ● ● ● ● ●
band4
● ●● ● ● ● ● ● ●● ●●● ●
●● ● ● ● ● ●● ●
20
● ●●● ● ● ● ● ● ● ●●●● ● ●
●● ● ● ● ● ● ● ● ●●● ● ●
●● ● ● ● ●● ●
●●●●●●● ● ●● ● ● ● ● ● ● ● ●● ●● ● ● ●
● ● ● ● ● ●
● ● ● ● ● ● ● ●● ● ●
● ● ●● ●●●● ● ● ● ● ● ● ● ● ● ● ●●● ●●●
● ● ●●● ● ● ● ● ● ● ● ● ● ● ●●● ●
●●● ●●●● ● ● ● ● ● ● ● ● ●●●●●●●
● ●● ● ● ● ● ● ●● ● ● ●
5 10
● ●● ● ● ● ●●
●● ● ●● ● ● ● ● ● ● ● ● ● ● ●●
● ● ●
● ● ●
●● ● ● ● ● ● ● ● ● ●●● ●
●● ● ●● ● ● ● ● ● ● ●●● ●
● ● ●●
● ● ●●
●●●●●●● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ●●●●●● ●
● ●● ● ● ● ● ● ● ●●
45 55 65 75 10 30 50 70
3. Datos de referencia
La zona cubierta por la imagen es una zona rural en la cual existen tres clases
de cobertura vegetal: pasto (1), bosque (2) y cultivo (3). En los dias pasados se
realizó una visita de campo en la cual se obtuvo, para cada pixel de la imagen, la
clase de cobertura existente. Luego, en la oficina, se elaboró un mapa raster con
las clases de cobertura existentes. Dicho mapa se puede descargar del siguiente
6
enlace:
[Link]
sharing
class : RasterLayer
dimensions : 12, 12, 144 (nrow, ncol, ncell)
resolution : 1, 1 (x, y)
extent : 0, 12, 0, 12 (xmin, xmax, ymin, ymax)
coord. ref. : +proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0
data source : /home/ivan/ud/pdi avanzado/R/[Link]
names : terreno
values : 1, 3 (min, max)
> plot(terreno)
7
12
10
3.0
8
2.5
2.0
6
1.5
4
1.0
2
0
0 2 4 6 8 10 12
4. Muestra de entrenamiento
La creación de la muestra de entrenamiento se puede realizar usando los
siguientes comandos:
> # definicion aleatoria de una muestra de 150 puntos
> [Link] <- 7435
> [Link] <- spsample(spterreno,150,"random")
> # seleccion aleatoria de 50 puntos para entrenamiento
> train <- sort(sample(1:150, floor(50)))
> [Link] <- [Link][train,]
> # obtencion de clases existentes en los sitios de muestreo
> temp1 <- overlay(spterreno,[Link])
> # creacion de la respuesta del modelo
> resp <- temp1$value
> # Obtencion de ND de la imagen en cada punto de muestreo
> trainvals <- extract(toy, [Link])
> #trainvals
> # Adicion de clases de cobertura a los puntos de entrenamiento
> [Link] = SpatialPointsDataFrame([Link], temp1)
> #[Link]
8
La visualización de los puntos de entrenamiento superpuestos sobre el raster
de terreno se puede realizar usando la siguiente expresión:
> plot(terreno)
> plot([Link], add=TRUE)
12
10
3.0
8
2.5
2.0
6
1.5
4
1.0
2
0
0 2 4 6 8 10 12
5. Análisis de separabilidad
Para realizar el análisis visual de separabilidad es conveniente crear un nuevo
raster que integre las cuatro bandas espectrales y la clase de cobertura existente
en el terreno. Las siguientes instrucciones permiten obtener ese raster:
class : RasterStack
dimensions : 12, 12, 144, 5 (nrow, ncol, ncell, nlayers)
resolution : 1, 1 (x, y)
extent : 0, 12, 0, 12 (xmin, xmax, ymin, ymax)
coord. ref. : +proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0
names : band1, band2, band3, band4, clase
9
min values : 43, 20, 10, 1, 1
max values : 79, 44, 69, 25, 3
●
●
40
●
●
● ●
● ●●
● ●●
35
●●● ●
● ● ●●● ●
band2
●●
● ●● ●
● ●●
30
●● ●●●
●
25
●
20
45 50 55 60 65 70 75 80
band1
10
70
60
50
ntoy$band3
40
ntoy$band2
●
●
●
●● ●
● ● 45
●●●● ●
30
● ● ●
●
● ●● ●●●
●● 40
●
●● ●● ●
●●● ●●
●●●●
●● ● ● 35
20
● 30
●
25
10
20
40 50 60 70 80
ntoy$band1
11
79 44 69 25
43 20 10 1
6. Muestra de validación
La creacion de la muestra de validación se puede realizar usando la siguiente
expresión:
> # definicion aleatoria de 100 puntos de validacion
> # seleccionados tomando, en la muestra de 150 puntos, previamente obtenida,
> # aquellos puntos que no corresponden a sitios de entrenamiento
> [Link] <- [Link][-train,]
> # obtencion de clases existentes en los sitios de validacion
> temp <- overlay(spterreno,[Link])
> # creacion de la respuesta del modelo
> response <- temp$value
> # Obtencion de ND de la imagen en cada punto de muestreo
> testvals <- extract(toy, [Link])
> #testvals
> # Adicion de clases de cobertura a los puntos de entrenamiento
> [Link] = SpatialPointsDataFrame([Link], temp)
> #[Link]
La visualización de los puntos de entrenamiento superpuestos sobre el raster
de terreno se puede realizar usando la siguiente expresión:
12
> plot(terreno)
> plot([Link], add=TRUE)
12
10
3.0
8
2.5
2.0
6
1.5
4
1.0
2
0
0 2 4 6 8 10 12
13
> # conversion de tipos de objetos
> train <- cbind(trainvals, resp)
> [Link] <- [Link](train)
> # Clase 1: Pasto
> # recuperacion de las 4 bandas para todos los pixeles de esta clase
> pasto <- [Link][[Link]$resp==1,1:4]
> # valor medio de clase 1
> mean1 <- colMeans( pasto )
> mean1
band1 band2 band3 band4
50.15 34.30 14.75 2.55
> # matriz de covarianza de clase 1
> var1<-var( pasto )
> var1
band1 band2 band3 band4
band1 10.976316 10.6368421 1.2500000 1.0184211
band2 10.636842 16.0105263 1.3421053 0.7736842
band3 1.250000 1.3421053 1.5657895 0.4078947
band4 1.018421 0.7736842 0.4078947 0.8921053
> #
> # Clase 2: Bosque
> bosque <- [Link][[Link]$resp==2,1:4]
> # valor medio de clase 2
> mean2 <- colMeans( bosque )
> mean2
band1 band2 band3 band4
66.1 30.2 57.5 19.7
> # matriz de covarianza clase 2
> var2<-var( bosque )
> var2
band1 band2 band3 band4
band1 85.211111 32.866667 60.83333 9.366667
band2 32.866667 22.844444 25.55556 7.177778
band3 60.833333 25.555556 48.72222 10.611111
band4 9.366667 7.177778 10.61111 5.788889
> #
> # Clase 3: Cultivo
> cultivo <- [Link][[Link]$resp==3,1:4]
> # valor medio de clase 3
> mean3 <- colMeans( cultivo )
> mean3
14
band1 band2 band3 band4
58.30 28.35 42.20 13.55
15
52 682.2080775 31.479371 4.289352 3
53 875.0944757 25.592307 4.457043 3
54 513.1488745 20.302291 12.023673 3
55 752.4189947 28.032215 5.989533 3
120 953.4314878 4.926042 64.411595 2
121 1388.4029702 16.096046 49.489052 2
122 956.3467447 4.557744 34.741806 2
123 2019.2991388 7.617391 128.563540 2
124 920.6859931 14.833726 25.934763 2
125 1330.3871180 2.587669 23.313295 2
3.0
8
2.5
2.0
6
1.5
4
1.0
2
0
0 2 4 6 8 10 12
16
Clases obtenidas mediante DM
12
10
3.0
8
2.5
2.0
6
1.5
4
1.0
2
0
0 2 4 6 8 10 12
true
predicted 1 2 3
1 46 0 0
2 0 25 0
3 0 5 24
attr(,"error")
[1] 0.05
17
[1] 95
[1] 0.9223361
18
band3< 25
|
band4>=16
1
2 3
Call:
rpart(formula = resp ~ ., data = [Link], method = "class",
control = [Link](cp = 0.005))
n= 50
Variable importance
band4 band3 band1 band2
34 33 19 14
19
class counts: 20 10 20
probabilities: 0.400 0.200 0.400
left son=2 (20 obs) right son=3 (30 obs)
Primary splits:
band3 < 25 to the left, improve=18.666670, (0 missing)
band4 < 7.5 to the left, improve=18.666670, (0 missing)
band1 < 55.5 to the left, improve= 9.760000, (0 missing)
band2 < 32.5 to the right, improve= 7.772059, (0 missing)
Surrogate splits:
band4 < 7.5 to the left, agree=1.00, adj=1.00, (0 split)
band1 < 53.5 to the left, agree=0.86, adj=0.65, (0 split)
band2 < 32.5 to the right, agree=0.80, adj=0.50, (0 split)
20
+ compress=TRUE,
+ margin = .2)
> text(rp2,
+ use.n=TRUE,
+ all = TRUE,
+ fancy = TRUE)
1
|
20/10/20
band3< 25
band3>=25
1 3
20/0/0 0/10/20
band4>=16
band4< 16
2 3
0/10/1 0/0/19
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
1 1 1 1 1 1 1 1 1 1 3 3 3 3 3 3 2 3 3 3
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
3 3 3 3 3 3 3 3 3 3 2 3 3 3 3 3 3 2 3 3
21
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
3 3 3 2 3 2 3 3 3 3 3 3 3 3 3 3 3 3 3 3
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
2 2 2 2 2 2 2 2 2 2 2 2 2 3 3 2 2 2 2 2
141 142 143 144
2 2 2 2
Levels: 1 2 3
[1] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
[38] 1 1 1 1 1 1 1 1 1 1 1 1 1 3 3 3 3 3 3 2 3 3 3 3 3 3 3 3 3 3 3 3 3 2 3 3 3
[75] 3 3 3 2 3 3 3 3 3 2 3 2 3 3 3 3 3 3 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 2 2
[112] 2 2 2 2 2 2 2 2 3 2 2 2 2 2 2 2 2 2 2 2 2 2 3 3 2 2 2 2 2 2 2 2 2
22
Clases existentes en el terreno
12
10
3.0
8
2.5
2.0
6
1.5
4
1.0
2
0
0 2 4 6 8 10 12
23
Clases obtenidas mediante arboles de decision
12
10
3.0
8
2.5
2.0
6
1.5
4
1.0
2
0
0 2 4 6 8 10 12
24
Para realizar la evaluacion de la exactitud tematica de la clasificacion obte-
nida se pueden usar las siguientes instrucciones:
true
predicted 1 2 3
1 46 0 0
2 0 24 1
3 0 1 28
attr(,"error")
[1] 0.02
[1] 98
[1] 0.9688376
25
7) band4 > 16 11 6.702 2 ( 0.00000 0.90909 0.09091 )
14) band1 < 63.5 5 5.004 2 ( 0.00000 0.80000 0.20000 ) *
15) band1 > 63.5 6 0.000 2 ( 0.00000 1.00000 0.00000 ) *
> # ploteo default del arbol de clasificacion
> plot(tree1)
> text(tree1)
band3 < 25
|
band4 < 16
1
26
67.0 31.0 1.7 −Inf
100
80
deviance
60
40
20
size
27
Observe si el error de clasificación es mas alto que el obtenido usando el
árbol original. Enseguida se puede realizar el ploteo del árbol podado:
> plot(poda1)
> text(poda1)
band3 < 25
|
band4 < 16
1
3 2
El modelo del árbol podado se puede utilizar para predecir la clase de co-
bertura en toda la imagen:
> # prediccion
> clasepred <- predict(poda1,dfval, type="class")
> clasepred
[1] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
[38] 1 1 1 1 1 1 1 1 1 1 1 1 1 3 3 3 3 3 3 2 3 3 3 3 3 3 3 3 3 3 3 3 3 2 3 3 3
[75] 3 3 3 2 3 3 3 3 3 2 3 2 3 3 3 3 3 3 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 2 2
[112] 2 2 2 2 2 2 2 2 3 2 2 2 2 2 2 2 2 2 2 2 2 2 3 3 2 2 2 2 2 2 2 2 2
Levels: 1 2 3
28
[1] 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
[38] 1 1 1 1 1 1 1 1 1 1 1 1 1 3 3 3 3 3 3 2 3 3 3 3 3 3 3 3 3 3 3 3 3 2 3 3 3
[75] 3 3 3 2 3 3 3 3 3 2 3 2 3 3 3 3 3 3 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 2 2
[112] 2 2 2 2 2 2 2 2 3 2 2 2 2 2 2 2 2 2 2 2 2 2 3 3 2 2 2 2 2 2 2 2 2
3.0
8
2.5
2.0
6
1.5
4
1.0
2
0
0 2 4 6 8 10 12
29
Clases obtenidas mediante arboles de decision
12
10
3.0
8
2.5
2.0
6
1.5
4
1.0
2
0
0 2 4 6 8 10 12
true
predicted 1 2 3
1 46 0 0
2 0 24 1
3 0 1 28
attr(,"error")
[1] 0.02
[1] 98
30
> # obtencion del valor kappa
> k4 = Kappa(conf4)$Unweighted[[1]]
> #
> k4
[1] 0.9688376
[[1]]
[1] 0.36456035 0.98485726 0.94782691 0.73933375 0.73947463 0.48966957
31
[7] 0.75608153 0.70427414 0.67213954 0.29464407 1.00846097 0.80332531
[13] 0.50334661 0.70580415 0.66029905 0.87909791 1.00821980 0.51866163
[19] 0.30160166 0.67897137 0.09518044 1.00806030 0.39385538 0.92672284
[[2]]
[1] 0.686779377 1.036186976 0.704788401 0.755405994 0.777404648 0.353107982
[7] 0.514597291 0.795720246 0.740793320 0.706523425 0.310435699 0.428548183
[13] 0.844651383 0.544201576 0.582514173 0.021849332 0.003427867 0.528996683
[19] 0.134228106 0.898589362 0.693821678 0.025590719 0.924764222 0.661695649
[25] 0.462930122 0.545449144 0.317650289 0.553843913 0.322615142 0.099621849
[31] 0.629295055 0.414380741
[[3]]
[1] 0.68616853 0.38473915 1.00542228 0.69912609 0.87275512 0.79711784
[7] 0.30769575 0.70791266 0.73567309 1.05199721 0.37331071 0.53976709
[13] 0.65984281 0.01333983 0.22235711 0.73607448 0.90688484 0.01656446
[19] 0.65679412 1.05138270 0.46361421 0.54842803 0.75203397 0.30884941
[25] 1.09281192 0.73948217 0.96436575
> alphaindex(svp)
[[1]]
[1] 4 5 6 8 10 13 14 16 18 19 20 22 28 30 32 35 38 41 42 44 46 47 49 50
[[2]]
[1] 1 5 7 9 10 12 13 14 15 18 19 21 22 23 24 25 26 28 29 31 32 33 35 37 40
[26] 41 42 43 45 46 48 49
[[3]]
[1] 1 4 6 7 8 9 12 15 16 20 21 23 24 25 29 30 31 33 37 38 40 43 44 45 47
[26] 48 50
> b(svp)
> # prediccion
> clasepred <- predict(svp,getValues(toy))
La siguiente instruccion permite crear un raster con las clases de cobertura
obtenidas por el algoritmo SVM:
32
Las siguientes instrucciones permiten visualizar el raster de clases existentes
en el terreno y el raster de clases obtenidas mediante SVM:
> plot(terreno, main="Clases existentes en el terreno")
3.0
8
2.5
2.0
6
1.5
4
1.0
2
0
0 2 4 6 8 10 12
33
Clases obtenidas mediante SVM
12
10
3.0
8
2.5
2.0
6
1.5
4
1.0
2
0
0 2 4 6 8 10 12
true
predicted 1 2 3
1 45 0 1
34
2 0 21 4
3 0 0 29
attr(,"error")
[1] 0.05
[1] 95
[1] 0.9221062
35