Cargamos las librerías a utilizar

library(tidyverse) #siempre lo tenemos a mano
library(stringr) #para trabajar con strings
library(lubridate) #para trabajar con fechas 

Lubridate: Manejo de fechas

El paquete lubridate está pensado para trabajar con los datos tipo fecha(date) o fecha-hora(datetime) para cambiarles el formato, realizar operaciones y extraer información.

La cheatsheet muestra todas las cosas que se pueden hacer con este paquete

Cambio de formato

Existe una gran cantidad de funciones para realizar esto. La idea general es poder llevar los objetos datetime a un formato común compuesto de los elementos: año, mes, día, hora, minuto y segundo (también se puede setear el huso horario)

fecha  <- "29/09/93 17:35:16"
fecha
[1] "29/09/93 17:35:16"
# Clase de dato
class(fecha)
[1] "character"

Con la función dmy_hms podemos convertir este string a una fecha: estamos indicando que el formato de la fecha es día(d), mes(m), año(y), hora(h), minuto(m) y segundo(s)

fecha  <- dmy_hms(fecha)
fecha
[1] "1993-09-29 17:35:16 UTC"
# Clase de dato
class(fecha)
[1] "POSIXct" "POSIXt" 

Muchas funciones de lubridate operan con esta misma lógica

Otra función para realizar un cambio de formato es parse_date_time. Permite construir objetos datetime a partir de datos más complejos, como por ejemplo cuando aparece el nombre del mes y el año.

En el parámetro x pasamos el dato de la fecha y en el parámetro orders especificamos el orden en el cual se encuentra la información de la fecha

fecha2  <- "Sep-93"
fecha2 <- parse_date_time(fecha2, orders = 'my')
fecha2

Extracción de información

Existen muchas funciones muy sencillas para extraer información de un objeto datetime. Algunas son

# Obtener el año
year(fecha)
#Obtener el semestre
semester(fecha)
#Obtener el trimestre
quarter(fecha)
#Obtener el mes
month(fecha)
# Obtener el día
day(fecha)
# Obtener la fecha
date(fecha)
# Obtener el dia de la semana
wday(fecha)
#Obtener el nombre del día
wday(fecha, label = TRUE) 
#Obtener la hora
hour(fecha) 

Operaciones

Podemos sumar o restarle cualquier período de tiempo a un objeto datetime

# Sumo dos días 
fecha + days(2)
# Resto 1 semana y dos horas
fecha - (weeks(1) + hours(2))

Stringr: manejo de strings

Vamos a usar un paquete muy útil para manejar variables de tipo string, es decir, variables de texto, llamado stringr. Primero vamos a ver algunos de los principales comandos y luego vamos a ver algunos ejemplos un poco más complejos de cómo podemos usar las funciones de este paquete.

Tal como vimos para ggplot2, el paquete stringr cuenta con una cheat sheet que pueden consultar siguiendo este link.

Principales funciones

str_length

Con la función str_length() podemos ver el largo de un string.

string1 <- "abcdefghi"
str_length(string1)

Ojo que cuenta los espacios en blanco como un caracter.

string2 <- "abcd efghi"
str_length(string2)

str_sub

La función str_sub() nos permite extraer los caracteres que se encuentran entre determinadas posiciones. Tiene tres argumentos: el string, el orden del caracter a partir del cual tiene que empezar a extraer y el orden del caracter hasta el cual tiene que extraer.

#quiero el tercer caracter
str_sub(string1,3,3)
#quiero el cuarto y quinto caracter
str_sub(string1,4,5)

Puedo pasarle la posición de los caracteres con un menos para indicar que quiero que cuente de atrás para adelante. Por ejemplo, si quiero que traiga el anteúltimo caracter llamo a la posición como -2.

#quiero la última y anteúltima posición
str_sub(string1,-2,-1)

Otro uso que le podemos dar a este comando es el de reemplazar elementos. Supongamos que quiero reemplazar la última letra por una z.

str_sub(string1,-1,-1) <- "z"
string1

Manejo de espacios en blanco

Es frecuente que aparezcan datos mal cargados o con errores de tipeo que tienen espacios donde no debería haberlos. La función str_trim() permite que nos deshagamos de los espacios en blanco a izquierda, derecha o ambos lados de nuestro string.

string3 <- c("  acelga   ", "brocoli   ",  "   choclo")
#Veamos el string
string3

Quitamos los espacios en blanco a ambos lados con el argumento side=‘both’

str_trim(string3, side = 'both')

Quitamos los espacios en blanco del lado izquierdo con el argumento side=‘left’

str_trim(string3, "left")

Mayúsculas y minúsculas

Existen varias funciones para manipular las mayusculas/minúsculas de nuestros strings. A modo de sugerencia, siempre es convientiente manejarse con todos los caracteres en minúscula o en mayúscula. Esto ayuda a normalizar la información para armar mejor grupos, joinear tablas, etc.

string4 <- "No me gusta el frio"
string4
#llevo todo a minúsculas
str_to_lower(string4)
#llevo todo a mayúsculas
str_to_upper(string4)
#llevo a mayúscula la primer letra de cada palabra
str_to_title(string4)

str_split

La función str_split() nos permite partir un string de acuerdo a algún separador/patron (pattern) que definamos.

#quiero separar todas las letras de mi string
string1_separado <- str_split(string1,pattern = "")
string1_separado

Notemos que esta funcion nos devuelve una lista

class(string1_separado)
# Si queremos acceder al primer elemento de la lista
string1_separado[[1]][1]

Definimos un nuevo string

string5 <- "ab-cd-ef"
string5

Lo separamos por el guion

str_split(string5,pattern="-")

Reemplazar elementos de strings

La función base gsub() nos permite reemplazar parte del string por otra cosa. Las funciones str_replace() y str_replace_all() de stringr nos permiten hacer lo mismo.

str_replace solo reemplaza la primera ocurrencia del patron mientras que str_replace_all() reemplaza todas las ocurrencias

string6 <- "todos los caballos blancos"
string6
#le sacamos los espacios
gsub(pattern = " ", replacement = "", x = string6)
#lo llevamos a lenguaje inclusivo
gsub(pattern = "os", replacement = "xs", x = string6)

Con stringr

# Reemplazamos la primera ocurrencia
str_replace(string = string6, pattern = "os", replacement = "xs")
# Reemplazamos todas las ocurrencias
str_replace_all(string = string6, pattern = "os", replacement = "xs")

Detectar patrones en strings

La función grepl() nos permite encontrar expresiones dentro de nuestros strings. Nos reporta VERDADERO o FALSO de acuerdo a si encuentra la expresión que estamos buscando.

string7 <-c("caño", "baño", "ladrillo")
string7
grepl(pattern = "ñ",x = string7)

La funcion str_detect() de stringr permite hacer lo mismo.

Ejemplo práctico

Ejemplo tiburones

Vamos a ver un ejemplo a partir de una base pública que nos trae información sobre ataques de tiburones en el mundo en distintos momentos. Cada fila corresponde a un ataque.

tiburones <- read.csv("https://raw.githubusercontent.com/dmuba/dmuba.github.io/3005a7a5e8c9db5c188ca22a7b9269c94db8ced7/Practicos/TPs%20Entregables/TP02/Shark_Attack_Data.csv") %>% select(-c(Case.Number.1,Case.Number.2,original.order, X, X.1))
head(tiburones,10)

Vamos a trabajar un poco con la limpieza y la normalización de esta base ya que al juntar datos de distintas fuentes la información no es homogénea por lo que es dificil hacer cualquier tipo de análisis.

Country

Veamos si existen problemas con la variable del país (Country)

# Creamos una lista con los valores de Country para ver si hay algunos problemas
tiburones %>% select(Country) %>% # Seleccionamos la variable del pais
  mutate(Country=as.character(Country)) %>% # Lo convertimos de factor a string
  arrange(Country) %>% # La ordenamos
  distinct() %>% # Nos quedamos con los valores unicos
  as.list() # La convertimos en lista para que sea mas sencilla de ver
$Country
  [1] ""                               " PHILIPPINES"                   " TONGA"                        
  [4] "ADMIRALTY ISLANDS"              "ALGERIA"                        "AMERICAN SAMOA"                
  [7] "ANDAMAN / NICOBAR ISLANDAS"     "ANGOLA"                         "ANTIGUA"                       
 [10] "ARGENTINA"                      "ARUBA"                          "ASIA?"                         
 [13] "ATLANTIC OCEAN"                 "AUSTRALIA"                      "AZORES"                        
 [16] "BAHAMAS"                        "BAHREIN"                        "BANGLADESH"                    
 [19] "BARBADOS"                       "BAY OF BENGAL"                  "BELIZE"                        
 [22] "BERMUDA"                        "Between PORTUGAL & INDIA"       "BRAZIL"                        
 [25] "BRITISH ISLES"                  "BRITISH NEW GUINEA"             "BRITISH VIRGIN ISLANDS"        
 [28] "BRITISH WEST INDIES"            "BURMA"                          "CANADA"                        
 [31] "CAPE VERDE"                     "CARIBBEAN SEA"                  "CAYMAN ISLANDS"                
 [34] "CENTRAL PACIFIC"                "CEYLON (SRI LANKA)"             "CHILE"                         
 [37] "CHINA"                          "Coast of AFRICA"                "COLUMBIA"                      
 [40] "COOK ISLANDS"                   "COSTA RICA"                     "CRETE"                         
 [43] "CROATIA"                        "CUBA"                           "CURACAO"                       
 [46] "CYPRUS"                         "DIEGO GARCIA"                   "DJIBOUTI"                      
 [49] "DOMINICAN REPUBLIC"             "ECUADOR"                        "EGYPT"                         
 [52] "EGYPT "                         "EGYPT / ISRAEL"                 "EL SALVADOR"                   
 [55] "ENGLAND"                        "EQUATORIAL GUINEA / CAMEROON"   "FALKLAND ISLANDS"              
 [58] "FEDERATED STATES OF MICRONESIA" "Fiji"                           "FIJI"                          
 [61] "FRANCE"                         "FRENCH POLYNESIA"               "GABON"                         
 [64] "GEORGIA"                        "GHANA"                          "GRAND CAYMAN"                  
 [67] "GREECE"                         "GREENLAND"                      "GRENADA"                       
 [70] "GUAM"                           "GUATEMALA"                      "GUINEA"                        
 [73] "GULF OF ADEN"                   "GUYANA"                         "HAITI"                         
 [76] "HONDURAS"                       "HONG KONG"                      "ICELAND"                       
 [79] "INDIA"                          "INDIAN OCEAN"                   "INDIAN OCEAN?"                 
 [82] "INDONESIA"                      "IRAN"                           "IRAN / IRAQ"                   
 [85] "IRAQ"                           "IRELAND"                        "ISRAEL"                        
 [88] "ITALY"                          "ITALY / CROATIA"                "JAMAICA"                       
 [91] "JAPAN"                          "JAVA"                           "JOHNSTON ISLAND"               
 [94] "KENYA"                          "KIRIBATI"                       "KOREA"                         
 [97] "KUWAIT"                         "LEBANON"                        "LIBERIA"                       
[100] "LIBYA"                          "MADAGASCAR"                     "MALAYSIA"                      
[103] "MALDIVE ISLANDS"                "MALTA"                          "MARSHALL ISLANDS"              
[106] "MARTINIQUE"                     "MAURITIUS"                      "MAYOTTE"                       
[109] "MEDITERRANEAN SEA"              "MEDITERRANEAN SEA?"             "MEXICO"                        
[112] "MEXICO "                        "MICRONESIA"                     "MID ATLANTIC OCEAN"            
[115] "MID-PACIFC OCEAN"               "MONACO"                         "MONTENEGRO"                    
[118] "MOZAMBIQUE"                     "NAMIBIA"                        "NETHERLANDS ANTILLES"          
[121] "NEVIS"                          "NEW BRITAIN"                    "NEW CALEDONIA"                 
[124] "NEW GUINEA"                     "NEW ZEALAND"                    "NICARAGUA"                     
[127] "NICARAGUA "                     "NIGERIA"                        "NORTH ATLANTIC OCEAN"          
[130] "NORTH ATLANTIC OCEAN "          "NORTH PACIFIC OCEAN"            "NORTH SEA"                     
[133] "NORTHERN ARABIAN SEA"           "NORTHERN MARIANA ISLANDS"       "NORWAY"                        
[136] "OCEAN"                          "OKINAWA"                        "PACIFIC OCEAN"                 
[139] "PACIFIC OCEAN "                 "PALAU"                          "PALESTINIAN TERRITORIES"       
[142] "PANAMA"                         "PAPUA NEW GUINEA"               "PARAGUAY"                      
[145] "PERSIAN GULF"                   "PHILIPPINES"                    "PORTUGAL"                      
[148] "PUERTO RICO"                    "RED SEA"                        "RED SEA / INDIAN OCEAN"        
[151] "RED SEA?"                       "REUNION"                        "RUSSIA"                        
[154] "SAMOA"                          "SAN DOMINGO"                    "SAUDI ARABIA"                  
[157] "SCOTLAND"                       "SENEGAL"                        "Seychelles"                    
[160] "SEYCHELLES"                     "Sierra Leone"                   "SIERRA LEONE"                  
[163] "SINGAPORE"                      "SLOVENIA"                       "SOLOMON ISLANDS"               
[166] "SOLOMON ISLANDS / VANUATU"      "SOMALIA"                        "SOUTH AFRICA"                  
[169] "SOUTH ATLANTIC OCEAN"           "SOUTH CHINA SEA"                "SOUTH KOREA"                   
[172] "SOUTH PACIFIC OCEAN"            "SOUTHWEST PACIFIC OCEAN"        "SPAIN"                         
[175] "SRI LANKA"                      "St Helena"                      "ST. MAARTIN"                   
[178] "ST. MARTIN"                     "SUDAN"                          "SUDAN?"                        
[181] "SWEDEN"                         "SYRIA"                          "TAIWAN"                        
[184] "TANZANIA"                       "TASMAN SEA"                     "THAILAND"                      
[187] "THE BALKANS"                    "TONGA"                          "TRINIDAD & TOBAGO"             
[190] "TUNISIA"                        "TURKEY"                         "TURKS & CAICOS"                
[193] "TUVALU"                         "UNITED ARAB EMIRATES"           "UNITED ARAB EMIRATES (UAE)"    
[196] "UNITED KINGDOM"                 "URUGUAY"                        "USA"                           
[199] "VANUATU"                        "VENEZUELA"                      "VIETNAM"                       
[202] "WESTERN SAMOA"                  "YEMEN"                          "YEMEN "                        
[205] "YUGOSLAVIA"                    

Hay varios problemas, pero veamos dos:

  1. Hay algunos nombres que no están en mayúscula
  2. Hay algunos nombres que tienen espacios en blanco a izquierda y derecha

Llevamos los nombres a mayúscula

tiburones <- tiburones %>% mutate(pais=str_to_upper(Country))
head(tiburones, 10)

Quitamos los espacios en blanco a izquierda y derecha

tiburones <- tiburones %>% mutate(pais=str_trim(pais, side="both"))
tiburones %>% select(pais) %>% # Seleccionamos la variable del pais
  #mutate(Country=as.character(Country)) %>% # Lo convertimos de factor a string
  arrange(pais) %>% # La ordenamos
  distinct() %>% # Nos quedamos con los valores unicos
  as.list() # La convertimos en lista para que sea mas sencilla de ver
$pais
  [1] ""                               "ADMIRALTY ISLANDS"              "ALGERIA"                       
  [4] "AMERICAN SAMOA"                 "ANDAMAN / NICOBAR ISLANDAS"     "ANGOLA"                        
  [7] "ANTIGUA"                        "ARGENTINA"                      "ARUBA"                         
 [10] "ASIA?"                          "ATLANTIC OCEAN"                 "AUSTRALIA"                     
 [13] "AZORES"                         "BAHAMAS"                        "BAHREIN"                       
 [16] "BANGLADESH"                     "BARBADOS"                       "BAY OF BENGAL"                 
 [19] "BELIZE"                         "BERMUDA"                        "BETWEEN PORTUGAL & INDIA"      
 [22] "BRAZIL"                         "BRITISH ISLES"                  "BRITISH NEW GUINEA"            
 [25] "BRITISH VIRGIN ISLANDS"         "BRITISH WEST INDIES"            "BURMA"                         
 [28] "CANADA"                         "CAPE VERDE"                     "CARIBBEAN SEA"                 
 [31] "CAYMAN ISLANDS"                 "CENTRAL PACIFIC"                "CEYLON (SRI LANKA)"            
 [34] "CHILE"                          "CHINA"                          "COAST OF AFRICA"               
 [37] "COLUMBIA"                       "COOK ISLANDS"                   "COSTA RICA"                    
 [40] "CRETE"                          "CROATIA"                        "CUBA"                          
 [43] "CURACAO"                        "CYPRUS"                         "DIEGO GARCIA"                  
 [46] "DJIBOUTI"                       "DOMINICAN REPUBLIC"             "ECUADOR"                       
 [49] "EGYPT"                          "EGYPT / ISRAEL"                 "EL SALVADOR"                   
 [52] "ENGLAND"                        "EQUATORIAL GUINEA / CAMEROON"   "FALKLAND ISLANDS"              
 [55] "FEDERATED STATES OF MICRONESIA" "FIJI"                           "FRANCE"                        
 [58] "FRENCH POLYNESIA"               "GABON"                          "GEORGIA"                       
 [61] "GHANA"                          "GRAND CAYMAN"                   "GREECE"                        
 [64] "GREENLAND"                      "GRENADA"                        "GUAM"                          
 [67] "GUATEMALA"                      "GUINEA"                         "GULF OF ADEN"                  
 [70] "GUYANA"                         "HAITI"                          "HONDURAS"                      
 [73] "HONG KONG"                      "ICELAND"                        "INDIA"                         
 [76] "INDIAN OCEAN"                   "INDIAN OCEAN?"                  "INDONESIA"                     
 [79] "IRAN"                           "IRAN / IRAQ"                    "IRAQ"                          
 [82] "IRELAND"                        "ISRAEL"                         "ITALY"                         
 [85] "ITALY / CROATIA"                "JAMAICA"                        "JAPAN"                         
 [88] "JAVA"                           "JOHNSTON ISLAND"                "KENYA"                         
 [91] "KIRIBATI"                       "KOREA"                          "KUWAIT"                        
 [94] "LEBANON"                        "LIBERIA"                        "LIBYA"                         
 [97] "MADAGASCAR"                     "MALAYSIA"                       "MALDIVE ISLANDS"               
[100] "MALTA"                          "MARSHALL ISLANDS"               "MARTINIQUE"                    
[103] "MAURITIUS"                      "MAYOTTE"                        "MEDITERRANEAN SEA"             
[106] "MEDITERRANEAN SEA?"             "MEXICO"                         "MICRONESIA"                    
[109] "MID ATLANTIC OCEAN"             "MID-PACIFC OCEAN"               "MONACO"                        
[112] "MONTENEGRO"                     "MOZAMBIQUE"                     "NAMIBIA"                       
[115] "NETHERLANDS ANTILLES"           "NEVIS"                          "NEW BRITAIN"                   
[118] "NEW CALEDONIA"                  "NEW GUINEA"                     "NEW ZEALAND"                   
[121] "NICARAGUA"                      "NIGERIA"                        "NORTH ATLANTIC OCEAN"          
[124] "NORTH PACIFIC OCEAN"            "NORTH SEA"                      "NORTHERN ARABIAN SEA"          
[127] "NORTHERN MARIANA ISLANDS"       "NORWAY"                         "OCEAN"                         
[130] "OKINAWA"                        "PACIFIC OCEAN"                  "PALAU"                         
[133] "PALESTINIAN TERRITORIES"        "PANAMA"                         "PAPUA NEW GUINEA"              
[136] "PARAGUAY"                       "PERSIAN GULF"                   "PHILIPPINES"                   
[139] "PORTUGAL"                       "PUERTO RICO"                    "RED SEA"                       
[142] "RED SEA / INDIAN OCEAN"         "RED SEA?"                       "REUNION"                       
[145] "RUSSIA"                         "SAMOA"                          "SAN DOMINGO"                   
[148] "SAUDI ARABIA"                   "SCOTLAND"                       "SENEGAL"                       
[151] "SEYCHELLES"                     "SIERRA LEONE"                   "SINGAPORE"                     
[154] "SLOVENIA"                       "SOLOMON ISLANDS"                "SOLOMON ISLANDS / VANUATU"     
[157] "SOMALIA"                        "SOUTH AFRICA"                   "SOUTH ATLANTIC OCEAN"          
[160] "SOUTH CHINA SEA"                "SOUTH KOREA"                    "SOUTH PACIFIC OCEAN"           
[163] "SOUTHWEST PACIFIC OCEAN"        "SPAIN"                          "SRI LANKA"                     
[166] "ST HELENA"                      "ST. MAARTIN"                    "ST. MARTIN"                    
[169] "SUDAN"                          "SUDAN?"                         "SWEDEN"                        
[172] "SYRIA"                          "TAIWAN"                         "TANZANIA"                      
[175] "TASMAN SEA"                     "THAILAND"                       "THE BALKANS"                   
[178] "TONGA"                          "TRINIDAD & TOBAGO"              "TUNISIA"                       
[181] "TURKEY"                         "TURKS & CAICOS"                 "TUVALU"                        
[184] "UNITED ARAB EMIRATES"           "UNITED ARAB EMIRATES (UAE)"     "UNITED KINGDOM"                
[187] "URUGUAY"                        "USA"                            "VANUATU"                       
[190] "VENEZUELA"                      "VIETNAM"                        "WESTERN SAMOA"                 
[193] "YEMEN"                          "YUGOSLAVIA"                    

Date

Vamos a empezar analizando la variable Date de nuestro dataset. Primero llevamos esta variable a un pequeño dataset aparte y llevamos la variable al tipo character para poder manejarla como un string.

Date<-tiburones %>% select(Case.Number, Date) %>% # Seleccionamos las variables de numero de caso y fecha
                    mutate(Date=as.character(Date)) # Tranformamos la fecha en string
glimpse(Date)

Vemos que la variable Date viene en muchos casos con la palabra Reported lo cual nos impide que podamos tratar esa expresión como fecha usando las herramientas que vimos en la sección de lubridate.

Date <- Date %>% mutate(date_clean1= str_replace_all(string = Date, pattern =  "Reported ", replacement = ""))
head(Date,10)

Time

Vamos ahora a ver el caso de la variable Time. Vamos a proceder igual que con la variable Date, creando un pequeño dataset para normalizar esta variable.

#traemos la variable que nos interesa
Time <- tiburones %>% select(Time)
#la llevamos a tipo character para trabajarla como string
Time <- Time %>% mutate(Time=as.character(Time))
#borro esta entrada porque tiene un dato raro que no nos deja trabajar 
Time[1545,] <- ""
#llevamos todo a minúsculas (con otra función que también hace eso)
Time<-Time %>% mutate(Time=tolower(Time))
Time

Nuestro objetivo es llevar las horas a una variable categórica con los valores mañana, tarde y noche. Para eso por un lado vamos a tener que extraer la hora de las variables que la tienen cargada en forma númerica para luego agruparlas en esas tres categorías, y por el otro lado normalizar la forma categórica dada en inglés que actualmente tiene cuatro categorías.

Empecemos trabajando con las entradas que tienen los valores dados en números. Primero vamos a ver que entradas tienen h y vamos a generar una columna con el largo del string.

Time <- Time %>% mutate(tiene_h = grepl(pattern = "h",x = Time),
                        largo=str_length(Time))
Time

Ahora creamos una variable que nos va a decir si se trata de un caso con la hora dada en números. Para detectar estos casos, el string tiene que contener la letra h y tener 5 caracteres.

Time = Time %>% mutate(es_hora = case_when(tiene_h==TRUE & largo==5 ~ "si",
                                           tiene_h==FALSE | largo!=5 ~ "no"))
Time

Ahora, si se trata de una entrada con el formato de hora, vamos a traer la primera y segunda posición que corresponden a la hora.

Time = Time %>% mutate(hora = case_when(es_hora =="si" ~ substr(Time,1,2)),
                       hora = as.numeric(hora))
Time

Ahora vamos a llevar los valores noméricos continuos a las variables discretas que mencionamos y vamos a llevar las variables en inglés a las variables en castellano.

Time = Time %>% mutate(hora_estandar = case_when(grepl("afternoon",Time)==TRUE ~ "tarde",
                                                 grepl("day",Time)==TRUE ~ "tarde",
                                                 grepl("night",Time)==TRUE ~ "noche",
                                                 grepl("morning",Time)==TRUE ~ "mañana",
                                                 hora>5 & hora<12 ~ "mañana",
                                                 hora>11 & hora<19 ~ "tarde",
                                                 hora<6 | hora>18 ~ "noche"))
# Reemplazamos los NA por "hora indefinida" 
Time <- Time %>% replace_na(list(hora_estandar="hora indefinida"))
Time

Fecha con Lubridate

# Seleccionamos algunas variables
tiburones <- tiburones %>% select(Case.Number, Type,Date, pais)
# Hacemos la limpieza de la fecha como vimos más arriba
tiburones <- tiburones %>% mutate(date_clean1= str_replace_all(string = Date, pattern =  "Reported ", replacement = ""))
glimpse(tiburones)

Transformamos la variable fecha de un string a una fecha

tiburones <- tiburones %>% mutate(fecha= dmy(date_clean1))

El mensaje indica que no pudo convertir a fecha 889 registros.

Extraemos variables de la fecha

tiburones <- tiburones %>% mutate(año = year(fecha), #Obtener el año
                                  semestre=semester(fecha), # Obtener el semestre
                                  trimestre=quarter(fecha),#Obtener el trimestre 
                                  mes=month(fecha,label = TRUE), #Obtener el nombre del mes
                                  dia=day(fecha),# Obtener el día
                                  dia_semana=wday(fecha, label = TRUE) #Obtener el nombre del día
                                  )

glimpse(tiburones)

Algunos gráficos

Filtramos los registros y nos quedamos con los ataques desde 1800

tiburones_filtro <- tiburones %>% filter(año >=1800)

Veamos la evolución por año de los ataques de tiburones

ggplot(tiburones_filtro, aes(año)) +
  geom_line(stat = "count") +
  geom_point(stat='count') +
  theme_bw() +
  labs(title='Evolucion ataques de tiburones', x='Año', y='Ataques')

Seleccionamos a dos paises con muchos ataques. Recordemos que habiamos hecho algunos procedimientos de normalización sobre esta variable

tiburones_aus_usa <- tiburones_filtro %>% filter(pais %in% c("AUSTRALIA","USA")) 

Observemos el ciclo anual de ataques de tiburones en estos paises

ggplot(tiburones_aus_usa, aes(mes,color=pais, group=pais)) +
  geom_line(stat = "count") +
  geom_point(stat='count') +
  theme_bw() +
  labs(title='Ciclo anual ataques de tiburones', x='Mes', y='Ataques')
LS0tCnRpdGxlOiBDbGFzZSA1CmF1dGhvcjogIkJhcnJpb2xhIHkgRG90dGEgIgpzdWJ0aXRsZTogU3RyaW5ncyB5IEZlY2hhcwpkYXRlOiAiMTYvNy8yMDE5IgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazogCiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZSAKLS0tCjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+CmRpdi5tYWluLWNvbnRhaW5lciB7CiAgbWF4LXdpZHRoOiAxNjAwcHg7CiAgbWFyZ2luLWxlZnQ6IGF1dG87CiAgbWFyZ2luLXJpZ2h0OiBhdXRvOwp9Cjwvc3R5bGU+CgojIyMjIENhcmdhbW9zIGxhcyBsaWJyZXLDrWFzIGEgdXRpbGl6YXIKYGBge3IsIG1lc3NhZ2U9RkFMU0V9CmxpYnJhcnkodGlkeXZlcnNlKSAjc2llbXByZSBsbyB0ZW5lbW9zIGEgbWFubwpsaWJyYXJ5KHN0cmluZ3IpICNwYXJhIHRyYWJhamFyIGNvbiBzdHJpbmdzCmxpYnJhcnkobHVicmlkYXRlKSAjcGFyYSB0cmFiYWphciBjb24gZmVjaGFzIApgYGAKCiMgTHVicmlkYXRlOiBNYW5lam8gZGUgZmVjaGFzCkVsIHBhcXVldGUgbHVicmlkYXRlIGVzdMOhIHBlbnNhZG8gcGFyYSB0cmFiYWphciBjb24gbG9zIGRhdG9zIHRpcG8gZmVjaGEoZGF0ZSkgbyBmZWNoYS1ob3JhKGRhdGV0aW1lKSBwYXJhIGNhbWJpYXJsZXMgZWwgZm9ybWF0bywgcmVhbGl6YXIgb3BlcmFjaW9uZXMgeSBleHRyYWVyIGluZm9ybWFjacOzbi4KCkxhIFtjaGVhdHNoZWV0XShodHRwczovL3Jhd2dpdC5jb20vcnN0dWRpby9jaGVhdHNoZWV0cy9tYXN0ZXIvbHVicmlkYXRlLnBkZikgbXVlc3RyYSB0b2RhcyBsYXMgY29zYXMgcXVlIHNlIHB1ZWRlbiBoYWNlciBjb24gZXN0ZSBwYXF1ZXRlCgojIyMgQ2FtYmlvIGRlIGZvcm1hdG8KCkV4aXN0ZSB1bmEgZ3JhbiBjYW50aWRhZCBkZSBmdW5jaW9uZXMgcGFyYSByZWFsaXphciBlc3RvLiBMYSBpZGVhIGdlbmVyYWwgZXMgcG9kZXIgbGxldmFyIGxvcyBvYmpldG9zIGRhdGV0aW1lIGEgdW4gZm9ybWF0byBjb23Dum4gY29tcHVlc3RvIGRlIGxvcyBlbGVtZW50b3M6IGHDsW8sIG1lcywgZMOtYSwgaG9yYSwgbWludXRvIHkgc2VndW5kbyAodGFtYmnDqW4gc2UgcHVlZGUgc2V0ZWFyIGVsIGh1c28gaG9yYXJpbykKCmBgYHtyfQpmZWNoYSAgPC0gIjI5LzA5LzkzIDE3OjM1OjE2IgpmZWNoYQojIENsYXNlIGRlIGRhdG8KY2xhc3MoZmVjaGEpCmBgYAoKQ29uIGxhIGZ1bmNpw7NuIGRteV9obXMgcG9kZW1vcyBjb252ZXJ0aXIgZXN0ZSBzdHJpbmcgYSB1bmEgZmVjaGE6IGVzdGFtb3MgaW5kaWNhbmRvIHF1ZSBlbCBmb3JtYXRvIGRlIGxhIGZlY2hhIGVzIGTDrWEoZCksIG1lcyhtKSwgYcOxbyh5KSwgaG9yYShoKSwgbWludXRvKG0pIHkgc2VndW5kbyhzKQoKYGBge3J9CmZlY2hhICA8LSBkbXlfaG1zKGZlY2hhKQpmZWNoYQojIENsYXNlIGRlIGRhdG8KY2xhc3MoZmVjaGEpCmBgYApNdWNoYXMgZnVuY2lvbmVzIGRlIGx1YnJpZGF0ZSBvcGVyYW4gY29uIGVzdGEgbWlzbWEgbMOzZ2ljYQoKT3RyYSBmdW5jacOzbiBwYXJhIHJlYWxpemFyIHVuIGNhbWJpbyBkZSBmb3JtYXRvIGVzICpwYXJzZV9kYXRlX3RpbWUqLiBQZXJtaXRlIGNvbnN0cnVpciBvYmpldG9zIGRhdGV0aW1lIGEgcGFydGlyIGRlIGRhdG9zIG3DoXMgY29tcGxlam9zLCBjb21vIHBvciBlamVtcGxvIGN1YW5kbyBhcGFyZWNlIGVsIG5vbWJyZSBkZWwgbWVzIHkgZWwgYcOxby4KCkVuIGVsIHBhcsOhbWV0cm8gKngqIHBhc2Ftb3MgZWwgZGF0byBkZSBsYSBmZWNoYSB5IGVuIGVsIHBhcsOhbWV0cm8gKm9yZGVycyogZXNwZWNpZmljYW1vcyBlbCBvcmRlbiBlbiBlbCBjdWFsIHNlIGVuY3VlbnRyYSBsYSBpbmZvcm1hY2nDs24gZGUgbGEgZmVjaGEKCmBgYHtyfQpmZWNoYTIgIDwtICJTZXAtOTMiCmZlY2hhMiA8LSBwYXJzZV9kYXRlX3RpbWUoZmVjaGEyLCBvcmRlcnMgPSAnbXknKQpmZWNoYTIKYGBgCgojIyMgRXh0cmFjY2nDs24gZGUgaW5mb3JtYWNpw7NuCgpFeGlzdGVuIG11Y2hhcyBmdW5jaW9uZXMgbXV5IHNlbmNpbGxhcyBwYXJhIGV4dHJhZXIgaW5mb3JtYWNpw7NuIGRlIHVuIG9iamV0byBkYXRldGltZS4gQWxndW5hcyBzb24KCmBgYHtyfQojIE9idGVuZXIgZWwgYcOxbwp5ZWFyKGZlY2hhKQojT2J0ZW5lciBlbCBzZW1lc3RyZQpzZW1lc3RlcihmZWNoYSkKI09idGVuZXIgZWwgdHJpbWVzdHJlCnF1YXJ0ZXIoZmVjaGEpCiNPYnRlbmVyIGVsIG1lcwptb250aChmZWNoYSkKIyBPYnRlbmVyIGVsIGTDrWEKZGF5KGZlY2hhKQojIE9idGVuZXIgbGEgZmVjaGEKZGF0ZShmZWNoYSkKIyBPYnRlbmVyIGVsIGRpYSBkZSBsYSBzZW1hbmEKd2RheShmZWNoYSkKI09idGVuZXIgZWwgbm9tYnJlIGRlbCBkw61hCndkYXkoZmVjaGEsIGxhYmVsID0gVFJVRSkgCiNPYnRlbmVyIGxhIGhvcmEKaG91cihmZWNoYSkgCmBgYAoKIyMjIE9wZXJhY2lvbmVzCgpQb2RlbW9zIHN1bWFyIG8gcmVzdGFybGUgY3VhbHF1aWVyIHBlcsOtb2RvIGRlIHRpZW1wbyBhIHVuIG9iamV0byBkYXRldGltZQoKYGBge3J9CiMgU3VtbyBkb3MgZMOtYXMgCmZlY2hhICsgZGF5cygyKQojIFJlc3RvIDEgc2VtYW5hIHkgZG9zIGhvcmFzCmZlY2hhIC0gKHdlZWtzKDEpICsgaG91cnMoMikpCmBgYAoKIyBTdHJpbmdyOiBtYW5lam8gZGUgc3RyaW5ncwoKVmFtb3MgYSB1c2FyIHVuIHBhcXVldGUgbXV5IMO6dGlsIHBhcmEgbWFuZWphciB2YXJpYWJsZXMgZGUgdGlwbyBgc3RyaW5nYCwgZXMgZGVjaXIsIHZhcmlhYmxlcyBkZSB0ZXh0bywgbGxhbWFkbyBgc3RyaW5ncmAuIFByaW1lcm8gdmFtb3MgYSB2ZXIgYWxndW5vcyBkZSBsb3MgcHJpbmNpcGFsZXMgY29tYW5kb3MgeSBsdWVnbyB2YW1vcyBhIHZlciBhbGd1bm9zIGVqZW1wbG9zIHVuIHBvY28gbcOhcyBjb21wbGVqb3MgZGUgY8OzbW8gcG9kZW1vcyB1c2FyIGxhcyBmdW5jaW9uZXMgZGUgZXN0ZSBwYXF1ZXRlLiAKClRhbCBjb21vIHZpbW9zIHBhcmEgYGdncGxvdDJgLCBlbCBwYXF1ZXRlIGBzdHJpbmdyYCBjdWVudGEgY29uIHVuYSBjaGVhdCBzaGVldCBxdWUgcHVlZGVuIGNvbnN1bHRhciBzaWd1aWVuZG8gZXN0ZSBbbGlua10oaHR0cDovL2VkcnViLmluL0NoZWF0U2hlZXRzL2NoZWF0U2hlZXRTdHJpbmdyLnBkZikuCgojIyBQcmluY2lwYWxlcyBmdW5jaW9uZXMKCiMjIyBzdHJfbGVuZ3RoCgpDb24gbGEgZnVuY2nDs24gYHN0cl9sZW5ndGgoKWAgcG9kZW1vcyB2ZXIgZWwgbGFyZ28gZGUgdW4gc3RyaW5nLgpgYGB7cn0Kc3RyaW5nMSA8LSAiYWJjZGVmZ2hpIgpzdHJfbGVuZ3RoKHN0cmluZzEpCmBgYAoKT2pvIHF1ZSBjdWVudGEgbG9zIGVzcGFjaW9zIGVuIGJsYW5jbyBjb21vIHVuIGNhcmFjdGVyLgpgYGB7cn0Kc3RyaW5nMiA8LSAiYWJjZCBlZmdoaSIKc3RyX2xlbmd0aChzdHJpbmcyKQpgYGAKCiMjIyBzdHJfc3ViCgpMYSBmdW5jacOzbiBgc3RyX3N1YigpYCBub3MgcGVybWl0ZSBleHRyYWVyIGxvcyBjYXJhY3RlcmVzIHF1ZSBzZSBlbmN1ZW50cmFuIGVudHJlIGRldGVybWluYWRhcyBwb3NpY2lvbmVzLiBUaWVuZSB0cmVzIGFyZ3VtZW50b3M6IGVsIHN0cmluZywgZWwgb3JkZW4gZGVsIGNhcmFjdGVyIGEgcGFydGlyIGRlbCBjdWFsIHRpZW5lIHF1ZSBlbXBlemFyIGEgZXh0cmFlciB5IGVsIG9yZGVuIGRlbCBjYXJhY3RlciBoYXN0YSBlbCBjdWFsIHRpZW5lIHF1ZSBleHRyYWVyLgoKYGBge3J9CiNxdWllcm8gZWwgdGVyY2VyIGNhcmFjdGVyCnN0cl9zdWIoc3RyaW5nMSwzLDMpCmBgYAoKYGBge3J9CiNxdWllcm8gZWwgY3VhcnRvIHkgcXVpbnRvIGNhcmFjdGVyCnN0cl9zdWIoc3RyaW5nMSw0LDUpCmBgYAoKUHVlZG8gcGFzYXJsZSBsYSBwb3NpY2nDs24gZGUgbG9zIGNhcmFjdGVyZXMgY29uIHVuIG1lbm9zIHBhcmEgaW5kaWNhciBxdWUgcXVpZXJvIHF1ZSBjdWVudGUgZGUgYXRyw6FzIHBhcmEgYWRlbGFudGUuIFBvciBlamVtcGxvLCBzaSBxdWllcm8gcXVlIHRyYWlnYSBlbCBhbnRlw7psdGltbyBjYXJhY3RlciBsbGFtbyBhIGxhIHBvc2ljacOzbiBjb21vIGAtMmAuCgpgYGB7cn0KI3F1aWVybyBsYSDDumx0aW1hIHkgYW50ZcO6bHRpbWEgcG9zaWNpw7NuCnN0cl9zdWIoc3RyaW5nMSwtMiwtMSkKYGBgCgpPdHJvIHVzbyBxdWUgbGUgcG9kZW1vcyBkYXIgYSBlc3RlIGNvbWFuZG8gZXMgZWwgZGUgcmVlbXBsYXphciBlbGVtZW50b3MuIFN1cG9uZ2Ftb3MgcXVlIHF1aWVybyByZWVtcGxhemFyIGxhIMO6bHRpbWEgbGV0cmEgcG9yIHVuYSB6LgpgYGB7cn0Kc3RyX3N1YihzdHJpbmcxLC0xLC0xKSA8LSAieiIKc3RyaW5nMQpgYGAKCiMjIyBNYW5lam8gZGUgZXNwYWNpb3MgZW4gYmxhbmNvCgpFcyBmcmVjdWVudGUgcXVlIGFwYXJlemNhbiBkYXRvcyBtYWwgY2FyZ2Fkb3MgbyBjb24gZXJyb3JlcyBkZSB0aXBlbyBxdWUgdGllbmVuIGVzcGFjaW9zIGRvbmRlIG5vIGRlYmVyw61hIGhhYmVybG9zLiBMYSBmdW5jacOzbiBgc3RyX3RyaW0oKWAgcGVybWl0ZSBxdWUgbm9zIGRlc2hhZ2Ftb3MgZGUgbG9zIGVzcGFjaW9zIGVuIGJsYW5jbyBhIGl6cXVpZXJkYSwgZGVyZWNoYSBvIGFtYm9zIGxhZG9zIGRlIG51ZXN0cm8gc3RyaW5nLgoKYGBge3J9CnN0cmluZzMgPC0gYygiICBhY2VsZ2EgICAiLCAiYnJvY29saSAgICIsICAiICAgY2hvY2xvIikKI1ZlYW1vcyBlbCBzdHJpbmcKc3RyaW5nMwpgYGAKUXVpdGFtb3MgbG9zIGVzcGFjaW9zIGVuIGJsYW5jbyBhIGFtYm9zIGxhZG9zIGNvbiBlbCBhcmd1bWVudG8gc2lkZT0nYm90aCcKCmBgYHtyfQpzdHJfdHJpbShzdHJpbmczLCBzaWRlID0gJ2JvdGgnKQpgYGAKClF1aXRhbW9zIGxvcyBlc3BhY2lvcyBlbiBibGFuY28gZGVsIGxhZG8gaXpxdWllcmRvIGNvbiBlbCBhcmd1bWVudG8gc2lkZT0nbGVmdCcKYGBge3J9CnN0cl90cmltKHN0cmluZzMsICJsZWZ0IikKYGBgCgojIyMgTWF5w7pzY3VsYXMgeSBtaW7DunNjdWxhcwoKRXhpc3RlbiB2YXJpYXMgZnVuY2lvbmVzIHBhcmEgbWFuaXB1bGFyIGxhcyBtYXl1c2N1bGFzL21pbsO6c2N1bGFzIGRlIG51ZXN0cm9zIHN0cmluZ3MuIEEgbW9kbyBkZSBzdWdlcmVuY2lhLCBzaWVtcHJlIGVzIGNvbnZpZW50aWVudGUgbWFuZWphcnNlIGNvbiB0b2RvcyBsb3MgY2FyYWN0ZXJlcyBlbiBtaW7DunNjdWxhIG8gZW4gbWF5w7pzY3VsYS4gRXN0byBheXVkYSBhIG5vcm1hbGl6YXIgbGEgaW5mb3JtYWNpw7NuIHBhcmEgYXJtYXIgbWVqb3IgZ3J1cG9zLCBqb2luZWFyIHRhYmxhcywgZXRjLgoKYGBge3J9CnN0cmluZzQgPC0gIk5vIG1lIGd1c3RhIGVsIGZyaW8iCnN0cmluZzQKYGBgCmBgYHtyfQojbGxldm8gdG9kbyBhIG1pbsO6c2N1bGFzCnN0cl90b19sb3dlcihzdHJpbmc0KQpgYGAKYGBge3J9CiNsbGV2byB0b2RvIGEgbWF5w7pzY3VsYXMKc3RyX3RvX3VwcGVyKHN0cmluZzQpCmBgYApgYGB7cn0KI2xsZXZvIGEgbWF5w7pzY3VsYSBsYSBwcmltZXIgbGV0cmEgZGUgY2FkYSBwYWxhYnJhCnN0cl90b190aXRsZShzdHJpbmc0KQpgYGAKCiMjIyBzdHJfc3BsaXQKCkxhIGZ1bmNpw7NuIGBzdHJfc3BsaXQoKWAgbm9zIHBlcm1pdGUgcGFydGlyIHVuIHN0cmluZyBkZSBhY3VlcmRvIGEgYWxnw7puIHNlcGFyYWRvci9wYXRyb24gKHBhdHRlcm4pIHF1ZSBkZWZpbmFtb3MuCgpgYGB7cn0KI3F1aWVybyBzZXBhcmFyIHRvZGFzIGxhcyBsZXRyYXMgZGUgbWkgc3RyaW5nCnN0cmluZzFfc2VwYXJhZG8gPC0gc3RyX3NwbGl0KHN0cmluZzEscGF0dGVybiA9ICIiKQpzdHJpbmcxX3NlcGFyYWRvCmBgYAoKTm90ZW1vcyBxdWUgZXN0YSBmdW5jaW9uIG5vcyBkZXZ1ZWx2ZSB1bmEgbGlzdGEKCmBgYHtyfQpjbGFzcyhzdHJpbmcxX3NlcGFyYWRvKQojIFNpIHF1ZXJlbW9zIGFjY2VkZXIgYWwgcHJpbWVyIGVsZW1lbnRvIGRlIGxhIGxpc3RhCnN0cmluZzFfc2VwYXJhZG9bWzFdXVsxXQpgYGAKCkRlZmluaW1vcyB1biBudWV2byBzdHJpbmcKCmBgYHtyfQpzdHJpbmc1IDwtICJhYi1jZC1lZiIKc3RyaW5nNQpgYGAKCkxvIHNlcGFyYW1vcyBwb3IgZWwgZ3Vpb24KCmBgYHtyfQpzdHJfc3BsaXQoc3RyaW5nNSxwYXR0ZXJuPSItIikKYGBgCgojIyMgUmVlbXBsYXphciBlbGVtZW50b3MgZGUgc3RyaW5ncwoKTGEgZnVuY2nDs24gYmFzZSBgZ3N1YigpYCBub3MgcGVybWl0ZSByZWVtcGxhemFyIHBhcnRlIGRlbCBzdHJpbmcgcG9yIG90cmEgY29zYS4gTGFzIGZ1bmNpb25lcyBgc3RyX3JlcGxhY2UoKWAgeSBgc3RyX3JlcGxhY2VfYWxsKClgIGRlIGBzdHJpbmdyYCBub3MgcGVybWl0ZW4gaGFjZXIgbG8gbWlzbW8uIAoKYHN0cl9yZXBsYWNlYCBzb2xvIHJlZW1wbGF6YSBsYSBwcmltZXJhIG9jdXJyZW5jaWEgZGVsIHBhdHJvbiBtaWVudHJhcyBxdWUgYHN0cl9yZXBsYWNlX2FsbCgpYCByZWVtcGxhemEgdG9kYXMgbGFzIG9jdXJyZW5jaWFzCgpgYGB7cn0Kc3RyaW5nNiA8LSAidG9kb3MgbG9zIGNhYmFsbG9zIGJsYW5jb3MiCnN0cmluZzYKYGBgCgpgYGB7cn0KI2xlIHNhY2Ftb3MgbG9zIGVzcGFjaW9zCmdzdWIocGF0dGVybiA9ICIgIiwgcmVwbGFjZW1lbnQgPSAiIiwgeCA9IHN0cmluZzYpCmBgYAoKYGBge3J9CiNsbyBsbGV2YW1vcyBhIGxlbmd1YWplIGluY2x1c2l2bwpnc3ViKHBhdHRlcm4gPSAib3MiLCByZXBsYWNlbWVudCA9ICJ4cyIsIHggPSBzdHJpbmc2KQpgYGAKCkNvbiBzdHJpbmdyCgpgYGB7cn0KIyBSZWVtcGxhemFtb3MgbGEgcHJpbWVyYSBvY3VycmVuY2lhCnN0cl9yZXBsYWNlKHN0cmluZyA9IHN0cmluZzYsIHBhdHRlcm4gPSAib3MiLCByZXBsYWNlbWVudCA9ICJ4cyIpCiMgUmVlbXBsYXphbW9zIHRvZGFzIGxhcyBvY3VycmVuY2lhcwpzdHJfcmVwbGFjZV9hbGwoc3RyaW5nID0gc3RyaW5nNiwgcGF0dGVybiA9ICJvcyIsIHJlcGxhY2VtZW50ID0gInhzIikKYGBgCgojIyMgRGV0ZWN0YXIgcGF0cm9uZXMgZW4gc3RyaW5ncwoKTGEgZnVuY2nDs24gYGdyZXBsKClgIG5vcyBwZXJtaXRlIGVuY29udHJhciBleHByZXNpb25lcyBkZW50cm8gZGUgbnVlc3Ryb3Mgc3RyaW5ncy4gTm9zIHJlcG9ydGEgYFZFUkRBREVST2AgbyBgRkFMU09gIGRlIGFjdWVyZG8gYSBzaSBlbmN1ZW50cmEgbGEgZXhwcmVzacOzbiBxdWUgZXN0YW1vcyBidXNjYW5kby4KCmBgYHtyfQpzdHJpbmc3IDwtYygiY2HDsW8iLCAiYmHDsW8iLCAibGFkcmlsbG8iKQpzdHJpbmc3CmBgYApgYGB7cn0KZ3JlcGwocGF0dGVybiA9ICLDsSIseCA9IHN0cmluZzcpCmBgYAoKTGEgZnVuY2lvbiBgc3RyX2RldGVjdCgpYCBkZSBgc3RyaW5ncmAgcGVybWl0ZSBoYWNlciBsbyBtaXNtby4KCiMgRWplbXBsbyBwcsOhY3RpY28KCiMjIEVqZW1wbG8gdGlidXJvbmVzCgpWYW1vcyBhIHZlciB1biBlamVtcGxvIGEgcGFydGlyIGRlIHVuYSBiYXNlIHDDumJsaWNhIHF1ZSBub3MgdHJhZSBpbmZvcm1hY2nDs24gc29icmUgYXRhcXVlcyBkZSB0aWJ1cm9uZXMgZW4gZWwgbXVuZG8gZW4gZGlzdGludG9zIG1vbWVudG9zLiBDYWRhIGZpbGEgY29ycmVzcG9uZGUgYSB1biBhdGFxdWUuCgpgYGB7cn0KdGlidXJvbmVzIDwtIHJlYWQuY3N2KCJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vZG11YmEvZG11YmEuZ2l0aHViLmlvLzMwMDVhN2E1ZThjOWRiNWMxODhjYTIyYTdiOTI2OWM5NGRiOGNlZDcvUHJhY3RpY29zL1RQcyUyMEVudHJlZ2FibGVzL1RQMDIvU2hhcmtfQXR0YWNrX0RhdGEuY3N2IikgJT4lIHNlbGVjdCgtYyhDYXNlLk51bWJlci4xLENhc2UuTnVtYmVyLjIsb3JpZ2luYWwub3JkZXIsIFgsIFguMSkpCmhlYWQodGlidXJvbmVzLDEwKQpgYGAKClZhbW9zIGEgdHJhYmFqYXIgdW4gcG9jbyBjb24gbGEgbGltcGllemEgeSBsYSBub3JtYWxpemFjacOzbiBkZSBlc3RhIGJhc2UgeWEgcXVlIGFsIGp1bnRhciBkYXRvcyBkZSBkaXN0aW50YXMgZnVlbnRlcyBsYSBpbmZvcm1hY2nDs24gbm8gZXMgaG9tb2fDqW5lYSBwb3IgbG8gcXVlIGVzIGRpZmljaWwgaGFjZXIgY3VhbHF1aWVyIHRpcG8gZGUgYW7DoWxpc2lzLgoKIyMjIENvdW50cnkKClZlYW1vcyBzaSBleGlzdGVuIHByb2JsZW1hcyBjb24gbGEgdmFyaWFibGUgZGVsIHBhw61zIChDb3VudHJ5KQoKYGBge3J9CiMgQ3JlYW1vcyB1bmEgbGlzdGEgY29uIGxvcyB2YWxvcmVzIGRlIENvdW50cnkgcGFyYSB2ZXIgc2kgaGF5IGFsZ3Vub3MgcHJvYmxlbWFzCnRpYnVyb25lcyAlPiUgc2VsZWN0KENvdW50cnkpICU+JSAjIFNlbGVjY2lvbmFtb3MgbGEgdmFyaWFibGUgZGVsIHBhaXMKICBtdXRhdGUoQ291bnRyeT1hcy5jaGFyYWN0ZXIoQ291bnRyeSkpICU+JSAjIExvIGNvbnZlcnRpbW9zIGRlIGZhY3RvciBhIHN0cmluZwogIGFycmFuZ2UoQ291bnRyeSkgJT4lICMgTGEgb3JkZW5hbW9zCiAgZGlzdGluY3QoKSAlPiUgIyBOb3MgcXVlZGFtb3MgY29uIGxvcyB2YWxvcmVzIHVuaWNvcwogIGFzLmxpc3QoKSAjIExhIGNvbnZlcnRpbW9zIGVuIGxpc3RhIHBhcmEgcXVlIHNlYSBtYXMgc2VuY2lsbGEgZGUgdmVyCmBgYAoKSGF5IHZhcmlvcyBwcm9ibGVtYXMsIHBlcm8gdmVhbW9zIGRvczoKCjEpIEhheSBhbGd1bm9zIG5vbWJyZXMgcXVlIG5vIGVzdMOhbiBlbiBtYXnDunNjdWxhCjIpIEhheSBhbGd1bm9zIG5vbWJyZXMgcXVlIHRpZW5lbiBlc3BhY2lvcyBlbiBibGFuY28gYSBpenF1aWVyZGEgeSBkZXJlY2hhCgpMbGV2YW1vcyBsb3Mgbm9tYnJlcyBhIG1hecO6c2N1bGEKYGBge3J9CnRpYnVyb25lcyA8LSB0aWJ1cm9uZXMgJT4lIG11dGF0ZShwYWlzPXN0cl90b191cHBlcihDb3VudHJ5KSkKaGVhZCh0aWJ1cm9uZXMsIDEwKQpgYGAKClF1aXRhbW9zIGxvcyBlc3BhY2lvcyBlbiBibGFuY28gYSBpenF1aWVyZGEgeSBkZXJlY2hhCgpgYGB7cn0KdGlidXJvbmVzIDwtIHRpYnVyb25lcyAlPiUgbXV0YXRlKHBhaXM9c3RyX3RyaW0ocGFpcywgc2lkZT0iYm90aCIpKQp0aWJ1cm9uZXMgJT4lIHNlbGVjdChwYWlzKSAlPiUgIyBTZWxlY2Npb25hbW9zIGxhIHZhcmlhYmxlIGRlbCBwYWlzCiAgI211dGF0ZShDb3VudHJ5PWFzLmNoYXJhY3RlcihDb3VudHJ5KSkgJT4lICMgTG8gY29udmVydGltb3MgZGUgZmFjdG9yIGEgc3RyaW5nCiAgYXJyYW5nZShwYWlzKSAlPiUgIyBMYSBvcmRlbmFtb3MKICBkaXN0aW5jdCgpICU+JSAjIE5vcyBxdWVkYW1vcyBjb24gbG9zIHZhbG9yZXMgdW5pY29zCiAgYXMubGlzdCgpICMgTGEgY29udmVydGltb3MgZW4gbGlzdGEgcGFyYSBxdWUgc2VhIG1hcyBzZW5jaWxsYSBkZSB2ZXIKYGBgCgojIyMgRGF0ZQoKVmFtb3MgYSBlbXBlemFyIGFuYWxpemFuZG8gbGEgdmFyaWFibGUgYERhdGVgIGRlIG51ZXN0cm8gZGF0YXNldC4gUHJpbWVybyBsbGV2YW1vcyBlc3RhIHZhcmlhYmxlIGEgdW4gcGVxdWXDsW8gZGF0YXNldCBhcGFydGUgeSBsbGV2YW1vcyBsYSB2YXJpYWJsZSBhbCB0aXBvIGBjaGFyYWN0ZXJgIHBhcmEgcG9kZXIgbWFuZWphcmxhIGNvbW8gdW4gc3RyaW5nLgoKYGBge3J9CkRhdGU8LXRpYnVyb25lcyAlPiUgc2VsZWN0KENhc2UuTnVtYmVyLCBEYXRlKSAlPiUgIyBTZWxlY2Npb25hbW9zIGxhcyB2YXJpYWJsZXMgZGUgbnVtZXJvIGRlIGNhc28geSBmZWNoYQogICAgICAgICAgICAgICAgICAgIG11dGF0ZShEYXRlPWFzLmNoYXJhY3RlcihEYXRlKSkgIyBUcmFuZm9ybWFtb3MgbGEgZmVjaGEgZW4gc3RyaW5nCmdsaW1wc2UoRGF0ZSkKYGBgCgpWZW1vcyBxdWUgbGEgdmFyaWFibGUgYERhdGVgIHZpZW5lIGVuIG11Y2hvcyBjYXNvcyBjb24gbGEgcGFsYWJyYSBfX1JlcG9ydGVkX18gbG8gY3VhbCBub3MgaW1waWRlIHF1ZSBwb2RhbW9zIHRyYXRhciBlc2EgZXhwcmVzacOzbiBjb21vIGZlY2hhIHVzYW5kbyBsYXMgaGVycmFtaWVudGFzIHF1ZSB2aW1vcyBlbiBsYSBzZWNjacOzbiBkZSBsdWJyaWRhdGUuIAoKYGBge3J9CkRhdGUgPC0gRGF0ZSAlPiUgbXV0YXRlKGRhdGVfY2xlYW4xPSBzdHJfcmVwbGFjZV9hbGwoc3RyaW5nID0gRGF0ZSwgcGF0dGVybiA9ICAiUmVwb3J0ZWQgIiwgcmVwbGFjZW1lbnQgPSAiIikpCmhlYWQoRGF0ZSwxMCkKYGBgCgojIyMgVGltZQoKVmFtb3MgYWhvcmEgYSB2ZXIgZWwgY2FzbyBkZSBsYSB2YXJpYWJsZSBgVGltZWAuIFZhbW9zIGEgcHJvY2VkZXIgaWd1YWwgcXVlIGNvbiBsYSB2YXJpYWJsZSBgRGF0ZWAsIGNyZWFuZG8gdW4gcGVxdWXDsW8gZGF0YXNldCBwYXJhIG5vcm1hbGl6YXIgZXN0YSB2YXJpYWJsZS4KCmBgYHtyfQojdHJhZW1vcyBsYSB2YXJpYWJsZSBxdWUgbm9zIGludGVyZXNhClRpbWUgPC0gdGlidXJvbmVzICU+JSBzZWxlY3QoVGltZSkKI2xhIGxsZXZhbW9zIGEgdGlwbyBjaGFyYWN0ZXIgcGFyYSB0cmFiYWphcmxhIGNvbW8gc3RyaW5nClRpbWUgPC0gVGltZSAlPiUgbXV0YXRlKFRpbWU9YXMuY2hhcmFjdGVyKFRpbWUpKQojYm9ycm8gZXN0YSBlbnRyYWRhIHBvcnF1ZSB0aWVuZSB1biBkYXRvIHJhcm8gcXVlIG5vIG5vcyBkZWphIHRyYWJhamFyIApUaW1lWzE1NDUsXSA8LSAiIgojbGxldmFtb3MgdG9kbyBhIG1pbsO6c2N1bGFzIChjb24gb3RyYSBmdW5jacOzbiBxdWUgdGFtYmnDqW4gaGFjZSBlc28pClRpbWU8LVRpbWUgJT4lIG11dGF0ZShUaW1lPXRvbG93ZXIoVGltZSkpClRpbWUKYGBgCgpOdWVzdHJvIG9iamV0aXZvIGVzIGxsZXZhciBsYXMgaG9yYXMgYSB1bmEgdmFyaWFibGUgY2F0ZWfDs3JpY2EgY29uIGxvcyB2YWxvcmVzIF9fbWHDsWFuYV9fLCBfX3RhcmRlX18geSBfX25vY2hlX18uIFBhcmEgZXNvIHBvciB1biBsYWRvIHZhbW9zIGEgdGVuZXIgcXVlIGV4dHJhZXIgbGEgaG9yYSBkZSBsYXMgdmFyaWFibGVzIHF1ZSBsYSB0aWVuZW4gY2FyZ2FkYSBlbiBmb3JtYSBuw7ptZXJpY2EgcGFyYSBsdWVnbyBhZ3J1cGFybGFzIGVuIGVzYXMgdHJlcyBjYXRlZ29yw61hcywgeSBwb3IgZWwgb3RybyBsYWRvIG5vcm1hbGl6YXIgbGEgZm9ybWEgY2F0ZWfDs3JpY2EgZGFkYSBlbiBpbmdsw6lzIHF1ZSBhY3R1YWxtZW50ZSB0aWVuZSBjdWF0cm8gY2F0ZWdvcsOtYXMuCgpFbXBlY2Vtb3MgdHJhYmFqYW5kbyBjb24gbGFzIGVudHJhZGFzIHF1ZSB0aWVuZW4gbG9zIHZhbG9yZXMgZGFkb3MgZW4gbsO6bWVyb3MuIFByaW1lcm8gdmFtb3MgYSB2ZXIgcXVlIGVudHJhZGFzIHRpZW5lbiBfX2hfXyB5IHZhbW9zIGEgZ2VuZXJhciB1bmEgY29sdW1uYSBjb24gZWwgbGFyZ28gZGVsIHN0cmluZy4KCmBgYHtyfQpUaW1lIDwtIFRpbWUgJT4lIG11dGF0ZSh0aWVuZV9oID0gZ3JlcGwocGF0dGVybiA9ICJoIix4ID0gVGltZSksCiAgICAgICAgICAgICAgICAgICAgICAgIGxhcmdvPXN0cl9sZW5ndGgoVGltZSkpClRpbWUKYGBgCgpBaG9yYSBjcmVhbW9zIHVuYSB2YXJpYWJsZSBxdWUgbm9zIHZhIGEgZGVjaXIgc2kgc2UgdHJhdGEgZGUgdW4gY2FzbyBjb24gbGEgaG9yYSBkYWRhIGVuIG7Dum1lcm9zLiBQYXJhIGRldGVjdGFyIGVzdG9zIGNhc29zLCBlbCBzdHJpbmcgdGllbmUgcXVlIGNvbnRlbmVyIGxhIGxldHJhIF9faF9fIHkgdGVuZXIgNSBjYXJhY3RlcmVzLgoKYGBge3J9ClRpbWUgPSBUaW1lICU+JSBtdXRhdGUoZXNfaG9yYSA9IGNhc2Vfd2hlbih0aWVuZV9oPT1UUlVFICYgbGFyZ289PTUgfiAic2kiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGllbmVfaD09RkFMU0UgfCBsYXJnbyE9NSB+ICJubyIpKQpUaW1lCmBgYAoKQWhvcmEsIHNpIHNlIHRyYXRhIGRlIHVuYSBlbnRyYWRhIGNvbiBlbCBmb3JtYXRvIGRlIGhvcmEsIHZhbW9zIGEgdHJhZXIgbGEgcHJpbWVyYSB5IHNlZ3VuZGEgcG9zaWNpw7NuIHF1ZSBjb3JyZXNwb25kZW4gYSBsYSBob3JhLgoKYGBge3IsIHdhcm5pbmc9RkFMU0V9ClRpbWUgPSBUaW1lICU+JSBtdXRhdGUoaG9yYSA9IGNhc2Vfd2hlbihlc19ob3JhID09InNpIiB+IHN1YnN0cihUaW1lLDEsMikpLAogICAgICAgICAgICAgICAgICAgICAgIGhvcmEgPSBhcy5udW1lcmljKGhvcmEpKQpUaW1lCmBgYAoKQWhvcmEgdmFtb3MgYSBsbGV2YXIgbG9zIHZhbG9yZXMgbm9tw6lyaWNvcyBjb250aW51b3MgYSBsYXMgdmFyaWFibGVzIGRpc2NyZXRhcyBxdWUgbWVuY2lvbmFtb3MgeSB2YW1vcyBhIGxsZXZhciBsYXMgdmFyaWFibGVzIGVuIGluZ2zDqXMgYSBsYXMgdmFyaWFibGVzIGVuIGNhc3RlbGxhbm8uCgpgYGB7cn0KVGltZSA9IFRpbWUgJT4lIG11dGF0ZShob3JhX2VzdGFuZGFyID0gY2FzZV93aGVuKGdyZXBsKCJhZnRlcm5vb24iLFRpbWUpPT1UUlVFIH4gInRhcmRlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyZXBsKCJkYXkiLFRpbWUpPT1UUlVFIH4gInRhcmRlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyZXBsKCJuaWdodCIsVGltZSk9PVRSVUUgfiAibm9jaGUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JlcGwoIm1vcm5pbmciLFRpbWUpPT1UUlVFIH4gIm1hw7FhbmEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaG9yYT41ICYgaG9yYTwxMiB+ICJtYcOxYW5hIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhvcmE+MTEgJiBob3JhPDE5IH4gInRhcmRlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhvcmE8NiB8IGhvcmE+MTggfiAibm9jaGUiKSkKIyBSZWVtcGxhemFtb3MgbG9zIE5BIHBvciAiaG9yYSBpbmRlZmluaWRhIiAKVGltZSA8LSBUaW1lICU+JSByZXBsYWNlX25hKGxpc3QoaG9yYV9lc3RhbmRhcj0iaG9yYSBpbmRlZmluaWRhIikpClRpbWUKYGBgCgojIyMgRmVjaGEgY29uIEx1YnJpZGF0ZQoKYGBge3J9CiMgU2VsZWNjaW9uYW1vcyBhbGd1bmFzIHZhcmlhYmxlcwp0aWJ1cm9uZXMgPC0gdGlidXJvbmVzICU+JSBzZWxlY3QoQ2FzZS5OdW1iZXIsIFR5cGUsRGF0ZSwgcGFpcykKIyBIYWNlbW9zIGxhIGxpbXBpZXphIGRlIGxhIGZlY2hhIGNvbW8gdmltb3MgbcOhcyBhcnJpYmEKdGlidXJvbmVzIDwtIHRpYnVyb25lcyAlPiUgbXV0YXRlKGRhdGVfY2xlYW4xPSBzdHJfcmVwbGFjZV9hbGwoc3RyaW5nID0gRGF0ZSwgcGF0dGVybiA9ICAiUmVwb3J0ZWQgIiwgcmVwbGFjZW1lbnQgPSAiIikpCmdsaW1wc2UodGlidXJvbmVzKQpgYGAKClRyYW5zZm9ybWFtb3MgbGEgdmFyaWFibGUgZmVjaGEgZGUgdW4gc3RyaW5nIGEgdW5hIGZlY2hhCgpgYGB7cn0KdGlidXJvbmVzIDwtIHRpYnVyb25lcyAlPiUgbXV0YXRlKGZlY2hhPSBkbXkoZGF0ZV9jbGVhbjEpKQpgYGAKCkVsIG1lbnNhamUgaW5kaWNhIHF1ZSBubyBwdWRvIGNvbnZlcnRpciBhIGZlY2hhIDg4OSByZWdpc3Ryb3MuCgpFeHRyYWVtb3MgdmFyaWFibGVzIGRlIGxhIGZlY2hhCgpgYGB7cn0KdGlidXJvbmVzIDwtIHRpYnVyb25lcyAlPiUgbXV0YXRlKGHDsW8gPSB5ZWFyKGZlY2hhKSwgI09idGVuZXIgZWwgYcOxbwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VtZXN0cmU9c2VtZXN0ZXIoZmVjaGEpLCAjIE9idGVuZXIgZWwgc2VtZXN0cmUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyaW1lc3RyZT1xdWFydGVyKGZlY2hhKSwjT2J0ZW5lciBlbCB0cmltZXN0cmUgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXM9bW9udGgoZmVjaGEsbGFiZWwgPSBUUlVFKSwgI09idGVuZXIgZWwgbm9tYnJlIGRlbCBtZXMKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpYT1kYXkoZmVjaGEpLCMgT2J0ZW5lciBlbCBkw61hCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWFfc2VtYW5hPXdkYXkoZmVjaGEsIGxhYmVsID0gVFJVRSkgI09idGVuZXIgZWwgbm9tYnJlIGRlbCBkw61hCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApCgpnbGltcHNlKHRpYnVyb25lcykKYGBgCgojIyMgQWxndW5vcyBncsOhZmljb3MKCkZpbHRyYW1vcyBsb3MgcmVnaXN0cm9zIHkgbm9zIHF1ZWRhbW9zIGNvbiBsb3MgYXRhcXVlcyBkZXNkZSAxODAwCgpgYGB7cn0KdGlidXJvbmVzX2ZpbHRybyA8LSB0aWJ1cm9uZXMgJT4lIGZpbHRlcihhw7FvID49MTgwMCkKYGBgCgpWZWFtb3MgbGEgZXZvbHVjacOzbiBwb3IgYcOxbyBkZSBsb3MgYXRhcXVlcyBkZSB0aWJ1cm9uZXMKCmBgYHtyfQpnZ3Bsb3QodGlidXJvbmVzX2ZpbHRybywgYWVzKGHDsW8pKSArCiAgZ2VvbV9saW5lKHN0YXQgPSAiY291bnQiKSArCiAgZ2VvbV9wb2ludChzdGF0PSdjb3VudCcpICsKICB0aGVtZV9idygpICsKICBsYWJzKHRpdGxlPSdFdm9sdWNpb24gYXRhcXVlcyBkZSB0aWJ1cm9uZXMnLCB4PSdBw7FvJywgeT0nQXRhcXVlcycpCmBgYAoKU2VsZWNjaW9uYW1vcyBhIGRvcyBwYWlzZXMgY29uIG11Y2hvcyBhdGFxdWVzLiBSZWNvcmRlbW9zIHF1ZSBoYWJpYW1vcyBoZWNobyBhbGd1bm9zIHByb2NlZGltaWVudG9zIGRlIG5vcm1hbGl6YWNpw7NuIHNvYnJlIGVzdGEgdmFyaWFibGUKCmBgYHtyfQp0aWJ1cm9uZXNfYXVzX3VzYSA8LSB0aWJ1cm9uZXNfZmlsdHJvICU+JSBmaWx0ZXIocGFpcyAlaW4lIGMoIkFVU1RSQUxJQSIsIlVTQSIpKSAKYGBgCgpPYnNlcnZlbW9zIGVsIGNpY2xvIGFudWFsIGRlIGF0YXF1ZXMgZGUgdGlidXJvbmVzIGVuIGVzdG9zIHBhaXNlcwoKYGBge3J9CmdncGxvdCh0aWJ1cm9uZXNfYXVzX3VzYSwgYWVzKG1lcyxjb2xvcj1wYWlzLCBncm91cD1wYWlzKSkgKwogIGdlb21fbGluZShzdGF0ID0gImNvdW50IikgKwogIGdlb21fcG9pbnQoc3RhdD0nY291bnQnKSArCiAgdGhlbWVfYncoKSArCiAgbGFicyh0aXRsZT0nQ2ljbG8gYW51YWwgYXRhcXVlcyBkZSB0aWJ1cm9uZXMnLCB4PSdNZXMnLCB5PSdBdGFxdWVzJykKYGBgCg==