library("ggplot2")
library("dplyr")
library("tidyverse")
[30m-- [1mAttaching packages[22m --------------------------------------- tidyverse 1.2.1 --[39m
[30m[32mv[30m [34mtidyr [30m 0.8.2 [32mv[30m [34mpurrr [30m 0.2.5
[32mv[30m [34mreadr [30m 1.1.1 [32mv[30m [34mstringr[30m 1.3.1
[32mv[30m [34mtidyr [30m 0.8.2 [32mv[30m [34mforcats[30m 0.3.0[39m
[30m-- [1mConflicts[22m ------------------------------------------ tidyverse_conflicts() --
[31mx[30m [34mdplyr[30m::[32mfilter()[30m masks [34mstats[30m::filter()
[31mx[30m [34mdplyr[30m::[32mlag()[30m masks [34mstats[30m::lag()[39m
library("tibble")
install.packages("tidyverse")
Introducción al análisis de datos. en el texto se trata: “Reestructura de datos y el principio de los datos limpios” y “Estrategia divide-aplica-combina”.
La limpieza y orden de los datos es elemental para facilitar el trabajo de análisis, en este texto se muestran técnicas para hacer de la data un lugar más conveniente donde trabajar.
La idea es limpiar los datos de la información que no necesitamos y almacenarlos de una manera consistente que nos permita enfocarnos en responder las dudas antes de estar luchando por descifrarlos. A fin de cuentas, una data ordenada y limpia nos ayuda a trabajar en la: Manipulación, visualización y modelación de los datos.
En resumen:
Cada variable forma una columna
Cada observación forma un renglón
Cada tipo de unidad observacional forma una tabla
Lo importante de armar una tabla ordenada es comenzar por identificar las variables, en el siguiente caso, las variable será las anotaciones de Camilo y Luciano con la camiseta de su club universitario, Club Atlético Cenicero (CAC).
comenzaremos por asignarle nombre a la data, en este caso le pondremos Goles_por_partido, siendo el primer dato el nombre del jugador, separado por un guión bajo el número correspondiente a la fecha:
Goles_por_partido <- tibble(camilo_1 = c(2),
camilo_2 = c(3),
camilo_3 = c(1),
luciano_1 = c(1),
luciano_2 = c(3),
luciano_3 = c(0)
)
A continuación la tabla:
tibble(camilo_1 = c(2),
camilo_2 = c(3),
camilo_3 = c(1),
luciano_1 = c(1),
luciano_2 = c(3),
luciano_3 = c(0)
)
En este caso, las varibles son identificables como “nombres” (Camilo y Luciano), “fechas” y goles marcados. Los datos se encuentran en una sola líne sin una tabla clara.
Por otro lado, existen muchos errores posibles a la hora de ordenar una data, analizarla y extraer datos. Los errores más comunes dentro de este ejercicio pueden ser que: Los encabezados de las columnas son valores numéricos; pueden haber más de una variable por columna; las variables están organizadas tanto en filas como en columnas; más de un tipo de observación en una tabla o una misma unidad observacional está almacenada en múltiples tablas.
Es por eso que el paquete tidyr: tiene dos funciones claves para facilitar la tarea:
Gather: Junta las columnas en pares de valores y nombres, concrete los datos anchos en largos.
Spread: Separa dos columnas para hacer los datos más anchos.
En el caso de tener una tabla con datos desordenados e ilegibles, debemos ocupar tidy para ordenarla. Para comenzar se deben alargar los datos y así reconocer las dos columnas que se agrupan key y value. Para hacer esto ocupamos la función gather.
Dato importante
Si queremos restar de las columnas alguna variable es se debe anteponer el signo menos (-) antes de la variable a eliminar.
Para ejemplificar usaremos el primer ejemplo de este archivo, en el cual destacaban las variables relacionadas con los partidos de fútbol jugados por Camilo y Luciano, datos que sólo se presentan de manera lineal, para ordenar utilizaremos la función gather.
tidyr::gather(data = Goles_por_partido,
key = "Fecha_jugada",
value = "goles_marcados")
También puede pasar que una columna presente dos variables diferentes, en este caso podemos utilizar la función de tidy “separate”. Lo que hace es recibir la información:
Nombre de la base de datos.
El nombre de la variable que deseamos separar en más de una.
La posición de donde deseamos “cortar”. La función es separar valores en distintos puntos de la columna siempre y cuando esta no tenga un valor alfa numérico. (espacio, guión, punto, etc.).
En general, el paquete tidy es una herramienta muy útil en la visualización de datos en RStudio, ordena los datos para hacerlos más legibles a través de distintos métodos y funciones, como por ejemplo Gather y Spread.
Goles_Por_Partido_tidy <- gather(data = Goles_por_partido,
key = "Fecha_jugada",
value = "goles_marcados") %>%
separate(Fecha_jugada, into = c("Nombre", "Fecha"), sep = "_")
gather(data = Goles_por_partido,
key = "Fecha_jugada",
value = "goles_marcados") %>%
separate(Fecha_jugada, into = c("Nombre", "Fecha"), sep = "_")
Es elemental en este proceso tener en cuenta identificar de la mejor manera las diferentes variables presentes en la tabla, no sólo a modo infirmativo, sino que también para saber cuáles de estas son necesarias para nuestro trabajo. Por otra parte, es necesario tener en cuenta 5 puntos que son claves para la visualización de datos con tidy:
Incluir un encabezado con el nombre de las variables.
Los nombres de las variables deben ser entendibles. (Pendejetes es mejor que PobInfantilMenorA18).
En general los datos se deben guardar en un archivo por tabla.
Escribir un script con las modificaciones que se hicieron a los datos crudos (reproducibilidad).
Selección de variables, datos faltantes, tipos y detección de valores atípicos.
Otra forma de ordenar una data ilegible o enredada es la clásica forma de aplica-combina, que consiste en romper un problema en pedazos, separar todas las variables y dejarlas como información parcelada, para luego unir de la mejor forma y así ordenar.
Para esto es necesario tener en cuenta 3 conceptos:
Separa la base de datos original.
Aplica funciones a cada subconjunto.
Combina los resultados en una nueva base de datos.
Finalmente, si hablamos de ordenar datos no podemos dejar fuera a “dplyr”, en él se encuentran varias funciones, como por ejemplo:
Filter: Para obtener un subconjunto a elección.
Select: Selecciona columnas según el nombre.
Arrange: Reordena filas.
Mutate: Agrega nuevas variables.
Summarise: Reduce variables a valores (promedio).
En la siguiente tabla buscaremos dar un ejemplo de una de las funciones de dplyr, en base a la tabla utilizada con los goles por jugador y fecha. En este caso, ejemplificaremos con la función Filter:
filter(Goles_Por_Partido_tidy, goles_marcados == "0")
En la tabla anterior, filtramos los datos para extraer la información que necesitamos, en este caso para sacar el número de veces que un jugador no anotó en alguna fecha, dando como resultado que el jugador “Luciano” no anotó en la fecha número 3.
A diferencia del paquete tidy, en este caso generalmente se trabaja con una data ordenada, que previamente ordenamos o que ya se encontraba legible y útil para nuestro trabajo. Sin embargo, estas funciones funcionan de manera similar, reciben de entrada un dataframe, los argumentos que siguen indican qué trabajo realizaremos y nos arroja la nueva información.
LS0tDQp0aXRsZTogIlJlc3VtZW4gdGlkeWRhdGEiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQpgYGB7cn0NCmxpYnJhcnkoImdncGxvdDIiKQ0KbGlicmFyeSgiZHBseXIiKQ0KbGlicmFyeSgidGlkeXZlcnNlIikNCmxpYnJhcnkoInRpYmJsZSIpDQpgYGANCg0KYGBge3J9DQppbnN0YWxsLnBhY2thZ2VzKCJ0aWR5dmVyc2UiKQ0KYGBgDQoNCiMjI0ludHJvZHVjY2nzbiBhbCBhbuFsaXNpcyBkZSBkYXRvcy4gZW4gZWwgdGV4dG8gc2UgdHJhdGE6ICJSZWVzdHJ1Y3R1cmEgZGUgZGF0b3MgeSBlbCBwcmluY2lwaW8gZGUgbG9zIGRhdG9zIGxpbXBpb3MiIHkgIkVzdHJhdGVnaWEgZGl2aWRlLWFwbGljYS1jb21iaW5hIi4NCg0KDQoNCkxhIGxpbXBpZXphIHkgb3JkZW4gZGUgbG9zIGRhdG9zIGVzIGVsZW1lbnRhbCBwYXJhIGZhY2lsaXRhciBlbCB0cmFiYWpvIGRlIGFu4Wxpc2lzLCBlbiBlc3RlIHRleHRvIHNlIG11ZXN0cmFuIHTpY25pY2FzIHBhcmEgaGFjZXIgZGUgbGEgZGF0YSB1biBsdWdhciBt4XMgY29udmVuaWVudGUgZG9uZGUgdHJhYmFqYXIuDQoNCg0KDQpMYSBpZGVhIGVzIGxpbXBpYXIgbG9zIGRhdG9zIGRlIGxhIGluZm9ybWFjafNuIHF1ZSBubyBuZWNlc2l0YW1vcyB5IGFsbWFjZW5hcmxvcyBkZSB1bmEgbWFuZXJhIGNvbnNpc3RlbnRlIHF1ZSBub3MgcGVybWl0YSBlbmZvY2Fybm9zIGVuIHJlc3BvbmRlciBsYXMgZHVkYXMgYW50ZXMgZGUgZXN0YXIgbHVjaGFuZG8gcG9yIGRlc2NpZnJhcmxvcy4gQSBmaW4gZGUgY3VlbnRhcywgdW5hIGRhdGEgb3JkZW5hZGEgeSBsaW1waWEgbm9zIGF5dWRhIGEgdHJhYmFqYXIgZW4gbGE6IE1hbmlwdWxhY2nzbiwgdmlzdWFsaXphY2nzbiB5IG1vZGVsYWNp824gZGUgbG9zIGRhdG9zLg0KDQoNCg0KRW4gcmVzdW1lbjoNCg0KDQoNCi0gQ2FkYSB2YXJpYWJsZSBmb3JtYSB1bmEgY29sdW1uYQ0KDQoNCg0KLSBDYWRhIG9ic2VydmFjafNuIGZvcm1hIHVuIHJlbmds824NCg0KDQoNCi0gQ2FkYSB0aXBvIGRlIHVuaWRhZCBvYnNlcnZhY2lvbmFsIGZvcm1hIHVuYSB0YWJsYQ0KDQoNCg0KDQoNCkxvIGltcG9ydGFudGUgZGUgYXJtYXIgdW5hIHRhYmxhIG9yZGVuYWRhIGVzIGNvbWVuemFyIHBvciBpZGVudGlmaWNhciBsYXMgdmFyaWFibGVzLCBlbiBlbCBzaWd1aWVudGUgY2FzbywgbGFzIHZhcmlhYmxlIHNlcuEgbGFzIGFub3RhY2lvbmVzIGRlIENhbWlsbyB5IEx1Y2lhbm8gY29uIGxhIGNhbWlzZXRhIGRlIHN1IGNsdWIgdW5pdmVyc2l0YXJpbywgQ2x1YiBBdGzpdGljbyBDZW5pY2VybyAoKipDQUMqKikuDQoNCmNvbWVuemFyZW1vcyBwb3IgYXNpZ25hcmxlIG5vbWJyZSBhIGxhIGRhdGEsIGVuIGVzdGUgY2FzbyBsZSBwb25kcmVtb3MgKkdvbGVzX3Bvcl9wYXJ0aWRvKiwgc2llbmRvIGVsIHByaW1lciBkYXRvIGVsIG5vbWJyZSBkZWwganVnYWRvciwgc2VwYXJhZG8gcG9yIHVuIGd1afNuIGJham8gZWwgbvptZXJvIGNvcnJlc3BvbmRpZW50ZSBhIGxhIGZlY2hhOg0KDQpgYGB7cn0NCkdvbGVzX3Bvcl9wYXJ0aWRvIDwtIHRpYmJsZShjYW1pbG9fMSA9IGMoMiksDQogICAgICAgY2FtaWxvXzIgPSBjKDMpLA0KICAgICAgIGNhbWlsb18zID0gYygxKSwNCiAgICAgICBsdWNpYW5vXzEgPSBjKDEpLA0KICAgICAgIGx1Y2lhbm9fMiA9IGMoMyksDQogICAgICAgbHVjaWFub18zID0gYygwKQ0KICAgICAgICkNCmBgYA0KDQpBIGNvbnRpbnVhY2nzbiBsYSB0YWJsYToNCg0KYGBge3J9DQp0aWJibGUoY2FtaWxvXzEgPSBjKDIpLA0KICAgICAgIGNhbWlsb18yID0gYygzKSwNCiAgICAgICBjYW1pbG9fMyA9IGMoMSksDQogICAgICAgbHVjaWFub18xID0gYygxKSwNCiAgICAgICBsdWNpYW5vXzIgPSBjKDMpLA0KICAgICAgIGx1Y2lhbm9fMyA9IGMoMCkNCikNCmBgYA0KDQoNCkVuIGVzdGUgY2FzbywgbGFzIHZhcmlibGVzIHNvbiBpZGVudGlmaWNhYmxlcyBjb21vICJub21icmVzIiAoQ2FtaWxvIHkgTHVjaWFubyksICJmZWNoYXMiIHkgZ29sZXMgbWFyY2Fkb3MuIExvcyBkYXRvcyBzZSBlbmN1ZW50cmFuIGVuIHVuYSBzb2xhIGztbmUgc2luIHVuYSB0YWJsYSBjbGFyYS4NCg0KDQpQb3Igb3RybyBsYWRvLCBleGlzdGVuIG11Y2hvcyBlcnJvcmVzIHBvc2libGVzIGEgbGEgaG9yYSBkZSBvcmRlbmFyIHVuYSBkYXRhLCBhbmFsaXphcmxhIHkgZXh0cmFlciBkYXRvcy4gTG9zIGVycm9yZXMgbeFzIGNvbXVuZXMgZGVudHJvIGRlIGVzdGUgZWplcmNpY2lvIHB1ZWRlbiBzZXIgcXVlOiBMb3MgZW5jYWJlemFkb3MgZGUgbGFzIGNvbHVtbmFzIHNvbiB2YWxvcmVzIG51belyaWNvczsgcHVlZGVuIGhhYmVyIG3hcyBkZSB1bmEgdmFyaWFibGUgcG9yIGNvbHVtbmE7IGxhcyB2YXJpYWJsZXMgZXN04W4gb3JnYW5pemFkYXMgdGFudG8gZW4gZmlsYXMgY29tbyBlbiBjb2x1bW5hczsgbeFzIGRlIHVuIHRpcG8gZGUgb2JzZXJ2YWNp824gZW4gdW5hIHRhYmxhIG8gdW5hIG1pc21hIHVuaWRhZCBvYnNlcnZhY2lvbmFsIGVzdOEgYWxtYWNlbmFkYSBlbiBt+mx0aXBsZXMgdGFibGFzLg0KDQoNCg0KRXMgcG9yIGVzbyBxdWUgZWwgcGFxdWV0ZSAqdGlkeXI6KiB0aWVuZSBkb3MgZnVuY2lvbmVzIGNsYXZlcyBwYXJhIGZhY2lsaXRhciBsYSB0YXJlYToNCg0KDQoNCi0gKipHYXRoZXIqKjogSnVudGEgbGFzIGNvbHVtbmFzIGVuIHBhcmVzIGRlIHZhbG9yZXMgeSBub21icmVzLCBjb25jcmV0ZSBsb3MgZGF0b3MgYW5jaG9zIGVuIGxhcmdvcy4NCg0KDQoNCi0gKipTcHJlYWQqKjogU2VwYXJhIGRvcyBjb2x1bW5hcyBwYXJhIGhhY2VyIGxvcyBkYXRvcyBt4XMgYW5jaG9zLg0KDQoNCg0KDQoNCkVuIGVsIGNhc28gZGUgdGVuZXIgdW5hIHRhYmxhIGNvbiBkYXRvcyBkZXNvcmRlbmFkb3MgZSBpbGVnaWJsZXMsIGRlYmVtb3Mgb2N1cGFyIHRpZHkgcGFyYSBvcmRlbmFybGEuIFBhcmEgY29tZW56YXIgc2UgZGViZW4gYWxhcmdhciBsb3MgZGF0b3MgeSBhc+0gcmVjb25vY2VyIGxhcyBkb3MgY29sdW1uYXMgcXVlIHNlIGFncnVwYW4gKmtleSogeSAqdmFsdWUqLiBQYXJhIGhhY2VyIGVzdG8gb2N1cGFtb3MgbGEgZnVuY2nzbiAqZ2F0aGVyKi4NCg0KDQoNCi0gKipLZXkqKjogTm9tYnJlIGRlIGxhIG51ZXZhIHZhcmlhYmxlIHF1ZSBjb250aWVuZSBsbyBxdWUgZnVlcm9uIGxvcyBub21icmVzIGRlIGNvbHVtbmFzIHF1ZSBhcGlsYW1vcy4NCg0KDQoNCi0gKipWYWx1ZSoqOiBOb21icmUgZGUgbGEgdmFyaWFibGUgcXVlIGFsbWFjZW5hcuEgbG9zIHZhbG9yZXMgcXVlIGNvcnJlc3BvbmRlbiBhIGNhZGEgKmtleSouDQoNCg0KDQojIyNEYXRvIGltcG9ydGFudGUjIyMgDQoNCg0KDQpTaSBxdWVyZW1vcyByZXN0YXIgZGUgbGFzIGNvbHVtbmFzIGFsZ3VuYSB2YXJpYWJsZSBlcyBzZSBkZWJlIGFudGVwb25lciBlbCBzaWdubyBtZW5vcyAoLSkgYW50ZXMgZGUgbGEgdmFyaWFibGUgYSBlbGltaW5hci4NCg0KDQpQYXJhIGVqZW1wbGlmaWNhciB1c2FyZW1vcyBlbCBwcmltZXIgZWplbXBsbyBkZSBlc3RlIGFyY2hpdm8sIGVuIGVsIGN1YWwgZGVzdGFjYWJhbiBsYXMgdmFyaWFibGVzIHJlbGFjaW9uYWRhcyBjb24gbG9zIHBhcnRpZG9zIGRlIGb6dGJvbCBqdWdhZG9zIHBvciBDYW1pbG8geSBMdWNpYW5vLCBkYXRvcyBxdWUgc/NsbyBzZSBwcmVzZW50YW4gZGUgbWFuZXJhIGxpbmVhbCwgcGFyYSBvcmRlbmFyIHV0aWxpemFyZW1vcyBsYSBmdW5jafNuICpnYXRoZXIqLg0KDQpgYGB7cn0NCnRpZHlyOjpnYXRoZXIoZGF0YSA9IEdvbGVzX3Bvcl9wYXJ0aWRvLA0KICAgICAgICAgICAgICBrZXkgPSAiRmVjaGFfanVnYWRhIiwNCiAgICAgICAgICAgICAgdmFsdWUgPSAiZ29sZXNfbWFyY2Fkb3MiKQ0KYGBgDQoNCg0KDQpUYW1iaeluIHB1ZWRlIHBhc2FyIHF1ZSB1bmEgY29sdW1uYSBwcmVzZW50ZSBkb3MgdmFyaWFibGVzIGRpZmVyZW50ZXMsIGVuIGVzdGUgY2FzbyBwb2RlbW9zIHV0aWxpemFyIGxhIGZ1bmNp824gZGUgdGlkeSAic2VwYXJhdGUiLiBMbyBxdWUgaGFjZSBlcyByZWNpYmlyIGxhIGluZm9ybWFjafNuOg0KDQoNCg0KLSBOb21icmUgZGUgbGEgYmFzZSBkZSBkYXRvcy4NCg0KLSBFbCBub21icmUgZGUgbGEgdmFyaWFibGUgcXVlIGRlc2VhbW9zIHNlcGFyYXIgZW4gbeFzIGRlIHVuYS4NCg0KLSBMYSBwb3NpY2nzbiBkZSBkb25kZSBkZXNlYW1vcyAiY29ydGFyIi4gTGEgZnVuY2nzbiBlcyBzZXBhcmFyIHZhbG9yZXMgZW4gZGlzdGludG9zIHB1bnRvcyBkZSBsYSBjb2x1bW5hIHNpZW1wcmUgeSBjdWFuZG8gZXN0YSBubyB0ZW5nYSB1biB2YWxvciBhbGZhIG51belyaWNvLiAoZXNwYWNpbywgZ3Vp824sIHB1bnRvLCBldGMuKS4NCg0KDQoNCkVuIGdlbmVyYWwsIGVsIHBhcXVldGUgdGlkeSBlcyB1bmEgaGVycmFtaWVudGEgbXV5IPp0aWwgZW4gbGEgdmlzdWFsaXphY2nzbiBkZSBkYXRvcyBlbiBSU3R1ZGlvLCBvcmRlbmEgbG9zIGRhdG9zIHBhcmEgaGFjZXJsb3MgbeFzIGxlZ2libGVzIGEgdHJhdulzIGRlIGRpc3RpbnRvcyBt6XRvZG9zIHkgZnVuY2lvbmVzLCBjb21vIHBvciBlamVtcGxvICpHYXRoZXIqIHkgKlNwcmVhZCouIA0KDQoNCg0KYGBge3J9DQpHb2xlc19Qb3JfUGFydGlkb190aWR5IDwtIGdhdGhlcihkYXRhID0gR29sZXNfcG9yX3BhcnRpZG8sDQogICAgICAga2V5ID0gIkZlY2hhX2p1Z2FkYSIsDQogICAgICAgdmFsdWUgPSAiZ29sZXNfbWFyY2Fkb3MiKSAlPiUNCnNlcGFyYXRlKEZlY2hhX2p1Z2FkYSwgaW50byA9IGMoIk5vbWJyZSIsICJGZWNoYSIpLCBzZXAgPSAiXyIpDQpgYGANCg0KYGBge3J9DQpnYXRoZXIoZGF0YSA9IEdvbGVzX3Bvcl9wYXJ0aWRvLA0KICAgICAgIGtleSA9ICJGZWNoYV9qdWdhZGEiLA0KICAgICAgIHZhbHVlID0gImdvbGVzX21hcmNhZG9zIikgJT4lDQpzZXBhcmF0ZShGZWNoYV9qdWdhZGEsIGludG8gPSBjKCJOb21icmUiLCAiRmVjaGEiKSwgc2VwID0gIl8iKQ0KYGBgDQoNCg0KDQpFcyBlbGVtZW50YWwgZW4gZXN0ZSBwcm9jZXNvIHRlbmVyIGVuIGN1ZW50YSBpZGVudGlmaWNhciBkZSBsYSBtZWpvciBtYW5lcmEgbGFzIGRpZmVyZW50ZXMgdmFyaWFibGVzIHByZXNlbnRlcyBlbiBsYSB0YWJsYSwgbm8gc/NsbyBhIG1vZG8gaW5maXJtYXRpdm8sIHNpbm8gcXVlIHRhbWJp6W4gcGFyYSBzYWJlciBjdeFsZXMgZGUgZXN0YXMgc29uIG5lY2VzYXJpYXMgcGFyYSBudWVzdHJvIHRyYWJham8uIFBvciBvdHJhIHBhcnRlLCBlcyBuZWNlc2FyaW8gdGVuZXIgZW4gY3VlbnRhIDUgcHVudG9zIHF1ZSBzb24gY2xhdmVzIHBhcmEgbGEgdmlzdWFsaXphY2nzbiBkZSBkYXRvcyBjb24gdGlkeToNCg0KDQoNCi0gSW5jbHVpciB1biBlbmNhYmV6YWRvIGNvbiBlbCBub21icmUgZGUgbGFzIHZhcmlhYmxlcy4NCg0KLSBMb3Mgbm9tYnJlcyBkZSBsYXMgdmFyaWFibGVzIGRlYmVuIHNlciBlbnRlbmRpYmxlcy4gKFBlbmRlamV0ZXMgZXMgbWVqb3IgcXVlIFBvYkluZmFudGlsTWVub3JBMTgpLg0KDQotIEVuIGdlbmVyYWwgbG9zIGRhdG9zIHNlIGRlYmVuIGd1YXJkYXIgZW4gdW4gYXJjaGl2byBwb3IgdGFibGEuDQoNCi0gRXNjcmliaXIgdW4gc2NyaXB0IGNvbiBsYXMgbW9kaWZpY2FjaW9uZXMgcXVlIHNlIGhpY2llcm9uIGEgbG9zIGRhdG9zIGNydWRvcyAocmVwcm9kdWNpYmlsaWRhZCkuDQoNCi0gU2VsZWNjafNuIGRlIHZhcmlhYmxlcywgZGF0b3MgZmFsdGFudGVzLCB0aXBvcyB5IGRldGVjY2nzbiBkZSB2YWxvcmVzIGF07XBpY29zLg0KDQoNCg0KT3RyYSBmb3JtYSBkZSBvcmRlbmFyIHVuYSBkYXRhIGlsZWdpYmxlIG8gZW5yZWRhZGEgZXMgbGEgY2zhc2ljYSBmb3JtYSBkZSAqYXBsaWNhLWNvbWJpbmEqLCBxdWUgY29uc2lzdGUgZW4gcm9tcGVyIHVuIHByb2JsZW1hIGVuIHBlZGF6b3MsIHNlcGFyYXIgdG9kYXMgbGFzIHZhcmlhYmxlcyB5IGRlamFybGFzIGNvbW8gaW5mb3JtYWNp824gcGFyY2VsYWRhLCBwYXJhIGx1ZWdvIHVuaXIgZGUgbGEgbWVqb3IgZm9ybWEgeSBhc+0gb3JkZW5hci4NCg0KDQoNClBhcmEgZXN0byBlcyBuZWNlc2FyaW8gdGVuZXIgZW4gY3VlbnRhIDMgY29uY2VwdG9zOg0KDQoNCg0KLSAqKlNlcGFyYSoqIGxhIGJhc2UgZGUgZGF0b3Mgb3JpZ2luYWwuDQoNCi0gKipBcGxpY2EqKiBmdW5jaW9uZXMgYSBjYWRhIHN1YmNvbmp1bnRvLg0KDQotICoqQ29tYmluYSoqIGxvcyByZXN1bHRhZG9zIGVuIHVuYSBudWV2YSBiYXNlIGRlIGRhdG9zLg0KDQoNCg0KRmluYWxtZW50ZSwgc2kgaGFibGFtb3MgZGUgb3JkZW5hciBkYXRvcyBubyBwb2RlbW9zIGRlamFyIGZ1ZXJhIGEgImRwbHlyIiwgZW4g6Wwgc2UgZW5jdWVudHJhbiB2YXJpYXMgZnVuY2lvbmVzLCBjb21vIHBvciBlamVtcGxvOg0KDQoNCg0KLSAqKkZpbHRlcioqOiBQYXJhIG9idGVuZXIgdW4gc3ViY29uanVudG8gYSBlbGVjY2nzbi4NCg0KLSAqKlNlbGVjdCoqOiBTZWxlY2Npb25hIGNvbHVtbmFzIHNlZ/puIGVsIG5vbWJyZS4NCg0KLSAqKkFycmFuZ2UqKjogUmVvcmRlbmEgZmlsYXMuDQoNCi0gKipNdXRhdGUqKjogQWdyZWdhIG51ZXZhcyB2YXJpYWJsZXMuDQoNCi0gKipTdW1tYXJpc2UqKjogUmVkdWNlIHZhcmlhYmxlcyBhIHZhbG9yZXMgKHByb21lZGlvKS4NCg0KDQpFbiBsYSBzaWd1aWVudGUgdGFibGEgYnVzY2FyZW1vcyBkYXIgdW4gZWplbXBsbyBkZSB1bmEgZGUgbGFzIGZ1bmNpb25lcyBkZSAqZHBseXIqLCBlbiBiYXNlIGEgbGEgdGFibGEgdXRpbGl6YWRhIGNvbiBsb3MgZ29sZXMgcG9yIGp1Z2Fkb3IgeSBmZWNoYS4gRW4gZXN0ZSBjYXNvLCBlamVtcGxpZmljYXJlbW9zIGNvbiBsYSBmdW5jafNuICpGaWx0ZXIqOg0KDQpgYGB7cn0NCmZpbHRlcihHb2xlc19Qb3JfUGFydGlkb190aWR5LCBnb2xlc19tYXJjYWRvcyA9PSAiMCIpDQpgYGANCg0KRW4gbGEgdGFibGEgYW50ZXJpb3IsIGZpbHRyYW1vcyBsb3MgZGF0b3MgcGFyYSBleHRyYWVyIGxhIGluZm9ybWFjafNuIHF1ZSBuZWNlc2l0YW1vcywgZW4gZXN0ZSBjYXNvIHBhcmEgc2FjYXIgZWwgbvptZXJvIGRlIHZlY2VzIHF1ZSB1biBqdWdhZG9yIG5vIGFub3TzIGVuIGFsZ3VuYSBmZWNoYSwgZGFuZG8gY29tbyByZXN1bHRhZG8gcXVlIGVsIGp1Z2Fkb3IgIkx1Y2lhbm8iIG5vIGFub3TzIGVuIGxhIGZlY2hhIG76bWVybyAzLg0KDQpBIGRpZmVyZW5jaWEgZGVsIHBhcXVldGUgdGlkeSwgZW4gZXN0ZSBjYXNvIGdlbmVyYWxtZW50ZSBzZSB0cmFiYWphIGNvbiB1bmEgZGF0YSBvcmRlbmFkYSwgcXVlIHByZXZpYW1lbnRlIG9yZGVuYW1vcyBvIHF1ZSB5YSBzZSBlbmNvbnRyYWJhIGxlZ2libGUgeSD6dGlsIHBhcmEgbnVlc3RybyB0cmFiYWpvLiBTaW4gZW1iYXJnbywgZXN0YXMgZnVuY2lvbmVzIGZ1bmNpb25hbiBkZSBtYW5lcmEgc2ltaWxhciwgcmVjaWJlbiBkZSBlbnRyYWRhIHVuICpkYXRhZnJhbWUqLCBsb3MgYXJndW1lbnRvcyBxdWUgc2lndWVuIGluZGljYW4gcXXpIHRyYWJham8gcmVhbGl6YXJlbW9zIHkgbm9zIGFycm9qYSBsYSBudWV2YSBpbmZvcm1hY2nzbi4NCg0KDQo=