Introducción
En este documento se verán aspectos básicos del uso de R y
RStudio.
Objetos
En la sección anterior se mencionó que el Environment muestra los
objetos creados. En R se puede crear objetos y luego manipularlos. Por
ejemplo, el gráfico muestra el porcentaje de personas que apoyan a la
democracia en cada país. Si queremos guardar el resultados de Uruguay
(UY), podemos crear un objeto.
La siguiente línea de código crea un objeto llamado “UY” que almacena
el número 80. Esto objeto se muestra en el Environment, tanto el nombre,
como el valor que almacena.
UY = 80
HT = 46
Si quisiéramos calcular la diferencia en porcentaje entre Uruguay, el
país que muestra el mayor apoyo a la democracia, y Haití, el que muestra
el menor porcentaje, se puede calcular haciendo la resta del objeto
menos el valor del porcentaje en Haití. Cuando se corre este código,
RStudio nos muestra el resultado.
UY - HT
## [1] 34
Los objetos en R no solo almacenan números, sino que también pueden
guardar letras (o cadenas de caracteres).
El Barómetro de las Américas recoje información de casi todos los
países de las Américas. La tabla siguiente muestra los países en los que
se ha recogido información en alguna ronda.
Si queremos guardar el nombre de un país en un objeto, se puede
nombrar al objeto “pais1” y escribir el nombre del país (que es una
cadena de caracteres) entre comillas.
pais1 = "México"
Como se observa, el nombre del objeto no lleva tilde. Es posible
crear un objeto con tildes, pero se recomienda no hacerlo pues puede
crear problemas posteriores. La cadena de caracteres “México” sí incluye
la tilde. Esto no representa ningún problema. Es importante notar que
los caracteres en R se ponen entre comillas.
Vectores
Un vector es un objeto que contiene un conjunto de elementos, sean
números o cadenas de caracteres, entre otros. Por ejemplo, podemos crear
un vector que almacene todos los porcentajes del Gráfico 1.1.
apoyo = c(80, 73, 71, 69, 68, 67, 66, 63, 63, 63, 62, 61, 61, 57, 53, 52, 50, 50, 49, 46)
De manera similar, podemos crear un vector con los nombres (o siglas)
de los países.
pais = c("UY", "SV", "CR", "AR", "CL", "BR", "GY", "MX", "EC", "NI", "DO", "PN", "BO", "JA", "CO", "GT", "PY", "PE", "HN", "HT")
No es necesario seguir el mismo orden del gráfico; sin embargo, es
recomendable por razones que se explicarán más abajo.
Se puede seleccionar elementos particulares de un vector usando
[…]
. Por ejemplo, si queremos seleccionar el país de
Argentina, tanto su nombre, como su porcentaje, se tiene que colocar
entre corchetes la posición en la que se encuentra.
pais[11]
## [1] "DO"
apoyo[11]
## [1] 62
Funciones
Una función es un procedimiento que recibe un input y produce un
output. Por ejemplo, la función Y = X^2, recibe un valor X cualquiera,
por ejemplo 2, y devuelve un valor Y, en este caso 4. En R se tienen las
funciones algebraicas, como raíz cuadrada o logaritmo. Por ejemplo, la
función log(…)
recibe un valor X y devuelve un valor Y
igual al logaritmo de X.
sqrt(81) #por squared root
## [1] 9
log(20)
## [1] 2.995732
También se puede aplicar una función a un conjunto de datos, como los
almacenados en un vector. Por ejemplo, si quisiéramos calcular la tasa
de personas que apoya a la democracia por cada 1000 habitantes en todos
los países, tendríamos que multiplicar el vector “pais” entre 10. En
este caso, la función de multiplicación se aplica a cada elemento del
vector.
apoyo2 = apoyo*10
apoyo2
## [1] 800 730 710 690 680 670 660 630 630 630 620 610 610 570 530 520 500 500 490
## [20] 460
Hay otras funciones que resultan más útiles para nuestros objetivos
porque trabajan sobre un conjunto de valores, como los almacenados en un
vector, calculando un valor único. Por ejemplo, si queremos calcular el
apoyo a la democracia promedio en todos los países mostrados en el
Gráfico 1.1 se puede usar la función mean(…)
.
mean(apoyo)
## [1] 61.2
Esta función recibe todos los valores de un vector, los suma y los
divide entre el número de observaciones, mostrando la media (o
promedio).
Otra funciones muy usadas en estadística son la mediana, la
desviación estándar, el mínimo, el máximo y la suma.
median(apoyo)
## [1] 62.5
sd(apoyo)
## [1] 9.070484
min(apoyo)
## [1] 46
max(apoyo)
## [1] 80
sum(apoyo)
## [1] 1224
El Gráfico 1.1 muestra los resultados para los países donde se tiene
información. Sin embargo, en algunos casos un vector puede incluir un
valor perdido. Por ejemplo, el gráfico no muestra información para
Venezuela, país donde no se realizó trabajo de campo por motivos de
seguridad. Si quisiéramos crear un vector que incluya este valor
faltante, se podría hacer así:
apoyo2 = c(apoyo, NA)
apoyo2
## [1] 80 73 71 69 68 67 66 63 63 63 62 61 61 57 53 52 50 50 49 46 NA
En el procedimiento que hemos realizado hemos usado el mismo nombre
“apoyo2”, por lo que hemos sobreescrito el vector con estos nuevos
resultados. La cadena de número ahora incluye un valor final NA.
Algunas funciones NO pueden calcular directamente su procedimiento en
vectores que contienen valores NA. Por ejemplo, la función
mean
.
mean(apoyo2)
## [1] NA
El cálculo directo de la media del vector “apoyo2” nos devuelve un
resultado NA. Para poder hacer el cálculo, indicándole a la función que
no tome en cuenta este valor NA, se tiene que usar la especificación
na.rm=True
.
mean(apoyo2, na.rm=TRUE)
## [1] 61.2
Paquetes
R es un proyecto colaborativo. Muchos desarrolladores producen nuevos
paquetes que son administrados por el mismo proyecto de R. Estos
paquetes pueden incluir muchas funciones que ayudan a manejar datos.
Por ejemplo, R tiene funciones nativas para importar bases de datos
de diferentes formatos, como Excel, SPSS o Stata. Cada formato tiene una
función específica, como read_csv
o read_dta
.
Sin embargo, unos desarrolladores han producido un paquete llamado “rio”
que incluye una función import
que permite importar
cualquier tipo de base de datos. Este paquete no viene instalado en la
descarga básica de R, por lo que se tiene que instalar el paquete para
poder usarlo.
Para instalar un paquete se usa el comando
install.packages
con el nombre del paquete que se quiere
instalar entre comillas. En este caso hemos usado un # antes del código
debido a que ya se tiene instalado el paquete. Esto sirve para mostrar
que los comentarios o líneas de código que queremos mostrar, pero que no
se corran, se pueden hacer con un # antes del comentario o código.
#install.packages("rio")
Una vez instalado, se tiene que activar el paquete para poder usar
sus funciones. Esto se hace con el comando library
. Una vez
activado, se puede usar cualquier función de esta librería, como la
función import
. Para activar ya no se requiere comillas.
Este procedimiento se puede verificar en el panel inferior derecho, en
la pestaña “Packages”. El paquete “rio” aparece con un check.
library(rio)
Dataframes
Los dataframes son estructuras de datos rectangulares. Como
convención, los dataframes tienen en sus columnas a los vectores y en
las filas a las observaciones. Para crear un dataframe se usa el comando
data.frame(...)
.
Por ejemplo, podemos crear un dataframe que junte los datos del
vector “pais” con los del vector “apoyo”. Estos dos vectores tienen que
tener las mismas dimensiones. Vemos en el Environment que ambos tienen
como dimensión [1:20]. Este dataframe se puede guardar en un objeto
“apoyoAL”.
apoyoAL = data.frame(pais, apoyo)
apoyoAL
## pais apoyo
## 1 UY 80
## 2 SV 73
## 3 CR 71
## 4 AR 69
## 5 CL 68
## 6 BR 67
## 7 GY 66
## 8 MX 63
## 9 EC 63
## 10 NI 63
## 11 DO 62
## 12 PN 61
## 13 BO 61
## 14 JA 57
## 15 CO 53
## 16 GT 52
## 17 PY 50
## 18 PE 50
## 19 HN 49
## 20 HT 46
Vemos que el objeto “apoyoAL” se ha guardado en una sección aparte
del Environment que se llama “Data”. Este objeto tiene 20 observaciones
(es decir, 20 filas o países) y dos variables (es decir, dos vectores o
dos columnas). Se puede hacer click en este objeto y se puede ver la
plancha de datos en una pestaña aparte.
Si se quisiera hacer un dataframe con los vectores “pais” y “apoyo2”,
R nos daría un mensaje de error debido a que estos vectores tienen
diferentes dimensiones.
Ahora, el vector “apoyo” forma parte de la base de datos “apoyoAL”.
Para poder usar las funciones en un dataframe se debe especificar la
columna de la que se quiere calcular la función. Por ejemplo, si ahora
se quisiera calcular el promedio de apoyo a la democracia desde la base
de datos “apoyoAL” se tiene que especificar la columna con “$”.
mean(apoyoAL$apoyo)
## [1] 61.2
En general, cualquier base de datos es una estructura rectangular
donde en las filas tenemos las observaciones y en las columnas, las
variables, lo que cambia es el número de filas y de columnas.
Por ejemplo, una base de datos del Barómetro de las Américas de un
país puede tener 1,500 observaciones (1,500 filas) y más de 100
variables (más de 100 columnas). En ese caso, cada observación
corresponde a una persona que respondió la encuesta y una columna (o
vector de datos) representa las respuestas de todos los entrevistados a
una pregunta del cuestionario.
Es más, la base de datos conjunta (el merge de datos) es la base de
datos de todos los países. Esta base de datos puede tener más de 30 mil
observaciones (es decir, todos los entrevistados en todos los países en
una ronda determinada) y más de 100 columnas.
Más allá del tamaño de la base de datos, las columnas son vectores a
los que se les puede aplicar funciones.
En la siguiente sección sobre importación de los datos del Barómetro
de las Américas en RStudio se verá la manera de descargar una base de
datos del proyecto y cargarla en RStudio.
Resumen
En este documento se han revisado los elementos básico de R, como
objetos y vectores, y las funciones básicas que se pueden aplicar a
estos objetos. También se ha revisado la manera de instalar librerías y
de activarlas para poder usar sus funciones. Finalmente, se ha explicado
la idea de un dataframe.
Tarea
El proyecto del Barómetro de las Américas ha presentado sus
resultados para el 2023. El siguiente gráfico muestra los resultados
para el apoyo a la democracia en 2023.
Incluya estos resultados en el dataframe “apoyoAL” como un nuevo
vector/columna “apoyo2023”. Tome en cuenta:
Calcule la media de apoyo a la democracia en 2023.
Calcule la diferencia por país en el apoyo a la democracia entre
2021 y 2023.
LS0tCnRpdGxlOiAiUHJvY2VkaW1pZW50b3MgYsOhc2ljb3MiCm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgdG9jOiB0cnVlCiAgICB0b2NfZmxvYXQ6IHRydWUKICAgIGNvbGxhcHNlZDogZmFsc2UKICAgIG51bWJlcl9zZWN0aW9uczogZmFsc2UKICAgIHRvY19kZXB0aDogMQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQogICAgdGhlbWU6IGNvc21vCiAgICBoaWdobGlnaHQ6IHRleHRtYXRlCi0tLQoKIyBJbnRyb2R1Y2Npw7NuCgpFbiBlc3RlIGRvY3VtZW50byBzZSB2ZXLDoW4gYXNwZWN0b3MgYsOhc2ljb3MgZGVsIHVzbyBkZSBSIHkgUlN0dWRpby4KCiMgT2JqZXRvcwoKRW4gbGEgc2VjY2nDs24gYW50ZXJpb3Igc2UgbWVuY2lvbsOzIHF1ZSBlbCBFbnZpcm9ubWVudCBtdWVzdHJhIGxvcyBvYmpldG9zIGNyZWFkb3MuIEVuIFIgc2UgcHVlZGUgY3JlYXIgb2JqZXRvcyB5IGx1ZWdvIG1hbmlwdWxhcmxvcy4gUG9yIGVqZW1wbG8sIGVsIGdyw6FmaWNvIG11ZXN0cmEgZWwgcG9yY2VudGFqZSBkZSBwZXJzb25hcyBxdWUgYXBveWFuIGEgbGEgZGVtb2NyYWNpYSBlbiBjYWRhIHBhw61zLiBTaSBxdWVyZW1vcyBndWFyZGFyIGVsIHJlc3VsdGFkb3MgZGUgVXJ1Z3VheSAoVVkpLCBwb2RlbW9zIGNyZWFyIHVuIG9iamV0by4KCiFbXShGaWd1cmUxLjEucG5nKXt3aWR0aD0iNDkxIn0KCkxhIHNpZ3VpZW50ZSBsw61uZWEgZGUgY8OzZGlnbyBjcmVhIHVuIG9iamV0byBsbGFtYWRvICJVWSIgcXVlIGFsbWFjZW5hIGVsIG7Dum1lcm8gODAuIEVzdG8gb2JqZXRvIHNlIG11ZXN0cmEgZW4gZWwgRW52aXJvbm1lbnQsIHRhbnRvIGVsIG5vbWJyZSwgY29tbyBlbCB2YWxvciBxdWUgYWxtYWNlbmEuCgpgYGB7ciBvYmpldG99ClVZID0gODAKSFQgPSA0NgpgYGAKClNpIHF1aXNpw6lyYW1vcyBjYWxjdWxhciBsYSBkaWZlcmVuY2lhIGVuIHBvcmNlbnRhamUgZW50cmUgVXJ1Z3VheSwgZWwgcGHDrXMgcXVlIG11ZXN0cmEgZWwgbWF5b3IgYXBveW8gYSBsYSBkZW1vY3JhY2lhLCB5IEhhaXTDrSwgZWwgcXVlIG11ZXN0cmEgZWwgbWVub3IgcG9yY2VudGFqZSwgc2UgcHVlZGUgY2FsY3VsYXIgaGFjaWVuZG8gbGEgcmVzdGEgZGVsIG9iamV0byBtZW5vcyBlbCB2YWxvciBkZWwgcG9yY2VudGFqZSBlbiBIYWl0w60uIEN1YW5kbyBzZSBjb3JyZSBlc3RlIGPDs2RpZ28sIFJTdHVkaW8gbm9zIG11ZXN0cmEgZWwgcmVzdWx0YWRvLgoKYGBge3IgcmVzdGF9ClVZIC0gSFQKYGBgCgpMb3Mgb2JqZXRvcyBlbiBSIG5vIHNvbG8gYWxtYWNlbmFuIG7Dum1lcm9zLCBzaW5vIHF1ZSB0YW1iacOpbiBwdWVkZW4gZ3VhcmRhciBsZXRyYXMgKG8gY2FkZW5hcyBkZSBjYXJhY3RlcmVzKS4KCkVsIEJhcsOzbWV0cm8gZGUgbGFzIEFtw6lyaWNhcyByZWNvamUgaW5mb3JtYWNpw7NuIGRlIGNhc2kgdG9kb3MgbG9zIHBhw61zZXMgZGUgbGFzIEFtw6lyaWNhcy4gTGEgdGFibGEgc2lndWllbnRlIG11ZXN0cmEgbG9zIHBhw61zZXMgZW4gbG9zIHF1ZSBzZSBoYSByZWNvZ2lkbyBpbmZvcm1hY2nDs24gZW4gYWxndW5hIHJvbmRhLgoKIVtdKHBhaXMucG5nKXt3aWR0aD0iNTUyIn0KClNpIHF1ZXJlbW9zIGd1YXJkYXIgZWwgbm9tYnJlIGRlIHVuIHBhw61zIGVuIHVuIG9iamV0bywgc2UgcHVlZGUgbm9tYnJhciBhbCBvYmpldG8gInBhaXMxIiB5IGVzY3JpYmlyIGVsIG5vbWJyZSBkZWwgcGHDrXMgKHF1ZSBlcyB1bmEgY2FkZW5hIGRlIGNhcmFjdGVyZXMpIGVudHJlIGNvbWlsbGFzLgoKYGBge3IgcGFpc30KcGFpczEgPSAiTcOpeGljbyIKYGBgCgpDb21vIHNlIG9ic2VydmEsIGVsIG5vbWJyZSBkZWwgb2JqZXRvIG5vIGxsZXZhIHRpbGRlLiBFcyBwb3NpYmxlIGNyZWFyIHVuIG9iamV0byBjb24gdGlsZGVzLCBwZXJvIHNlIHJlY29taWVuZGEgbm8gaGFjZXJsbyBwdWVzIHB1ZWRlIGNyZWFyIHByb2JsZW1hcyBwb3N0ZXJpb3Jlcy4gTGEgY2FkZW5hIGRlIGNhcmFjdGVyZXMgIk3DqXhpY28iIHPDrSBpbmNsdXllIGxhIHRpbGRlLiBFc3RvIG5vIHJlcHJlc2VudGEgbmluZ8O6biBwcm9ibGVtYS4gRXMgaW1wb3J0YW50ZSBub3RhciBxdWUgbG9zIGNhcmFjdGVyZXMgZW4gUiBzZSBwb25lbiBlbnRyZSBjb21pbGxhcy4KCiMgVmVjdG9yZXMKClVuIHZlY3RvciBlcyB1biBvYmpldG8gcXVlIGNvbnRpZW5lIHVuIGNvbmp1bnRvIGRlIGVsZW1lbnRvcywgc2VhbiBuw7ptZXJvcyBvIGNhZGVuYXMgZGUgY2FyYWN0ZXJlcywgZW50cmUgb3Ryb3MuIFBvciBlamVtcGxvLCBwb2RlbW9zIGNyZWFyIHVuIHZlY3RvciBxdWUgYWxtYWNlbmUgdG9kb3MgbG9zIHBvcmNlbnRhamVzIGRlbCBHcsOhZmljbyAxLjEuCgpgYGB7ciB2ZWN0b3IgcG9yY2VudGFqZXN9CmFwb3lvID0gYyg4MCwgNzMsIDcxLCA2OSwgNjgsIDY3LCA2NiwgNjMsIDYzLCA2MywgNjIsIDYxLCA2MSwgNTcsIDUzLCA1MiwgNTAsIDUwLCA0OSwgNDYpCmBgYAoKRGUgbWFuZXJhIHNpbWlsYXIsIHBvZGVtb3MgY3JlYXIgdW4gdmVjdG9yIGNvbiBsb3Mgbm9tYnJlcyAobyBzaWdsYXMpIGRlIGxvcyBwYcOtc2VzLgoKYGBge3IgdmVjdG9yIHBhaXN9CnBhaXMgPSBjKCJVWSIsICJTViIsICJDUiIsICJBUiIsICJDTCIsICJCUiIsICJHWSIsICJNWCIsICJFQyIsICJOSSIsICJETyIsICJQTiIsICJCTyIsICJKQSIsICJDTyIsICJHVCIsICJQWSIsICJQRSIsICJITiIsICJIVCIpCmBgYAoKTm8gZXMgbmVjZXNhcmlvIHNlZ3VpciBlbCBtaXNtbyBvcmRlbiBkZWwgZ3LDoWZpY287IHNpbiBlbWJhcmdvLCBlcyByZWNvbWVuZGFibGUgcG9yIHJhem9uZXMgcXVlIHNlIGV4cGxpY2Fyw6FuIG3DoXMgYWJham8uCgpTZSBwdWVkZSBzZWxlY2Npb25hciBlbGVtZW50b3MgcGFydGljdWxhcmVzIGRlIHVuIHZlY3RvciB1c2FuZG8gYFvigKZdYC4gUG9yIGVqZW1wbG8sIHNpIHF1ZXJlbW9zIHNlbGVjY2lvbmFyIGVsIHBhw61zIGRlIEFyZ2VudGluYSwgdGFudG8gc3Ugbm9tYnJlLCBjb21vIHN1IHBvcmNlbnRhamUsIHNlIHRpZW5lIHF1ZSBjb2xvY2FyIGVudHJlIGNvcmNoZXRlcyBsYSBwb3NpY2nDs24gZW4gbGEgcXVlIHNlIGVuY3VlbnRyYS4KCmBgYHtyIHNlbGVjY2lvbmFyIHZlY3Rvcn0KcGFpc1sxMV0KYXBveW9bMTFdCmBgYAoKIyBGdW5jaW9uZXMKClVuYSBmdW5jacOzbiBlcyB1biBwcm9jZWRpbWllbnRvIHF1ZSByZWNpYmUgdW4gaW5wdXQgeSBwcm9kdWNlIHVuIG91dHB1dC4gUG9yIGVqZW1wbG8sIGxhIGZ1bmNpw7NuIFkgPSBYXF4yLCByZWNpYmUgdW4gdmFsb3IgWCBjdWFscXVpZXJhLCBwb3IgZWplbXBsbyAyLCB5IGRldnVlbHZlIHVuIHZhbG9yIFksIGVuIGVzdGUgY2FzbyA0LiBFbiBSIHNlIHRpZW5lbiBsYXMgZnVuY2lvbmVzIGFsZ2VicmFpY2FzLCBjb21vIHJhw616IGN1YWRyYWRhIG8gbG9nYXJpdG1vLiBQb3IgZWplbXBsbywgbGEgZnVuY2nDs24gYGxvZyjigKYpYCByZWNpYmUgdW4gdmFsb3IgWCB5IGRldnVlbHZlIHVuIHZhbG9yIFkgaWd1YWwgYWwgbG9nYXJpdG1vIGRlIFguCgpgYGB7ciByYWl6fQpzcXJ0KDgxKSAjcG9yIHNxdWFyZWQgcm9vdApsb2coMjApCmBgYAoKVGFtYmnDqW4gc2UgcHVlZGUgYXBsaWNhciB1bmEgZnVuY2nDs24gYSB1biBjb25qdW50byBkZSBkYXRvcywgY29tbyBsb3MgYWxtYWNlbmFkb3MgZW4gdW4gdmVjdG9yLiBQb3IgZWplbXBsbywgc2kgcXVpc2nDqXJhbW9zIGNhbGN1bGFyIGxhIHRhc2EgZGUgcGVyc29uYXMgcXVlIGFwb3lhIGEgbGEgZGVtb2NyYWNpYSBwb3IgY2FkYSAxMDAwIGhhYml0YW50ZXMgZW4gdG9kb3MgbG9zIHBhw61zZXMsIHRlbmRyw61hbW9zIHF1ZSBtdWx0aXBsaWNhciBlbCB2ZWN0b3IgInBhaXMiIGVudHJlIDEwLiBFbiBlc3RlIGNhc28sIGxhIGZ1bmNpw7NuIGRlIG11bHRpcGxpY2FjacOzbiBzZSBhcGxpY2EgYSBjYWRhIGVsZW1lbnRvIGRlbCB2ZWN0b3IuCgpgYGB7ciBhcG95bzJ9CmFwb3lvMiA9IGFwb3lvKjEwCmFwb3lvMgpgYGAKCkhheSBvdHJhcyBmdW5jaW9uZXMgcXVlIHJlc3VsdGFuIG3DoXMgw7p0aWxlcyBwYXJhIG51ZXN0cm9zIG9iamV0aXZvcyBwb3JxdWUgdHJhYmFqYW4gc29icmUgdW4gY29uanVudG8gZGUgdmFsb3JlcywgY29tbyBsb3MgYWxtYWNlbmFkb3MgZW4gdW4gdmVjdG9yLCBjYWxjdWxhbmRvIHVuIHZhbG9yIMO6bmljby4gUG9yIGVqZW1wbG8sIHNpIHF1ZXJlbW9zIGNhbGN1bGFyIGVsIGFwb3lvIGEgbGEgZGVtb2NyYWNpYSBwcm9tZWRpbyBlbiB0b2RvcyBsb3MgcGHDrXNlcyBtb3N0cmFkb3MgZW4gZWwgR3LDoWZpY28gMS4xIHNlIHB1ZWRlIHVzYXIgbGEgZnVuY2nDs24gYG1lYW4o4oCmKWAuCgpgYGB7ciBtZWRpYX0KbWVhbihhcG95bykKYGBgCgpFc3RhIGZ1bmNpw7NuIHJlY2liZSB0b2RvcyBsb3MgdmFsb3JlcyBkZSB1biB2ZWN0b3IsIGxvcyBzdW1hIHkgbG9zIGRpdmlkZSBlbnRyZSBlbCBuw7ptZXJvIGRlIG9ic2VydmFjaW9uZXMsIG1vc3RyYW5kbyBsYSBtZWRpYSAobyBwcm9tZWRpbykuCgpPdHJhIGZ1bmNpb25lcyBtdXkgdXNhZGFzIGVuIGVzdGFkw61zdGljYSBzb24gbGEgbWVkaWFuYSwgbGEgZGVzdmlhY2nDs24gZXN0w6FuZGFyLCBlbCBtw61uaW1vLCBlbCBtw6F4aW1vIHkgbGEgc3VtYS4KCmBgYHtyIG90cmFzIGZ1bmNpb25lc30KbWVkaWFuKGFwb3lvKQpzZChhcG95bykKbWluKGFwb3lvKQptYXgoYXBveW8pCnN1bShhcG95bykKYGBgCgpFbCBHcsOhZmljbyAxLjEgbXVlc3RyYSBsb3MgcmVzdWx0YWRvcyBwYXJhIGxvcyBwYcOtc2VzIGRvbmRlIHNlIHRpZW5lIGluZm9ybWFjacOzbi4gU2luIGVtYmFyZ28sIGVuIGFsZ3Vub3MgY2Fzb3MgdW4gdmVjdG9yIHB1ZWRlIGluY2x1aXIgdW4gdmFsb3IgcGVyZGlkby4gUG9yIGVqZW1wbG8sIGVsIGdyw6FmaWNvIG5vIG11ZXN0cmEgaW5mb3JtYWNpw7NuIHBhcmEgVmVuZXp1ZWxhLCBwYcOtcyBkb25kZSBubyBzZSByZWFsaXrDsyB0cmFiYWpvIGRlIGNhbXBvIHBvciBtb3Rpdm9zIGRlIHNlZ3VyaWRhZC4gU2kgcXVpc2nDqXJhbW9zIGNyZWFyIHVuIHZlY3RvciBxdWUgaW5jbHV5YSBlc3RlIHZhbG9yIGZhbHRhbnRlLCBzZSBwb2Ryw61hIGhhY2VyIGFzw606CgpgYGB7ciBhcG95byBjb24gTkF9CmFwb3lvMiA9IGMoYXBveW8sIE5BKQphcG95bzIKYGBgCgpFbiBlbCBwcm9jZWRpbWllbnRvIHF1ZSBoZW1vcyByZWFsaXphZG8gaGVtb3MgdXNhZG8gZWwgbWlzbW8gbm9tYnJlICJhcG95bzIiLCBwb3IgbG8gcXVlIGhlbW9zIHNvYnJlZXNjcml0byBlbCB2ZWN0b3IgY29uIGVzdG9zIG51ZXZvcyByZXN1bHRhZG9zLiBMYSBjYWRlbmEgZGUgbsO6bWVybyBhaG9yYSBpbmNsdXllIHVuIHZhbG9yIGZpbmFsIE5BLgoKQWxndW5hcyBmdW5jaW9uZXMgTk8gcHVlZGVuIGNhbGN1bGFyIGRpcmVjdGFtZW50ZSBzdSBwcm9jZWRpbWllbnRvIGVuIHZlY3RvcmVzIHF1ZSBjb250aWVuZW4gdmFsb3JlcyBOQS4gUG9yIGVqZW1wbG8sIGxhIGZ1bmNpw7NuIGBtZWFuYC4KCmBgYHtyIG1lZGlhIGFwb3lvMn0KbWVhbihhcG95bzIpCmBgYAoKRWwgY8OhbGN1bG8gZGlyZWN0byBkZSBsYSBtZWRpYSBkZWwgdmVjdG9yICJhcG95bzIiIG5vcyBkZXZ1ZWx2ZSB1biByZXN1bHRhZG8gTkEuIFBhcmEgcG9kZXIgaGFjZXIgZWwgY8OhbGN1bG8sIGluZGljw6FuZG9sZSBhIGxhIGZ1bmNpw7NuIHF1ZSBubyB0b21lIGVuIGN1ZW50YSBlc3RlIHZhbG9yIE5BLCBzZSB0aWVuZSBxdWUgdXNhciBsYSBlc3BlY2lmaWNhY2nDs24gYG5hLnJtPVRydWVgLgoKYGBge3IgbWVkaWEgYXBveW8gbmEucm19Cm1lYW4oYXBveW8yLCBuYS5ybT1UUlVFKQpgYGAKCiMgUGFxdWV0ZXMKClIgZXMgdW4gcHJveWVjdG8gY29sYWJvcmF0aXZvLiBNdWNob3MgZGVzYXJyb2xsYWRvcmVzIHByb2R1Y2VuIG51ZXZvcyBwYXF1ZXRlcyBxdWUgc29uIGFkbWluaXN0cmFkb3MgcG9yIGVsIG1pc21vIHByb3llY3RvIGRlIFIuIEVzdG9zIHBhcXVldGVzIHB1ZWRlbiBpbmNsdWlyIG11Y2hhcyBmdW5jaW9uZXMgcXVlIGF5dWRhbiBhIG1hbmVqYXIgZGF0b3MuCgpQb3IgZWplbXBsbywgUiB0aWVuZSBmdW5jaW9uZXMgbmF0aXZhcyBwYXJhIGltcG9ydGFyIGJhc2VzIGRlIGRhdG9zIGRlIGRpZmVyZW50ZXMgZm9ybWF0b3MsIGNvbW8gRXhjZWwsIFNQU1MgbyBTdGF0YS4gQ2FkYSBmb3JtYXRvIHRpZW5lIHVuYSBmdW5jacOzbiBlc3BlY8OtZmljYSwgY29tbyBgcmVhZF9jc3ZgIG8gYHJlYWRfZHRhYC4gU2luIGVtYmFyZ28sIHVub3MgZGVzYXJyb2xsYWRvcmVzIGhhbiBwcm9kdWNpZG8gdW4gcGFxdWV0ZSBsbGFtYWRvICJyaW8iIHF1ZSBpbmNsdXllIHVuYSBmdW5jacOzbiBgaW1wb3J0YCBxdWUgcGVybWl0ZSBpbXBvcnRhciBjdWFscXVpZXIgdGlwbyBkZSBiYXNlIGRlIGRhdG9zLiBFc3RlIHBhcXVldGUgbm8gdmllbmUgaW5zdGFsYWRvIGVuIGxhIGRlc2NhcmdhIGLDoXNpY2EgZGUgUiwgcG9yIGxvIHF1ZSBzZSB0aWVuZSBxdWUgaW5zdGFsYXIgZWwgcGFxdWV0ZSBwYXJhIHBvZGVyIHVzYXJsby4KClBhcmEgaW5zdGFsYXIgdW4gcGFxdWV0ZSBzZSB1c2EgZWwgY29tYW5kbyBgaW5zdGFsbC5wYWNrYWdlc2AgY29uIGVsIG5vbWJyZSBkZWwgcGFxdWV0ZSBxdWUgc2UgcXVpZXJlIGluc3RhbGFyIGVudHJlIGNvbWlsbGFzLiBFbiBlc3RlIGNhc28gaGVtb3MgdXNhZG8gdW4gXCMgYW50ZXMgZGVsIGPDs2RpZ28gZGViaWRvIGEgcXVlIHlhIHNlIHRpZW5lIGluc3RhbGFkbyBlbCBwYXF1ZXRlLiBFc3RvIHNpcnZlIHBhcmEgbW9zdHJhciBxdWUgbG9zIGNvbWVudGFyaW9zIG8gbMOtbmVhcyBkZSBjw7NkaWdvIHF1ZSBxdWVyZW1vcyBtb3N0cmFyLCBwZXJvIHF1ZSBubyBzZSBjb3JyYW4sIHNlIHB1ZWRlbiBoYWNlciBjb24gdW4gXCMgYW50ZXMgZGVsIGNvbWVudGFyaW8gbyBjw7NkaWdvLgoKYGBge3IgaW5zdGFsYXIgcGFxdWV0ZXN9CiNpbnN0YWxsLnBhY2thZ2VzKCJyaW8iKQpgYGAKClVuYSB2ZXogaW5zdGFsYWRvLCBzZSB0aWVuZSBxdWUgYWN0aXZhciBlbCBwYXF1ZXRlIHBhcmEgcG9kZXIgdXNhciBzdXMgZnVuY2lvbmVzLiBFc3RvIHNlIGhhY2UgY29uIGVsIGNvbWFuZG8gYGxpYnJhcnlgLiBVbmEgdmV6IGFjdGl2YWRvLCBzZSBwdWVkZSB1c2FyIGN1YWxxdWllciBmdW5jacOzbiBkZSBlc3RhIGxpYnJlcsOtYSwgY29tbyBsYSBmdW5jacOzbiBgaW1wb3J0YC4gUGFyYSBhY3RpdmFyIHlhIG5vIHNlIHJlcXVpZXJlIGNvbWlsbGFzLiBFc3RlIHByb2NlZGltaWVudG8gc2UgcHVlZGUgdmVyaWZpY2FyIGVuIGVsIHBhbmVsIGluZmVyaW9yIGRlcmVjaG8sIGVuIGxhIHBlc3Rhw7FhICJQYWNrYWdlcyIuIEVsIHBhcXVldGUgInJpbyIgYXBhcmVjZSBjb24gdW4gY2hlY2suCgpgYGB7ciBhY3RpdmFyfQpsaWJyYXJ5KHJpbykKYGBgCgojIERhdGFmcmFtZXMKCkxvcyBkYXRhZnJhbWVzIHNvbiBlc3RydWN0dXJhcyBkZSBkYXRvcyByZWN0YW5ndWxhcmVzLiBDb21vIGNvbnZlbmNpw7NuLCBsb3MgZGF0YWZyYW1lcyB0aWVuZW4gZW4gc3VzIGNvbHVtbmFzIGEgbG9zIHZlY3RvcmVzIHkgZW4gbGFzIGZpbGFzIGEgbGFzIG9ic2VydmFjaW9uZXMuIFBhcmEgY3JlYXIgdW4gZGF0YWZyYW1lIHNlIHVzYSBlbCBjb21hbmRvIGBkYXRhLmZyYW1lKC4uLilgLgoKUG9yIGVqZW1wbG8sIHBvZGVtb3MgY3JlYXIgdW4gZGF0YWZyYW1lIHF1ZSBqdW50ZSBsb3MgZGF0b3MgZGVsIHZlY3RvciAicGFpcyIgY29uIGxvcyBkZWwgdmVjdG9yICJhcG95byIuIEVzdG9zIGRvcyB2ZWN0b3JlcyB0aWVuZW4gcXVlIHRlbmVyIGxhcyBtaXNtYXMgZGltZW5zaW9uZXMuIFZlbW9zIGVuIGVsIEVudmlyb25tZW50IHF1ZSBhbWJvcyB0aWVuZW4gY29tbyBkaW1lbnNpw7NuIFsxOjIwXS4gRXN0ZSBkYXRhZnJhbWUgc2UgcHVlZGUgZ3VhcmRhciBlbiB1biBvYmpldG8gImFwb3lvQUwiLgoKYGBge3IgZGF0YWZyYW1lfQphcG95b0FMID0gZGF0YS5mcmFtZShwYWlzLCBhcG95bykKYXBveW9BTApgYGAKClZlbW9zIHF1ZSBlbCBvYmpldG8gImFwb3lvQUwiIHNlIGhhIGd1YXJkYWRvIGVuIHVuYSBzZWNjacOzbiBhcGFydGUgZGVsIEVudmlyb25tZW50IHF1ZSBzZSBsbGFtYSAiRGF0YSIuIEVzdGUgb2JqZXRvIHRpZW5lIDIwIG9ic2VydmFjaW9uZXMgKGVzIGRlY2lyLCAyMCBmaWxhcyBvIHBhw61zZXMpIHkgZG9zIHZhcmlhYmxlcyAoZXMgZGVjaXIsIGRvcyB2ZWN0b3JlcyBvIGRvcyBjb2x1bW5hcykuIFNlIHB1ZWRlIGhhY2VyIGNsaWNrIGVuIGVzdGUgb2JqZXRvIHkgc2UgcHVlZGUgdmVyIGxhIHBsYW5jaGEgZGUgZGF0b3MgZW4gdW5hIHBlc3Rhw7FhIGFwYXJ0ZS4KClNpIHNlIHF1aXNpZXJhIGhhY2VyIHVuIGRhdGFmcmFtZSBjb24gbG9zIHZlY3RvcmVzICJwYWlzIiB5ICJhcG95bzIiLCBSIG5vcyBkYXLDrWEgdW4gbWVuc2FqZSBkZSBlcnJvciBkZWJpZG8gYSBxdWUgZXN0b3MgdmVjdG9yZXMgdGllbmVuIGRpZmVyZW50ZXMgZGltZW5zaW9uZXMuCgpBaG9yYSwgZWwgdmVjdG9yICJhcG95byIgZm9ybWEgcGFydGUgZGUgbGEgYmFzZSBkZSBkYXRvcyAiYXBveW9BTCIuIFBhcmEgcG9kZXIgdXNhciBsYXMgZnVuY2lvbmVzIGVuIHVuIGRhdGFmcmFtZSBzZSBkZWJlIGVzcGVjaWZpY2FyIGxhIGNvbHVtbmEgZGUgbGEgcXVlIHNlIHF1aWVyZSBjYWxjdWxhciBsYSBmdW5jacOzbi4gUG9yIGVqZW1wbG8sIHNpIGFob3JhIHNlIHF1aXNpZXJhIGNhbGN1bGFyIGVsIHByb21lZGlvIGRlIGFwb3lvIGEgbGEgZGVtb2NyYWNpYSBkZXNkZSBsYSBiYXNlIGRlIGRhdG9zICJhcG95b0FMIiBzZSB0aWVuZSBxdWUgZXNwZWNpZmljYXIgbGEgY29sdW1uYSBjb24gIlwkIi4KCmBgYHtyIGFwb3lvIGRhdGF9Cm1lYW4oYXBveW9BTCRhcG95bykKYGBgCgpFbiBnZW5lcmFsLCBjdWFscXVpZXIgYmFzZSBkZSBkYXRvcyBlcyB1bmEgZXN0cnVjdHVyYSByZWN0YW5ndWxhciBkb25kZSBlbiBsYXMgZmlsYXMgdGVuZW1vcyBsYXMgb2JzZXJ2YWNpb25lcyB5IGVuIGxhcyBjb2x1bW5hcywgbGFzIHZhcmlhYmxlcywgbG8gcXVlIGNhbWJpYSBlcyBlbCBuw7ptZXJvIGRlIGZpbGFzIHkgZGUgY29sdW1uYXMuCgpQb3IgZWplbXBsbywgdW5hIGJhc2UgZGUgZGF0b3MgZGVsIEJhcsOzbWV0cm8gZGUgbGFzIEFtw6lyaWNhcyBkZSB1biBwYcOtcyBwdWVkZSB0ZW5lciAxLDUwMCBvYnNlcnZhY2lvbmVzICgxLDUwMCBmaWxhcykgeSBtw6FzIGRlIDEwMCB2YXJpYWJsZXMgKG3DoXMgZGUgMTAwIGNvbHVtbmFzKS4gRW4gZXNlIGNhc28sIGNhZGEgb2JzZXJ2YWNpw7NuIGNvcnJlc3BvbmRlIGEgdW5hIHBlcnNvbmEgcXVlIHJlc3BvbmRpw7MgbGEgZW5jdWVzdGEgeSB1bmEgY29sdW1uYSAobyB2ZWN0b3IgZGUgZGF0b3MpIHJlcHJlc2VudGEgbGFzIHJlc3B1ZXN0YXMgZGUgdG9kb3MgbG9zIGVudHJldmlzdGFkb3MgYSB1bmEgcHJlZ3VudGEgZGVsIGN1ZXN0aW9uYXJpby4KCkVzIG3DoXMsIGxhIGJhc2UgZGUgZGF0b3MgY29uanVudGEgKGVsIG1lcmdlIGRlIGRhdG9zKSBlcyBsYSBiYXNlIGRlIGRhdG9zIGRlIHRvZG9zIGxvcyBwYcOtc2VzLiBFc3RhIGJhc2UgZGUgZGF0b3MgcHVlZGUgdGVuZXIgbcOhcyBkZSAzMCBtaWwgb2JzZXJ2YWNpb25lcyAoZXMgZGVjaXIsIHRvZG9zIGxvcyBlbnRyZXZpc3RhZG9zIGVuIHRvZG9zIGxvcyBwYcOtc2VzIGVuIHVuYSByb25kYSBkZXRlcm1pbmFkYSkgeSBtw6FzIGRlIDEwMCBjb2x1bW5hcy4KCk3DoXMgYWxsw6EgZGVsIHRhbWHDsW8gZGUgbGEgYmFzZSBkZSBkYXRvcywgbGFzIGNvbHVtbmFzIHNvbiB2ZWN0b3JlcyBhIGxvcyBxdWUgc2UgbGVzIHB1ZWRlIGFwbGljYXIgZnVuY2lvbmVzLgoKRW4gbGEgc2lndWllbnRlIHNlY2Npw7NuIHNvYnJlIGltcG9ydGFjacOzbiBkZSBsb3MgZGF0b3MgZGVsIEJhcsOzbWV0cm8gZGUgbGFzIEFtw6lyaWNhcyBlbiBSU3R1ZGlvIHNlIHZlcsOhIGxhIG1hbmVyYSBkZSBkZXNjYXJnYXIgdW5hIGJhc2UgZGUgZGF0b3MgZGVsIHByb3llY3RvIHkgY2FyZ2FybGEgZW4gUlN0dWRpby4KCiMgUmVzdW1lbgoKRW4gZXN0ZSBkb2N1bWVudG8gc2UgaGFuIHJldmlzYWRvIGxvcyBlbGVtZW50b3MgYsOhc2ljbyBkZSBSLCBjb21vIG9iamV0b3MgeSB2ZWN0b3JlcywgeSBsYXMgZnVuY2lvbmVzIGLDoXNpY2FzIHF1ZSBzZSBwdWVkZW4gYXBsaWNhciBhIGVzdG9zIG9iamV0b3MuIFRhbWJpw6luIHNlIGhhIHJldmlzYWRvIGxhIG1hbmVyYSBkZSBpbnN0YWxhciBsaWJyZXLDrWFzIHkgZGUgYWN0aXZhcmxhcyBwYXJhIHBvZGVyIHVzYXIgc3VzIGZ1bmNpb25lcy4gRmluYWxtZW50ZSwgc2UgaGEgZXhwbGljYWRvIGxhIGlkZWEgZGUgdW4gZGF0YWZyYW1lLgoKIyBUYXJlYQoKRWwgcHJveWVjdG8gZGVsIEJhcsOzbWV0cm8gZGUgbGFzIEFtw6lyaWNhcyBoYSBwcmVzZW50YWRvIHN1cyByZXN1bHRhZG9zIHBhcmEgZWwgMjAyMy4gRWwgc2lndWllbnRlIGdyw6FmaWNvIG11ZXN0cmEgbG9zIHJlc3VsdGFkb3MgcGFyYSBlbCBhcG95byBhIGxhIGRlbW9jcmFjaWEgZW4gMjAyMy4KCiFbXShhcG95bzIwMjMucG5nKXt3aWR0aD0iNjE3In0KCkluY2x1eWEgZXN0b3MgcmVzdWx0YWRvcyBlbiBlbCBkYXRhZnJhbWUgImFwb3lvQUwiIGNvbW8gdW4gbnVldm8gdmVjdG9yL2NvbHVtbmEgImFwb3lvMjAyMyIuIFRvbWUgZW4gY3VlbnRhOgoKLSAgIExvcyByZXN1bHRhZG9zIHBhcmEgZWwgMjAyMyBpbmNsdXllbiBtw6FzIHBhw61zZXMuCgotICAgUHVlZGUgc29icmVlc2NyaWJpciBlbCBkYXRhZnJhbWUgImFwb3lvQUwiIGRlIHNlciBuZWNlc2FyaW8uCgoxLiAgQ2FsY3VsZSBsYSBtZWRpYSBkZSBhcG95byBhIGxhIGRlbW9jcmFjaWEgZW4gMjAyMy4KCjIuICBDYWxjdWxlIGxhIGRpZmVyZW5jaWEgcG9yIHBhw61zIGVuIGVsIGFwb3lvIGEgbGEgZGVtb2NyYWNpYSBlbnRyZSAyMDIxIHkgMjAyMy4K