Primero la Sección de Librerías de Funciones:

# rownames(installed.packages())
list.of.packages <- c(
"arm" , 
"broom" , 
"corrplot" , 
"cowplot" , 
"datasets" , 
"datasets" , 
"dplyr" , 
"eeptools" , 
"estimatr" , 
"FinCal" , 
"formatR" , 
"ggfortify" , 
"ggpubr" , 
"haven" , 
"Hmisc" , 
"infer" , 
"knitr" , 
"lmtest" , 
"margins" , 
"nycflights13" , 
"psych" , 
"readxl" , 
"reshape2" , 
"rms" , 
"skimr" , 
"stargazer" , 
"stringr" , 
"survival" , 
"tableone" , 
"tidyr" , 
"tidyverse" , 
"TTR" , 
"wooldridge" , 
"xlsx",
# Adicionales Octubre 2021:
"sqldf", # Para SQL en R
"RODBC",  # Para Conexion SQL y R Studio
# Adicionales 9 Octubre 2021:
"readr",
"devtools"
)
has   <- list.of.packages %in% rownames(installed.packages())
if(any(!has)) install.packages(list.of.packages[!has])

Llamada a LIBRERIAS:

library(googledrive)

Attaching package: 㤼㸱googledrive㤼㸲

The following objects are masked from 㤼㸱package:googlesheets4㤼㸲:

    request_generate, request_make

A partir de aquí la Sección de Importación de Datasets:

print("Working Directory: "); getwd() #get to show me the current Working Directory 
[1] "Working Directory: "
[1] "I:/001.7 CURSO-02 Lenguaje R Semillero/21.10.09.T  Sab Mentoria11 Renzo R"
### Cargando BBDD: n5ay5qadfe7e1nnsv5s01oe1x62mq51j.csv ####
# Version de BBDD: 2021.09.24 v1
# RUTA: https://ibm.box.com/shared/static/

# XLS file,  Download datasets
# download.file( "https://ibm.box.com/shared/static/nx0ohd9sq0iz3p871zg8ehc1m39ibpx6.xls" , 
#                destfile="movies-db.xls" )

# CSV file,  Download datasets
download.file("https://ibm.box.com/shared/static/n5ay5qadfe7e1nnsv5s01oe1x62mq51j.csv", 
              destfile="movies-db.csv")
trying URL 'https://ibm.box.com/shared/static/n5ay5qadfe7e1nnsv5s01oe1x62mq51j.csv'
Content type 'text/csv' length 1424 bytes
downloaded 1424 bytes
database_csv <- read.csv("movies-db.csv", header=TRUE, sep=",")

file.exists("movies-db.xlsx")
[1] TRUE
# Read data from the XLS file and attribute the table a dataframe.
database_xlsx <- read_excel("movies-db.xlsx")
database_xlsx

#movies_data
(
database <- database_xlsx
)

# Read data from the XLS file and attribute the table to a dataframe.
paises_001.xlsx <- read_excel("paises_001.xlsx")
paises_001.xlsx
NA
#movies_data
(
database <- paises_001.xlsx
)
NA

To download a Google Sheet online from Google Drive into a dataframe in R:

#################################################
#- GoogleSheet4
#################################################
#install.packages("devtools")
library(devtools)
#devtools::install_github("tidyverse/googlesheets4")

#install.packages("gargle")
library(googlesheets4)

gs4_auth()
The googlesheets4 package is requesting access to your Google account.
Select a pre-authorised account or enter '0' to obtain a new token.
Press Esc/Ctrl + C to cancel.

1: ecanchor@unmsm.edu.pe
1
#help(gs4_auth)
#################################################
#- Read an existing Spreadsheet 
###############################################

data_to_write <- read_sheet("https://docs.google.com/spreadsheets/d/1Cm-VRHrUDlGFke4d_wkCiL-htt0ctB_p7oPn6Pl6YEc")
Auto-refreshing stale OAuth token.
v Reading from paises_001_GoogleSheet.
v Range Sheet1.
data_to_write

To download a CSV file from Google Drive (está viendose sin UTF-8(acentos, eñe) si lo abro en Excel, debe de insertarse con llamada de datos al file CSCV):

#################################################
#- Downloading a spreadsheet file as a csv 
#################################################
target <- drive_get( "https://docs.google.com/spreadsheets/d/1Cm-VRHrUDlGFke4d_wkCiL-htt0ctB_p7oPn6Pl6YEc" )
drive_download( target , 
                type= "csv" , 
                path = "paises_001_GoogleSheet.csv" ,
                overwrite = TRUE )
File downloaded:
* paises_001_GoogleSheet <id: 1Cm-VRHrUDlGFke4d_wkCiL-htt0ctB_p7oPn6Pl6YEc>
Saved locally as:
* paises_001_GoogleSheet.csv

Read data from Google Drive (the ZIP file) and attribute the table to a dataframe.

# https://docs.google.com/spreadsheets/d/1PiNq7i0cXEhvXApRCvvh3FUDrF2kGeua/edit?usp=sharing&ouid=109636307569655661315&rtpof=true&sd=true
# Read data from Google Drive (the ZIP file) and attribute the table to a dataframe.
library(googledrive)
library(httpuv)
temp <- tempfile( fileext = ".zip" )
temp
[1] "C:\\Users\\user\\AppData\\Local\\Temp\\Rtmp8op7JF\\file5fd47a402c45.zip"
dl <- drive_download(
         as_id( "1AiZda_1-2nwrxI8fLD0Y6e5rTg7aocv0" ) , 
         path = temp , overwrite = TRUE )
File downloaded:
* Archive.zip <id: 1AiZda_1-2nwrxI8fLD0Y6e5rTg7aocv0>
Saved locally as:
* C:\Users\user\AppData\Local\Temp\Rtmp8op7JF\file5fd47a402c45.zip
dl
out <- unzip( temp , exdir = tempdir() )
out
 [1] "C:/Users/user/AppData/Local/Temp/Rtmp8op7JF/bank/.DS_Store"                                     
 [2] "C:/Users/user/AppData/Local/Temp/Rtmp8op7JF/__MACOSX/bank/._.DS_Store"                          
 [3] "C:/Users/user/AppData/Local/Temp/Rtmp8op7JF/bank/bank-full.csv"                                 
 [4] "C:/Users/user/AppData/Local/Temp/Rtmp8op7JF/__MACOSX/bank/._bank-full.csv"                      
 [5] "C:/Users/user/AppData/Local/Temp/Rtmp8op7JF/bank/bank.csv"                                      
 [6] "C:/Users/user/AppData/Local/Temp/Rtmp8op7JF/__MACOSX/bank/._bank.csv"                           
 [7] "C:/Users/user/AppData/Local/Temp/Rtmp8op7JF/__MACOSX/._bank"                                    
 [8] "C:/Users/user/AppData/Local/Temp/Rtmp8op7JF/bank-additional/.DS_Store"                          
 [9] "C:/Users/user/AppData/Local/Temp/Rtmp8op7JF/__MACOSX/bank-additional/._.DS_Store"               
[10] "C:/Users/user/AppData/Local/Temp/Rtmp8op7JF/bank-additional/.Rhistory"                          
[11] "C:/Users/user/AppData/Local/Temp/Rtmp8op7JF/__MACOSX/bank-additional/._.Rhistory"               
[12] "C:/Users/user/AppData/Local/Temp/Rtmp8op7JF/bank-additional/bank-additional-full.csv"           
[13] "C:/Users/user/AppData/Local/Temp/Rtmp8op7JF/__MACOSX/bank-additional/._bank-additional-full.csv"
[14] "C:/Users/user/AppData/Local/Temp/Rtmp8op7JF/bank-additional/bank-additional.csv"                
[15] "C:/Users/user/AppData/Local/Temp/Rtmp8op7JF/__MACOSX/bank-additional/._bank-additional.csv"     
[16] "C:/Users/user/AppData/Local/Temp/Rtmp8op7JF/__MACOSX/._bank-additional"                         
bank <- read.csv( out[14] , sep = ";" )
str(bank)
'data.frame':   4119 obs. of  21 variables:
 $ age           : int  30 39 25 38 47 32 32 41 31 35 ...
 $ job           : chr  "blue-collar" "services" "services" "services" ...
 $ marital       : chr  "married" "single" "married" "married" ...
 $ education     : chr  "basic.9y" "high.school" "high.school" "basic.9y" ...
 $ default       : chr  "no" "no" "no" "no" ...
 $ housing       : chr  "yes" "no" "yes" "unknown" ...
 $ loan          : chr  "no" "no" "no" "unknown" ...
 $ contact       : chr  "cellular" "telephone" "telephone" "telephone" ...
 $ month         : chr  "may" "may" "jun" "jun" ...
 $ day_of_week   : chr  "fri" "fri" "wed" "fri" ...
 $ duration      : int  487 346 227 17 58 128 290 44 68 170 ...
 $ campaign      : int  2 4 1 3 1 3 4 2 1 1 ...
 $ pdays         : int  999 999 999 999 999 999 999 999 999 999 ...
 $ previous      : int  0 0 0 0 0 2 0 0 1 0 ...
 $ poutcome      : chr  "nonexistent" "nonexistent" "nonexistent" "nonexistent" ...
 $ emp.var.rate  : num  -1.8 1.1 1.4 1.4 -0.1 -1.1 -1.1 -0.1 -0.1 1.1 ...
 $ cons.price.idx: num  92.9 94 94.5 94.5 93.2 ...
 $ cons.conf.idx : num  -46.2 -36.4 -41.8 -41.8 -42 -37.5 -37.5 -42 -42 -36.4 ...
 $ euribor3m     : num  1.31 4.86 4.96 4.96 4.19 ...
 $ nr.employed   : num  5099 5191 5228 5228 5196 ...
 $ y             : chr  "no" "no" "no" "no" ...
bank
NA

Reading file from a CSV file:

# Read data from the TXT  file and attribute the table to a dataframe.
paises_001.csv <- read.csv("prueba_csv01.csv", header=TRUE, sep=";")
paises_001.csv

Reading file from a TXT file:

paises_001.txt <- read_csv("paises_001.txt")
Rows: 4 Columns: 3
-- Column specification ------------------------------------------------------
Delimiter: ","
chr (1): pais
dbl (2): poblacion, anio

i Use `spec()` to retrieve the full column specification for this data.
i Specify the column types or set `show_col_types = FALSE` to quiet this message.
paises_001.txt
#library(haven)
BaseCOVID19.sav <- read_sav("BaseCOVID-19.sav")
BaseCOVID19.sav
NA
#library(haven)
enaho01.dta <- read_dta("enaho01-2020-100.dta")
enaho01.dta
NA

REVISION RAPIDA DEL DATAFRAME:

#View(database)
summary(database) # Summary Estadístico.
       Nº            PAIS              CODIGO         
 Min.   : 1.00   Length:57          Length:57         
 1st Qu.:15.00   Class :character   Class :character  
 Median :30.00   Mode  :character   Mode  :character  
 Mean   :29.58                                        
 3rd Qu.:44.00                                        
 Max.   :58.00                                        
head(database) # Primeros 6.
names(database) # Names de columnas.
[1] "Nº"     "PAIS"   "CODIGO"
print(is.data.frame(database))
[1] TRUE
#attach(database) #only if there is only 1 dataset 
# CONTENIDO DE TABLA:
# database es la tabla con datos de películas.

ANALIZAMOS LA ESTRCUTURA DE LA TABLA:

Función str: structure Lab08-importingData


# Prints out the structure of your table.
str(database) # es la función structure
tibble [57 x 3] (S3: tbl_df/tbl/data.frame)
 $ Nº    : num [1:57] 1 2 3 4 5 6 7 8 9 10 ...
 $ PAIS  : chr [1:57] "Angola" "Argelia" "Benin" "Botswana" ...
 $ CODIGO: chr [1:57] "AGO" "DZA" "BEN" "BWA" ...

A partir de aquí inicia el Cuerpo del Script:

EJERCICIO FUNCIONES PROPIAS EN R

# UDF - User Defined Functions

sum( 111 , 222 )
[1] 333
prod( 111 , 222 )
[1] 24642
log( 8 , 2 )
[1] 3
# library(ggplot2)
# ggplot()


#Incremento Porcentual
( 
Importe <- 256
)
[1] 256
(
Impuesto <- 3.2/100
)
[1] 0.032
(
Precio.de.Venta <- Importe * ( 1+Impuesto )
)
[1] 264.192
(
Variación <- Precio.de.Venta/Importe - 1
)
[1] 0.032
# Function Increase_percentaje
Increase_percentaje <- function( Importe , Prc_Impuesto ){
  Precio.de.Venta <- Importe * ( 1+Prc_Impuesto/100 )
  Precio.de.Venta <- round( Precio.de.Venta , 2 )
  
  print( paste( "Increasing ", Importe ,
                " en ", Prc_Impuesto , 
                "% resulta en: ", Precio.de.Venta , " USD.",
                sep = "" ))
  return(Precio.de.Venta)
}

#Llamar a la function
Precio.de.Venta.1 <- Increase_percentaje( 256 , 3.2 ) 
[1] "Increasing 256 en 3.2% resulta en: 264.19 USD."
Precio.de.Venta.1
[1] 264.19

OTRA FUNCION:

# Function Increase_percentaje2
Increase_percentaje2 <- function( Importe , Prc_Impuesto ){
  Precio.de.Venta <- Importe * ( 1+Prc_Impuesto/100 )
  Precio.de.Venta <- round( Precio.de.Venta , 2 )
  
  if( Importe <= 0 ){
    print("Error. Importe <= 0.")
    return(NULL)
  }else if( Prc_Impuesto <= 0 ){
    print("Error. Prc_Impuesto <= 0.")
    return(NULL)
  }else{
  
  print( paste( "Increasing ", Importe ,
                " en ", Prc_Impuesto , 
                "% resulta en: ", Precio.de.Venta , " USD.",
                sep = "" ))
  return(Precio.de.Venta)
  }
}
#Llamar a la function
Precio.de.Venta.1 <- Increase_percentaje2( 256 , 3.2 ) 
[1] "Increasing 256 en 3.2% resulta en: 264.19 USD."
str(Precio.de.Venta.1)
 num 264
#Precio.de.Venta.1
Precio.de.Venta.2 <- Increase_percentaje2( -256 , 3.2 ) 
[1] "Error. Importe <= 0."
str(Precio.de.Venta.2)
 NULL
#Precio.de.Venta.2
Precio.de.Venta.3 <- Increase_percentaje2( 256 , -3.2 ) 
[1] "Error. Prc_Impuesto <= 0."
str(Precio.de.Venta.3)
 NULL
#Precio.de.Venta.2

EJEMPLO BUCLE FOR:

for( i in 1:5){
  print( i^2 )
}
[1] 1
[1] 4
[1] 9
[1] 16
[1] 25
Vector.1a5 <- c(1:5)
#Vector.1a5
Vector.1a5^2
[1]  1  4  9 16 25
for( i in Vector.1a5 ){
  print( i^2 )
}
[1] 1
[1] 4
[1] 9
[1] 16
[1] 25
Dataframe.1a5 <- as.data.frame( c(1:5) )
#Dataframe.1a5
names(Dataframe.1a5)
[1] "c(1:5)"
Dataframe.1a5$c
[1] 1 2 3 4 5
for( i in Dataframe.1a5$c ){
  print( i^2 )
}  
[1] 1
[1] 4
[1] 9
[1] 16
[1] 25
#help("sqldf")

mtcars
#View(mtcars)
df_query <- sqldf("select * from mtcars")
df_query
#str(df_query)
sqldf("SELECT cyl , count( cyl ) as Cilindros FROM mtcars GROUP BY cyl ")
df_pivot_sql <- sqldf( " SELECT cyl , 
                                COUNT( cyl ) as Cilindros 
                         FROM mtcars 
                         GROUP BY cyl ")
df_pivot_sql

EJERCICIOS ADICIONALES CON mtcars:

#mtcars
tabla.1 <- table( mtcars$cyl )
#tabla.1

colores <- c( "orange" , 
              "green" , 
              "yellow" )
#colores

plot.1 <- barplot( tabla.1 , 
                   xlab = "Cilindros" , 
                   ylab = "Frequencia" , 
                   main = "Nro de Cilindros" ,
                   col = colores )

plot.1
     [,1]
[1,]  0.7
[2,]  1.9
[3,]  3.1

CONTINUACION CON mtcars :


plot.2 <- ggplot( mtcars ,
                  aes( cyl )) +
          geom_bar( fill = colores ) + 
          labs( x= "Cilindros" , 
                y = "Frecuencias" , 
                title = "Numero de Cilindros")
plot.2  

NA

REPASO DE MATRICES:

matrix.1 <- matrix( 1:10 , 
            nrow = 5 , 
            ncol = 4 )
matrix.1
     [,1] [,2] [,3] [,4]
[1,]    1    6    1    6
[2,]    2    7    2    7
[3,]    3    8    3    8
[4,]    4    9    4    9
[5,]    5   10    5   10
dim(matrix.1)
[1] 5 4
matrix.1[2,4]
[1] 7
matrix.1[2, ]
[1] 2 7 2 7
matrix.1[ ,4]
[1]  6  7  8  9 10
df_matrix.1 <- as.data.frame( matrix.1 , row.names = NULL, 
                              optional = FALSE , 
                              make.names = TRUE , 
               stringsAsFactors = default.stringsAsFactors() )
#df_matrix.1
#df_matrix.1$V4
df_matrix.1['V4']
NA

EJERCICIOS:

summary(database)
       Nº            PAIS              CODIGO         
 Min.   : 1.00   Length:57          Length:57         
 1st Qu.:15.00   Class :character   Class :character  
 Median :30.00   Mode  :character   Mode  :character  
 Mean   :29.58                                        
 3rd Qu.:44.00                                        
 Max.   :58.00                                        
matrix_summary <- do.call(cbind, lapply(database, summary))
matrix_summary
        Nº                 PAIS        CODIGO     
Min.    "1"                "57"        "57"       
1st Qu. "15"               "character" "character"
Median  "30"               "character" "character"
Mean    "29.5789473684211" "57"        "57"       
3rd Qu. "44"               "character" "character"
Max.    "58"               "character" "character"
str(matrix_summary)
 chr [1:6, 1:3] "1" "15" "30" "29.5789473684211" "44" "58" "57" ...
 - attr(*, "dimnames")=List of 2
  ..$ : chr [1:6] "Min." "1st Qu." "Median" "Mean" ...
  ..$ : chr [1:3] "Nº" "PAIS" "CODIGO"
df_summary <- as.data.frame(matrix_summary, row.names = NULL, optional = FALSE,
              make.names = TRUE, 
              stringsAsFactors = default.stringsAsFactors())
df_summary

summary( database$cost_millions )
Unknown or uninitialised column: `cost_millions`.
Length  Class   Mode 
     0   NULL   NULL 
# Retrieve a subset_dataframe of the data frame consisting of the "genre" columns
database['PAIS']

# Retrieve the data for the "name" column in the data frame in a vector
database$PAIS
 [1] "Angola"                                       
 [2] "Argelia"                                      
 [3] "Benin"                                        
 [4] "Botswana"                                     
 [5] "Burkina Faso"                                 
 [6] "Burundi"                                      
 [7] "Cabo Verde"                                   
 [8] "Camerún"                                      
 [9] "Chad"                                         
[10] "Comoras"                                      
[11] "Congo"                                        
[12] "Côte d'Ivoire"                                
[13] "Djibouti"                                     
[14] "Egipto"                                       
[15] "Eritrea"                                      
[16] "España, territorios vinculados en Africa"     
[17] "Etiopía"                                      
[18] "Francia, territorios vinculados en Africa"    
[19] "Gabón"                                        
[20] "Gambia"                                       
[21] "Ghana"                                        
[22] "Guinea"                                       
[23] "Guinea Bissau"                                
[24] "Guinea Ecuatorial"                            
[25] "Kenya"                                        
[26] "Lesotho"                                      
[27] "Liberia"                                      
[28] "Libia"                                        
[29] "Madagascar"                                   
[30] "Malawi"                                       
[31] "Malí"                                         
[32] "Marruecos"                                    
[33] "Mauricio"                                     
[34] "Mauritania"                                   
[35] "Mozambique"                                   
[36] "Namibia"                                      
[37] "Níger"                                        
[38] "Nigeria"                                      
[39] "Reino Unido, territorios vinculados en África"
[40] "República Centroafricana"                     
[41] "República Democrática del Congo"              
[42] "Rwanda"                                       
[43] "Santo Tomé y Príncipe"                        
[44] "Senegal"                                      
[45] "Seychelles"                                   
[46] "Sierra Leona"                                 
[47] "Somalia"                                      
[48] "Sudáfrica"                                    
[49] "Sudán"                                        
[50] "Sudán del Sur"                                
[51] "Swazilandia"                                  
[52] "Tanzanía"                                     
[53] "Togo"                                         
[54] "Túnez"                                        
[55] "Uganda"                                       
[56] "Zambia"                                       
[57] "Zimbabwe"                                     
# Retrieve the 3rd row of the data frame.
database[3,]

# Retrieve the third row of the data frame, but only the "name" and "length_min" columns.
database[3, c("PAIS","CODIGO")]

summary(database)
       Nº            PAIS              CODIGO         
 Min.   : 1.00   Length:57          Length:57         
 1st Qu.:15.00   Class :character   Class :character  
 Median :30.00   Mode  :character   Mode  :character  
 Mean   :29.58                                        
 3rd Qu.:44.00                                        
 Max.   :58.00                                        
histograma <- hist(database$Nº ,col="yellow",breaks = 10)

histograma
$breaks
 [1]  0  5 10 15 20 25 30 35 40 45 50 55 60

$counts
 [1] 5 5 5 5 4 5 5 5 5 5 5 3

$density
 [1] 0.01754386 0.01754386 0.01754386 0.01754386 0.01403509 0.01754386
 [7] 0.01754386 0.01754386 0.01754386 0.01754386 0.01754386 0.01052632

$mids
 [1]  2.5  7.5 12.5 17.5 22.5 27.5 32.5 37.5 42.5 47.5 52.5 57.5

$xname
[1] "database$Nº"

$equidist
[1] TRUE

attr(,"class")
[1] "histogram"

time = gsub(":", "-", Sys.time())

#- exporta en formato .csv el df df_summary al fichero "df_summary.csv". Se guardará en la subcarpeta "datos/pruebas/" del proyecto
folder_path <- "./output_databases/"
filename <- "df_summary"
filetype <-".csv"
path <- paste(folder_path,filename," ",time,filetype, sep="")
write_csv(df_summary, path)

Hay varios packages que graban datos en formato .xls. Pero el más sencillo es el package xlsx. Veámoslo:

# install.packages("xlsx")
# library(xlsx)
write.xlsx(df_summary, "./output_databases/df_summary.xlsx", sheetName = "df_summary" )

La función write.xlsx() permite añadir datos a un archivo .xlsx preexistente; para ello tenemos que usar la opción append = TRUE:

# library(xlsx)
write.xlsx(df_summary, "./output_databases/df_summary.xlsx", sheetName = "summary", append = TRUE)

DEL EJERCICIO DE EJECUTAR SQL QUERY en UN R NOTEBOOK:

write.xlsx( df_pivot_sql , 
            "./output_databases/df_pivot_sql.xlsx", 
            sheetName = "df_pivot_sql" )

GRAFICA

#**********************************************************************
#*# Publication quality graphs require 600dpi
dpi=600    #pixels per square inch
carpeta = "./output_images/"
archivo = "histograma"
time = gsub(":", "-", Sys.time())
carpeta_y_archivo = paste(carpeta,archivo," ",time,".tif", sep="")
nombre_de_tif = carpeta_y_archivo
tiff(nombre_de_tif, width=6*dpi, height=5*dpi, res=dpi)
#**********************************************************************
histograma <- hist(database$Nº ,col="yellow",breaks = 10)
histograma
$breaks
 [1]  0  5 10 15 20 25 30 35 40 45 50 55 60

$counts
 [1] 5 5 5 5 4 5 5 5 5 5 5 3

$density
 [1] 0.01754386 0.01754386 0.01754386 0.01754386 0.01403509 0.01754386
 [7] 0.01754386 0.01754386 0.01754386 0.01754386 0.01754386 0.01052632

$mids
 [1]  2.5  7.5 12.5 17.5 22.5 27.5 32.5 37.5 42.5 47.5 52.5 57.5

$xname
[1] "database$Nº"

$equidist
[1] TRUE

attr(,"class")
[1] "histogram"
#**********************************************************************
dev.off()
null device 
          1 
print(paste("Finalizado procesamiento de",archivo," ",time, sep=""))
[1] "Finalizado procesamiento dehistograma 2021-10-09 17-19-51"
#**********************************************************************
citation()

To cite R in publications use:

  R Core Team (2021). R: A language and environment for statistical
  computing. R Foundation for Statistical Computing, Vienna, Austria.
  URL https://www.R-project.org/.

A BibTeX entry for LaTeX users is

  @Manual{,
    title = {R: A Language and Environment for Statistical Computing},
    author = {{R Core Team}},
    organization = {R Foundation for Statistical Computing},
    address = {Vienna, Austria},
    year = {2021},
    url = {https://www.R-project.org/},
  }

We have invested a lot of time and effort in creating R, please cite
it when using it for data analysis. See also ‘citation("pkgname")’
for citing R packages.
citation("readxl") 

To cite package ‘readxl’ in publications use:

  Hadley Wickham and Jennifer Bryan (2019). readxl: Read Excel Files.
  R package version 1.3.1. https://CRAN.R-project.org/package=readxl

A BibTeX entry for LaTeX users is

  @Manual{,
    title = {readxl: Read Excel Files},
    author = {Hadley Wickham and Jennifer Bryan},
    year = {2019},
    note = {R package version 1.3.1},
    url = {https://CRAN.R-project.org/package=readxl},
  }
# 
help("readxl") # Documentacion de la library readxl
LS0tDQp0aXRsZTogIlJlYWQgR29vZ2xlIFNoZWV0LCBHR3Bsb3QyLCBRdWVyeSBTUUwgZW4gIFIgTm90ZWJvb2sgKHBpdm90IHRhYmxlKSwgYnVjbGUgZm9yICYgZnVuY2lvbmVzLCBARUNSJ3MgTWFzdGVyIFIgTm90ZWJvb2sgVGVtcGxhdGUgMjAyMS1JSSINCmF1dGhvcjogIkluZy4gRXJuZXN0byBDYW5jaG8tUm9kcmlndWV6LCBNQkEgR2VvcmdlIFdhc2hpbmd0b24gVW5pdmVyc2l0eSINCmVtYWlsOiAiZXJuZXN0by5jYW5jaG9AdW5tc20uZWR1LnBlIg0KZGF0ZTogIjIwMjEuMTAuMDkiDQpvdXRwdXQ6DQogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQNCiAgcGRmX2RvY3VtZW50OiBkZWZhdWx0DQogIGh0bWxfZG9jdW1lbnQ6DQogICAgZGZfcHJpbnQ6IHBhZ2VkDQogIHdvcmRfZG9jdW1lbnQ6IGRlZmF1bHQNCi0tLQ0KDQpQcmltZXJvIGxhIFNlY2Npw7NuIGRlIExpYnJlcsOtYXMgZGUgRnVuY2lvbmVzOiANCg0KYGBge3IgSU5TVEFMQUNJT04gTElCUkVSSUFTIH0NCiMgcm93bmFtZXMoaW5zdGFsbGVkLnBhY2thZ2VzKCkpDQpsaXN0Lm9mLnBhY2thZ2VzIDwtIGMoDQoiYXJtIiAsIA0KImJyb29tIiAsIA0KImNvcnJwbG90IiAsIA0KImNvd3Bsb3QiICwgDQoiZGF0YXNldHMiICwgDQoiZGF0YXNldHMiICwgDQoiZHBseXIiICwgDQoiZWVwdG9vbHMiICwgDQoiZXN0aW1hdHIiICwgDQoiRmluQ2FsIiAsIA0KImZvcm1hdFIiICwgDQoiZ2dmb3J0aWZ5IiAsIA0KImdncHViciIgLCANCiJoYXZlbiIgLCANCiJIbWlzYyIgLCANCiJpbmZlciIgLCANCiJrbml0ciIgLCANCiJsbXRlc3QiICwgDQoibWFyZ2lucyIgLCANCiJueWNmbGlnaHRzMTMiICwgDQoicHN5Y2giICwgDQoicmVhZHhsIiAsIA0KInJlc2hhcGUyIiAsIA0KInJtcyIgLCANCiJza2ltciIgLCANCiJzdGFyZ2F6ZXIiICwgDQoic3RyaW5nciIgLCANCiJzdXJ2aXZhbCIgLCANCiJ0YWJsZW9uZSIgLCANCiJ0aWR5ciIgLCANCiJ0aWR5dmVyc2UiICwgDQoiVFRSIiAsIA0KIndvb2xkcmlkZ2UiICwgDQoieGxzeCIsDQojIEFkaWNpb25hbGVzIE9jdHVicmUgMjAyMToNCiJzcWxkZiIsICMgUGFyYSBTUUwgZW4gUg0KIlJPREJDIiwgICMgUGFyYSBDb25leGlvbiBTUUwgeSBSIFN0dWRpbw0KIyBBZGljaW9uYWxlcyA5IE9jdHVicmUgMjAyMToNCiJyZWFkciIsDQoiZGV2dG9vbHMiLA0KImdvb2dsZWRyaXZlIg0KKQ0KaGFzICAgPC0gbGlzdC5vZi5wYWNrYWdlcyAlaW4lIHJvd25hbWVzKGluc3RhbGxlZC5wYWNrYWdlcygpKQ0KaWYoYW55KCFoYXMpKSBpbnN0YWxsLnBhY2thZ2VzKGxpc3Qub2YucGFja2FnZXNbIWhhc10pDQoNCmBgYA0KDQoNCkxsYW1hZGEgYSBMSUJSRVJJQVM6DQpgYGB7ciBMTEFNQURBIEEgTElCUkVSSUFTfQ0KIyBsaWJyYXJ5KGFybSkgDQojIGxpYnJhcnkoYnJvb20pIA0KIyBsaWJyYXJ5KGNvcnJwbG90KSANCiMgbGlicmFyeShjb3dwbG90KSANCiMgbGlicmFyeShkYXRhc2V0cykgDQpsaWJyYXJ5KGRwbHlyKSANCiMgbGlicmFyeShlZXB0b29scykgDQojIGxpYnJhcnkoZXN0aW1hdHIpIA0KbGlicmFyeShGaW5DYWwpIA0KIyBsaWJyYXJ5KGZvcm1hdFIpIA0KIyBsaWJyYXJ5KGdnZm9ydGlmeSkgDQojIGxpYnJhcnkoZ2dwdWJyKSANCiBsaWJyYXJ5KGdncGxvdDIpIA0KIGxpYnJhcnkoaGF2ZW4pICNwYXJhIGxhIGxlY3R1cmEgZGUgYXJjaGl2b3MgRFRBIGRlIFN0YXRhDQojIGxpYnJhcnkoSG1pc2MpIA0KIyBsaWJyYXJ5KGluZmVyKSANCiMgbGlicmFyeShrbml0cikgDQojIGxpYnJhcnkobG10ZXN0KSANCiMgbGlicmFyeShtYXJnaW5zKSANCiMgbGlicmFyeShueWNmbGlnaHRzMTMpIA0KIyBsaWJyYXJ5KHBzeWNoKSANCmxpYnJhcnkocmVhZHhsKSANCmxpYnJhcnkocmVzaGFwZTIpICNwYXJhIGhhY2VyIFJlU2hhcGUgKFBpdm90IFRhYmxlcykNCiMgbGlicmFyeShybXMpIA0KIyBsaWJyYXJ5KHNraW1yKSANCiMgbGlicmFyeShzdGFyZ2F6ZXIpIA0KIyBsaWJyYXJ5KHN0cmluZ3IpIA0KIyBsaWJyYXJ5KHN1cnZpdmFsKSANCiMgbGlicmFyeSh0YWJsZW9uZSkgDQpsaWJyYXJ5KHRpZHlyKSAjcGFyYSBoYWNlciBSZVNoYXBlIChQaXZvdCBUYWJsZXMpDQpsaWJyYXJ5KHRpZHl2ZXJzZSkgDQpsaWJyYXJ5KFRUUikgI3BhcmEgbGFzIGdyYWZpY2FzIGRlIHNlcmllcyBkZSB0aWVtcG8NCiMgbGlicmFyeSh3b29sZHJpZGdlKSANCmxpYnJhcnkoeGxzeCkgI3BhcmEgZXhwb3J0YXIgYSBFeGNlbCBmaWxlDQoNCiMgQWRpY2lvbmFsZXMgT2N0dWJyZSAyMDIxOg0KbGlicmFyeShzcWxkZikgIyBQYXJhIFNRTCBlbiBSDQpsaWJyYXJ5KFJPREJDKSAjIFBhcmEgQ29uZXhpb24gU1FMIHkgUiBTdHVkaW8NCiMgQWRpY2lvbmFsZXMgOSBPY3R1YnJlIDIwMjE6DQpsaWJyYXJ5KHJlYWRyKQ0KbGlicmFyeShkZXZ0b29scykNCmxpYnJhcnkoZ29vZ2xlZHJpdmUpDQpgYGANCg0KDQpBIHBhcnRpciBkZSBhcXXDrSBsYSBTZWNjacOzbiBkZSBJbXBvcnRhY2nDs24gZGUgRGF0YXNldHM6DQpgYGB7ciBEQVRBIH0NCnByaW50KCJXb3JraW5nIERpcmVjdG9yeTogIik7IGdldHdkKCkgI2dldCB0byBzaG93IG1lIHRoZSBjdXJyZW50IFdvcmtpbmcgRGlyZWN0b3J5IA0KIyMjIENhcmdhbmRvIEJCREQ6IG41YXk1cWFkZmU3ZTFubnN2NXMwMW9lMXg2Mm1xNTFqLmNzdiAjIyMjDQojIFZlcnNpb24gZGUgQkJERDogMjAyMS4wOS4yNCB2MQ0KIyBSVVRBOiBodHRwczovL2libS5ib3guY29tL3NoYXJlZC9zdGF0aWMvDQoNCiMgWExTIGZpbGUsICBEb3dubG9hZCBkYXRhc2V0cw0KIyBkb3dubG9hZC5maWxlKCAiaHR0cHM6Ly9pYm0uYm94LmNvbS9zaGFyZWQvc3RhdGljL254MG9oZDlzcTBpejNwODcxemc4ZWhjMW0zOWlicHg2LnhscyIgLCANCiMgICAgICAgICAgICAgICAgZGVzdGZpbGU9Im1vdmllcy1kYi54bHMiICkNCg0KIyBDU1YgZmlsZSwgIERvd25sb2FkIGRhdGFzZXRzDQpkb3dubG9hZC5maWxlKCJodHRwczovL2libS5ib3guY29tL3NoYXJlZC9zdGF0aWMvbjVheTVxYWRmZTdlMW5uc3Y1czAxb2UxeDYybXE1MWouY3N2IiwgDQogICAgICAgICAgICAgIGRlc3RmaWxlPSJtb3ZpZXMtZGIuY3N2IikNCmRhdGFiYXNlX2NzdiA8LSByZWFkLmNzdigibW92aWVzLWRiLmNzdiIsIGhlYWRlcj1UUlVFLCBzZXA9IiwiKQ0KDQpmaWxlLmV4aXN0cygibW92aWVzLWRiLnhsc3giKQ0KIyBSZWFkIGRhdGEgZnJvbSB0aGUgWExTIGZpbGUgYW5kIGF0dHJpYnV0ZSB0aGUgdGFibGUgYSBkYXRhZnJhbWUuDQpkYXRhYmFzZV94bHN4IDwtIHJlYWRfZXhjZWwoIm1vdmllcy1kYi54bHN4IikNCmRhdGFiYXNlX3hsc3gNCg0KI21vdmllc19kYXRhDQooDQpkYXRhYmFzZSA8LSBkYXRhYmFzZV94bHN4DQopDQoNCiMgUmVhZCBkYXRhIGZyb20gdGhlIFhMUyBmaWxlIGFuZCBhdHRyaWJ1dGUgdGhlIHRhYmxlIHRvIGEgZGF0YWZyYW1lLg0KcGFpc2VzXzAwMS54bHN4IDwtIHJlYWRfZXhjZWwoInBhaXNlc18wMDEueGxzeCIpDQpwYWlzZXNfMDAxLnhsc3gNCg0KYGBgDQoNCg0KYGBge3IgU2VuZCB0byB0aGUgZGF0YWZyYW1lIGRhdGFiYXNlfQ0KI21vdmllc19kYXRhDQooDQpkYXRhYmFzZSA8LSBwYWlzZXNfMDAxLnhsc3gNCikNCg0KYGBgDQoNClRvIGRvd25sb2FkIGEgR29vZ2xlIFNoZWV0IG9ubGluZSBmcm9tIEdvb2dsZSBEcml2ZSBpbnRvIGEgZGF0YWZyYW1lIGluIFI6DQpgYGB7ciBSZWFkIEdvb2dsZSBTaGVldH0NCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMtIEdvb2dsZVNoZWV0NA0KIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KI2luc3RhbGwucGFja2FnZXMoImRldnRvb2xzIikNCmxpYnJhcnkoZGV2dG9vbHMpDQojZGV2dG9vbHM6Omluc3RhbGxfZ2l0aHViKCJ0aWR5dmVyc2UvZ29vZ2xlc2hlZXRzNCIpDQoNCiNpbnN0YWxsLnBhY2thZ2VzKCJnYXJnbGUiKQ0KbGlicmFyeShnb29nbGVzaGVldHM0KQ0KDQpnczRfYXV0aCgpDQojaGVscChnczRfYXV0aCkNCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMNCiMtIFJlYWQgYW4gZXhpc3RpbmcgU3ByZWFkc2hlZXQgDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIw0KDQpkYXRhX3RvX3dyaXRlIDwtIHJlYWRfc2hlZXQoImh0dHBzOi8vZG9jcy5nb29nbGUuY29tL3NwcmVhZHNoZWV0cy9kLzFDbS1WUkhyVURsR0ZrZTRkX3drQ2lMLWh0dDBjdEJfcDdvUG42UGw2WUVjIikNCmRhdGFfdG9fd3JpdGUNCmBgYA0KDQoNClRvIGRvd25sb2FkIGEgQ1NWIGZpbGUgZnJvbSBHb29nbGUgRHJpdmUgKGVzdMOhIHZpZW5kb3NlIHNpbiBVVEYtOChhY2VudG9zLCBlw7FlKSBzaSBsbyBhYnJvIGVuIEV4Y2VsLCBkZWJlIGRlIGluc2VydGFyc2UgY29uIGxsYW1hZGEgZGUgZGF0b3MgYWwgZmlsZSBDU0NWKToNCmBgYHtyIFJlYWQgQ1NWIGZyb20gRHJpdmV9DQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQojLSBEb3dubG9hZGluZyBhIHNwcmVhZHNoZWV0IGZpbGUgYXMgYSBjc3YgDQojIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjDQp0YXJnZXQgPC0gZHJpdmVfZ2V0KCAiaHR0cHM6Ly9kb2NzLmdvb2dsZS5jb20vc3ByZWFkc2hlZXRzL2QvMUNtLVZSSHJVRGxHRmtlNGRfd2tDaUwtaHR0MGN0Ql9wN29QbjZQbDZZRWMiICkNCmRyaXZlX2Rvd25sb2FkKCB0YXJnZXQgLCANCiAgICAgICAgICAgICAgICB0eXBlPSAiY3N2IiAsIA0KICAgICAgICAgICAgICAgIHBhdGggPSAicGFpc2VzXzAwMV9Hb29nbGVTaGVldC5jc3YiICwNCiAgICAgICAgICAgICAgICBvdmVyd3JpdGUgPSBUUlVFICkNCg0KYGBgDQoNClJlYWQgZGF0YSBmcm9tIEdvb2dsZSBEcml2ZSAodGhlIFpJUCBmaWxlKSBhbmQgYXR0cmlidXRlIHRoZSB0YWJsZSB0byBhIGRhdGFmcmFtZS4NCmBgYHtyIFJlYWQgWklQIHdpdGggQ1NWIGZpbGUgZnJvbSBHb29nbGUgRHJpdmV9DQojIGh0dHBzOi8vZG9jcy5nb29nbGUuY29tL3NwcmVhZHNoZWV0cy9kLzFQaU5xN2kwY1hFaHZYQXBSQ3Z2aDNGVURyRjJrR2V1YS9lZGl0P3VzcD1zaGFyaW5nJm91aWQ9MTA5NjM2MzA3NTY5NjU1NjYxMzE1JnJ0cG9mPXRydWUmc2Q9dHJ1ZQ0KIyBSZWFkIGRhdGEgZnJvbSBHb29nbGUgRHJpdmUgKHRoZSBaSVAgZmlsZSkgYW5kIGF0dHJpYnV0ZSB0aGUgdGFibGUgdG8gYSBkYXRhZnJhbWUuDQpsaWJyYXJ5KGdvb2dsZWRyaXZlKQ0KbGlicmFyeShodHRwdXYpDQp0ZW1wIDwtIHRlbXBmaWxlKCBmaWxlZXh0ID0gIi56aXAiICkNCnRlbXANCmRsIDwtIGRyaXZlX2Rvd25sb2FkKA0KICAgICAgICAgYXNfaWQoICIxQWlaZGFfMS0ybndyeEk4ZkxEMFk2ZTVyVGc3YW9jdjAiICkgLCANCiAgICAgICAgIHBhdGggPSB0ZW1wICwgb3ZlcndyaXRlID0gVFJVRSApDQpkbA0Kb3V0IDwtIHVuemlwKCB0ZW1wICwgZXhkaXIgPSB0ZW1wZGlyKCkgKQ0Kb3V0DQpiYW5rIDwtIHJlYWQuY3N2KCBvdXRbMTRdICwgc2VwID0gIjsiICkNCnN0cihiYW5rKQ0KYmFuaw0KDQpgYGANCg0KDQpSZWFkaW5nIGZpbGUgZnJvbSBhIENTViBmaWxlOg0KYGBge3IgUkVBRCBDU1Z9DQojIFJlYWQgZGF0YSBmcm9tIHRoZSBUWFQgIGZpbGUgYW5kIGF0dHJpYnV0ZSB0aGUgdGFibGUgdG8gYSBkYXRhZnJhbWUuDQpwYWlzZXNfMDAxLmNzdiA8LSByZWFkLmNzdigicHJ1ZWJhX2NzdjAxLmNzdiIsIGhlYWRlcj1UUlVFLCBzZXA9IjsiKQ0KcGFpc2VzXzAwMS5jc3YNCmBgYA0KDQpSZWFkaW5nIGZpbGUgZnJvbSBhIFRYVCBmaWxlOg0KYGBge3IgUkVBRCBUWFR9DQojIFJlYWQgZGF0YSBmcm9tIHRoZSBUWFQgIGZpbGUgYW5kIGF0dHJpYnV0ZSB0aGUgdGFibGUgdG8gYSBkYXRhZnJhbWUuDQpwYWlzZXNfMDAxLnR4dCA8LSByZWFkX2NzdigicGFpc2VzXzAwMS50eHQiKQ0KcGFpc2VzXzAwMS50eHQNCmBgYA0KDQpgYGB7ciBSZWFkIFNQU1MgZmlsZX0NCiNsaWJyYXJ5KGhhdmVuKQ0KQmFzZUNPVklEMTkuc2F2IDwtIHJlYWRfc2F2KCJCYXNlQ09WSUQtMTkuc2F2IikNCkJhc2VDT1ZJRDE5LnNhdg0KDQpgYGANCg0KYGBge3IgUmVhZCBTVEFUQSBmaWxlc30NCiNsaWJyYXJ5KGhhdmVuKQ0KZW5haG8wMS5kdGEgPC0gcmVhZF9kdGEoImVuYWhvMDEtMjAyMC0xMDAuZHRhIikNCmVuYWhvMDEuZHRhDQoNCmBgYA0KDQoNClJFVklTSU9OIFJBUElEQSBERUwgREFUQUZSQU1FOg0KYGBge3J9DQojVmlldyhkYXRhYmFzZSkNCnN1bW1hcnkoZGF0YWJhc2UpICMgU3VtbWFyeSBFc3RhZMOtc3RpY28uDQpoZWFkKGRhdGFiYXNlKSAjIFByaW1lcm9zIDYuDQpuYW1lcyhkYXRhYmFzZSkgIyBOYW1lcyBkZSBjb2x1bW5hcy4NCnByaW50KGlzLmRhdGEuZnJhbWUoZGF0YWJhc2UpKQ0KI2F0dGFjaChkYXRhYmFzZSkgI29ubHkgaWYgdGhlcmUgaXMgb25seSAxIGRhdGFzZXQgDQojIENPTlRFTklETyBERSBUQUJMQToNCiMgZGF0YWJhc2UgZXMgbGEgdGFibGEgY29uIGRhdG9zIGRlIHBlbMOtY3VsYXMuDQpgYGANCg0KQU5BTElaQU1PUyBMQSBFU1RSQ1VUVVJBIERFIExBIFRBQkxBOg0KDQpGdW5jacOzbiBzdHI6IHN0cnVjdHVyZQ0KTGFiMDgtaW1wb3J0aW5nRGF0YSANCmBgYHtyIENVRVJQT30NCg0KIyBQcmludHMgb3V0IHRoZSBzdHJ1Y3R1cmUgb2YgeW91ciB0YWJsZS4NCnN0cihkYXRhYmFzZSkgIyBlcyBsYSBmdW5jacOzbiBzdHJ1Y3R1cmUNCg0KDQpgYGANCg0KDQpBIHBhcnRpciBkZSBhcXXDrSBpbmljaWEgZWwgQ3VlcnBvIGRlbCBTY3JpcHQ6DQoNCkVKRVJDSUNJTyBGVU5DSU9ORVMgUFJPUElBUyBFTiBSDQpgYGB7cn0NCiMgVURGIC0gVXNlciBEZWZpbmVkIEZ1bmN0aW9ucw0KDQpzdW0oIDExMSAsIDIyMiApDQpwcm9kKCAxMTEgLCAyMjIgKQ0KbG9nKCA4ICwgMiApDQoNCiMgbGlicmFyeShnZ3Bsb3QyKQ0KIyBnZ3Bsb3QoKQ0KDQoNCiNJbmNyZW1lbnRvIFBvcmNlbnR1YWwNCiggDQpJbXBvcnRlIDwtIDI1Ng0KKQ0KKA0KSW1wdWVzdG8gPC0gMy4yLzEwMA0KKQ0KKA0KUHJlY2lvLmRlLlZlbnRhIDwtIEltcG9ydGUgKiAoIDErSW1wdWVzdG8gKQ0KKQ0KKA0KVmFyaWFjacOzbiA8LSBQcmVjaW8uZGUuVmVudGEvSW1wb3J0ZSAtIDENCikNCg0KIyBGdW5jdGlvbiBJbmNyZWFzZV9wZXJjZW50YWplDQpJbmNyZWFzZV9wZXJjZW50YWplIDwtIGZ1bmN0aW9uKCBJbXBvcnRlICwgUHJjX0ltcHVlc3RvICl7DQogIFByZWNpby5kZS5WZW50YSA8LSBJbXBvcnRlICogKCAxK1ByY19JbXB1ZXN0by8xMDAgKQ0KICBQcmVjaW8uZGUuVmVudGEgPC0gcm91bmQoIFByZWNpby5kZS5WZW50YSAsIDIgKQ0KICANCiAgcHJpbnQoIHBhc3RlKCAiSW5jcmVhc2luZyAiLCBJbXBvcnRlICwNCiAgICAgICAgICAgICAgICAiIGVuICIsIFByY19JbXB1ZXN0byAsIA0KICAgICAgICAgICAgICAgICIlIHJlc3VsdGEgZW46ICIsIFByZWNpby5kZS5WZW50YSAsICIgVVNELiIsDQogICAgICAgICAgICAgICAgc2VwID0gIiIgKSkNCiAgcmV0dXJuKFByZWNpby5kZS5WZW50YSkNCn0NCg0KI0xsYW1hciBhIGxhIGZ1bmN0aW9uDQpQcmVjaW8uZGUuVmVudGEuMSA8LSBJbmNyZWFzZV9wZXJjZW50YWplKCAyNTYgLCAzLjIgKSANClByZWNpby5kZS5WZW50YS4xDQoNCmBgYA0KDQpPVFJBIEZVTkNJT046DQpgYGB7cn0NCiMgRnVuY3Rpb24gSW5jcmVhc2VfcGVyY2VudGFqZTINCkluY3JlYXNlX3BlcmNlbnRhamUyIDwtIGZ1bmN0aW9uKCBJbXBvcnRlICwgUHJjX0ltcHVlc3RvICl7DQogIFByZWNpby5kZS5WZW50YSA8LSBJbXBvcnRlICogKCAxK1ByY19JbXB1ZXN0by8xMDAgKQ0KICBQcmVjaW8uZGUuVmVudGEgPC0gcm91bmQoIFByZWNpby5kZS5WZW50YSAsIDIgKQ0KICANCiAgaWYoIEltcG9ydGUgPD0gMCApew0KICAgIHByaW50KCJFcnJvci4gSW1wb3J0ZSA8PSAwLiIpDQogICAgcmV0dXJuKE5VTEwpDQogIH1lbHNlIGlmKCBQcmNfSW1wdWVzdG8gPD0gMCApew0KICAgIHByaW50KCJFcnJvci4gUHJjX0ltcHVlc3RvIDw9IDAuIikNCiAgICByZXR1cm4oTlVMTCkNCiAgfWVsc2V7DQogIA0KICBwcmludCggcGFzdGUoICJJbmNyZWFzaW5nICIsIEltcG9ydGUgLA0KICAgICAgICAgICAgICAgICIgZW4gIiwgUHJjX0ltcHVlc3RvICwgDQogICAgICAgICAgICAgICAgIiUgcmVzdWx0YSBlbjogIiwgUHJlY2lvLmRlLlZlbnRhICwgIiBVU0QuIiwNCiAgICAgICAgICAgICAgICBzZXAgPSAiIiApKQ0KICByZXR1cm4oUHJlY2lvLmRlLlZlbnRhKQ0KICB9DQp9DQojTGxhbWFyIGEgbGEgZnVuY3Rpb24NClByZWNpby5kZS5WZW50YS4xIDwtIEluY3JlYXNlX3BlcmNlbnRhamUyKCAyNTYgLCAzLjIgKSANCnN0cihQcmVjaW8uZGUuVmVudGEuMSkNCiNQcmVjaW8uZGUuVmVudGEuMQ0KUHJlY2lvLmRlLlZlbnRhLjIgPC0gSW5jcmVhc2VfcGVyY2VudGFqZTIoIC0yNTYgLCAzLjIgKSANCnN0cihQcmVjaW8uZGUuVmVudGEuMikNCiNQcmVjaW8uZGUuVmVudGEuMg0KUHJlY2lvLmRlLlZlbnRhLjMgPC0gSW5jcmVhc2VfcGVyY2VudGFqZTIoIDI1NiAsIC0zLjIgKSANCnN0cihQcmVjaW8uZGUuVmVudGEuMykNCiNQcmVjaW8uZGUuVmVudGEuMg0KYGBgDQoNCkVKRU1QTE8gQlVDTEUgRk9SOg0KYGBge3J9DQpmb3IoIGkgaW4gMTo1KXsNCiAgcHJpbnQoIGleMiApDQp9DQoNClZlY3Rvci4xYTUgPC0gYygxOjUpDQojVmVjdG9yLjFhNQ0KVmVjdG9yLjFhNV4yDQoNCmZvciggaSBpbiBWZWN0b3IuMWE1ICl7DQogIHByaW50KCBpXjIgKQ0KfQ0KDQpEYXRhZnJhbWUuMWE1IDwtIGFzLmRhdGEuZnJhbWUoIGMoMTo1KSApDQojRGF0YWZyYW1lLjFhNQ0KbmFtZXMoRGF0YWZyYW1lLjFhNSkNCkRhdGFmcmFtZS4xYTUkYw0KZm9yKCBpIGluIERhdGFmcmFtZS4xYTUkYyApew0KICBwcmludCggaV4yICkNCn0gIA0KDQpgYGANCg0KDQoNCmBgYHtyfQ0KI2hlbHAoInNxbGRmIikNCg0KbXRjYXJzDQojVmlldyhtdGNhcnMpDQoNCmBgYA0KDQpgYGB7cn0NCmRmX3F1ZXJ5IDwtIHNxbGRmKCJzZWxlY3QgKiBmcm9tIG10Y2FycyIpDQpkZl9xdWVyeQ0KI3N0cihkZl9xdWVyeSkNCg0KYGBgDQpgYGB7cn0NCnNxbGRmKCJTRUxFQ1QgY3lsICwgY291bnQoIGN5bCApIGFzIENpbGluZHJvcyBGUk9NIG10Y2FycyBHUk9VUCBCWSBjeWwgIikNCmBgYA0KDQpgYGB7cn0NCmRmX3Bpdm90X3NxbCA8LSBzcWxkZiggIiBTRUxFQ1QgY3lsICwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIENPVU5UKCBjeWwgKSBhcyBDaWxpbmRyb3MgDQogICAgICAgICAgICAgICAgICAgICAgICAgRlJPTSBtdGNhcnMgDQogICAgICAgICAgICAgICAgICAgICAgICAgR1JPVVAgQlkgY3lsICIpDQpkZl9waXZvdF9zcWwNCmBgYA0KDQpFSkVSQ0lDSU9TIEFESUNJT05BTEVTIENPTiBtdGNhcnM6DQoNCmBgYHtyfQ0KI210Y2Fycw0KdGFibGEuMSA8LSB0YWJsZSggbXRjYXJzJGN5bCApDQojdGFibGEuMQ0KDQpjb2xvcmVzIDwtIGMoICJvcmFuZ2UiICwgDQogICAgICAgICAgICAgICJncmVlbiIgLCANCiAgICAgICAgICAgICAgInllbGxvdyIgKQ0KI2NvbG9yZXMNCg0KcGxvdC4xIDwtIGJhcnBsb3QoIHRhYmxhLjEgLCANCiAgICAgICAgICAgICAgICAgICB4bGFiID0gIkNpbGluZHJvcyIgLCANCiAgICAgICAgICAgICAgICAgICB5bGFiID0gIkZyZXF1ZW5jaWEiICwgDQogICAgICAgICAgICAgICAgICAgbWFpbiA9ICJOcm8gZGUgQ2lsaW5kcm9zIiAsDQogICAgICAgICAgICAgICAgICAgY29sID0gY29sb3JlcyApDQpwbG90LjENCmBgYA0KDQpDT05USU5VQUNJT04gQ09OIG10Y2FycyA6IA0KDQpgYGB7cn0NCg0KcGxvdC4yIDwtIGdncGxvdCggbXRjYXJzICwNCiAgICAgICAgICAgICAgICAgIGFlcyggY3lsICkpICsNCiAgICAgICAgICBnZW9tX2JhciggZmlsbCA9IGNvbG9yZXMgKSArIA0KICAgICAgICAgIGxhYnMoIHg9ICJDaWxpbmRyb3MiICwgDQogICAgICAgICAgICAgICAgeSA9ICJGcmVjdWVuY2lhcyIgLCANCiAgICAgICAgICAgICAgICB0aXRsZSA9ICJOdW1lcm8gZGUgQ2lsaW5kcm9zIikNCnBsb3QuMiAgDQogIA0KYGBgDQoNCg0KDQpSRVBBU08gREUgTUFUUklDRVM6DQpgYGB7cn0NCm1hdHJpeC4xIDwtIG1hdHJpeCggMToxMCAsIA0KICAgICAgICAgICAgbnJvdyA9IDUgLCANCiAgICAgICAgICAgIG5jb2wgPSA0ICkNCm1hdHJpeC4xDQoNCmRpbShtYXRyaXguMSkNCg0KbWF0cml4LjFbMiw0XQ0KbWF0cml4LjFbMiwgXQ0KbWF0cml4LjFbICw0XQ0KZGZfbWF0cml4LjEgPC0gYXMuZGF0YS5mcmFtZSggbWF0cml4LjEgLCByb3cubmFtZXMgPSBOVUxMLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbmFsID0gRkFMU0UgLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ha2UubmFtZXMgPSBUUlVFICwgDQogICAgICAgICAgICAgICBzdHJpbmdzQXNGYWN0b3JzID0gZGVmYXVsdC5zdHJpbmdzQXNGYWN0b3JzKCkgKQ0KI2RmX21hdHJpeC4xDQojZGZfbWF0cml4LjEkVjQNCmRmX21hdHJpeC4xWydWNCddDQoNCmBgYA0KDQoNCg0KRUpFUkNJQ0lPUzoNCg0KDQpgYGB7cn0NCnN1bW1hcnkoZGF0YWJhc2UpDQptYXRyaXhfc3VtbWFyeSA8LSBkby5jYWxsKGNiaW5kLCBsYXBwbHkoZGF0YWJhc2UsIHN1bW1hcnkpKQ0KbWF0cml4X3N1bW1hcnkNCnN0cihtYXRyaXhfc3VtbWFyeSkNCmRmX3N1bW1hcnkgPC0gYXMuZGF0YS5mcmFtZShtYXRyaXhfc3VtbWFyeSwgcm93Lm5hbWVzID0gTlVMTCwgb3B0aW9uYWwgPSBGQUxTRSwNCiAgICAgICAgICAgICAgbWFrZS5uYW1lcyA9IFRSVUUsIA0KICAgICAgICAgICAgICBzdHJpbmdzQXNGYWN0b3JzID0gZGVmYXVsdC5zdHJpbmdzQXNGYWN0b3JzKCkpDQpkZl9zdW1tYXJ5DQoNCnN1bW1hcnkoIGRhdGFiYXNlJGNvc3RfbWlsbGlvbnMgKQ0KDQojIFJldHJpZXZlIGEgc3Vic2V0X2RhdGFmcmFtZSBvZiB0aGUgZGF0YSBmcmFtZSBjb25zaXN0aW5nIG9mIHRoZSAiZ2VucmUiIGNvbHVtbnMNCmRhdGFiYXNlWydQQUlTJ10NCg0KIyBSZXRyaWV2ZSB0aGUgZGF0YSBmb3IgdGhlICJuYW1lIiBjb2x1bW4gaW4gdGhlIGRhdGEgZnJhbWUgaW4gYSB2ZWN0b3INCmRhdGFiYXNlJFBBSVMNCg0KYGBgDQoNCmBgYHtyfQ0KIyBSZXRyaWV2ZSB0aGUgM3JkIHJvdyBvZiB0aGUgZGF0YSBmcmFtZS4NCmRhdGFiYXNlWzMsXQ0KDQojIFJldHJpZXZlIHRoZSB0aGlyZCByb3cgb2YgdGhlIGRhdGEgZnJhbWUsIGJ1dCBvbmx5IHRoZSAibmFtZSIgYW5kICJsZW5ndGhfbWluIiBjb2x1bW5zLg0KZGF0YWJhc2VbMywgYygiUEFJUyIsIkNPRElHTyIpXQ0KYGBgDQpgYGB7cn0NCg0Kc3VtbWFyeShkYXRhYmFzZSkNCmhpc3RvZ3JhbWEgPC0gaGlzdChkYXRhYmFzZSROwrogLGNvbD0ieWVsbG93IixicmVha3MgPSAxMCkNCmhpc3RvZ3JhbWENCmBgYA0KYGBge3J9DQoNCnRpbWUgPSBnc3ViKCI6IiwgIi0iLCBTeXMudGltZSgpKQ0KDQojLSBleHBvcnRhIGVuIGZvcm1hdG8gLmNzdiBlbCBkZiBkZl9zdW1tYXJ5IGFsIGZpY2hlcm8gImRmX3N1bW1hcnkuY3N2Ii4gU2UgZ3VhcmRhcsOhIGVuIGxhIHN1YmNhcnBldGEgImRhdG9zL3BydWViYXMvIiBkZWwgcHJveWVjdG8NCmZvbGRlcl9wYXRoIDwtICIuL291dHB1dF9kYXRhYmFzZXMvIg0KZmlsZW5hbWUgPC0gImRmX3N1bW1hcnkiDQpmaWxldHlwZSA8LSIuY3N2Ig0KcGF0aCA8LSBwYXN0ZShmb2xkZXJfcGF0aCxmaWxlbmFtZSwiICIsdGltZSxmaWxldHlwZSwgc2VwPSIiKQ0Kd3JpdGVfY3N2KGRmX3N1bW1hcnksIHBhdGgpDQoNCg0KYGBgDQpIYXkgdmFyaW9zIHBhY2thZ2VzIHF1ZSBncmFiYW4gZGF0b3MgZW4gZm9ybWF0byAueGxzLiBQZXJvIGVsIG3DoXMgc2VuY2lsbG8gZXMgZWwgcGFja2FnZSB4bHN4LiBWZcOhbW9zbG86DQpgYGB7cn0NCiMgaW5zdGFsbC5wYWNrYWdlcygieGxzeCIpDQojIGxpYnJhcnkoeGxzeCkNCndyaXRlLnhsc3goZGZfc3VtbWFyeSwgIi4vb3V0cHV0X2RhdGFiYXNlcy9kZl9zdW1tYXJ5Lnhsc3giLCBzaGVldE5hbWUgPSAiZGZfc3VtbWFyeSIgKQ0KDQpgYGANCg0KTGEgZnVuY2nDs24gd3JpdGUueGxzeCgpIHBlcm1pdGUgYcOxYWRpciBkYXRvcyBhIHVuIGFyY2hpdm8gLnhsc3ggcHJlZXhpc3RlbnRlOyBwYXJhIGVsbG8gdGVuZW1vcyBxdWUgdXNhciBsYSBvcGNpw7NuIGFwcGVuZCA9IFRSVUU6DQpgYGB7cn0NCiMgbGlicmFyeSh4bHN4KQ0Kd3JpdGUueGxzeChkZl9zdW1tYXJ5LCAiLi9vdXRwdXRfZGF0YWJhc2VzL2RmX3N1bW1hcnkueGxzeCIsIHNoZWV0TmFtZSA9ICJzdW1tYXJ5IiwgYXBwZW5kID0gVFJVRSkNCmBgYA0KDQoNCkRFTCBFSkVSQ0lDSU8gREUgRUpFQ1VUQVIgU1FMIFFVRVJZIGVuIFVOIFIgTk9URUJPT0s6DQpgYGB7cn0NCndyaXRlLnhsc3goIGRmX3Bpdm90X3NxbCAsIA0KICAgICAgICAgICAgIi4vb3V0cHV0X2RhdGFiYXNlcy9kZl9waXZvdF9zcWwueGxzeCIsIA0KICAgICAgICAgICAgc2hlZXROYW1lID0gImRmX3Bpdm90X3NxbCIgKQ0KYGBgDQoNCg0KDQoNCkdSQUZJQ0ENCmBgYHtyfQ0KIyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioNCiMqIyBQdWJsaWNhdGlvbiBxdWFsaXR5IGdyYXBocyByZXF1aXJlIDYwMGRwaQ0KZHBpPTYwMCAgICAjcGl4ZWxzIHBlciBzcXVhcmUgaW5jaA0KY2FycGV0YSA9ICIuL291dHB1dF9pbWFnZXMvIg0KYXJjaGl2byA9ICJoaXN0b2dyYW1hIg0KdGltZSA9IGdzdWIoIjoiLCAiLSIsIFN5cy50aW1lKCkpDQpjYXJwZXRhX3lfYXJjaGl2byA9IHBhc3RlKGNhcnBldGEsYXJjaGl2bywiICIsdGltZSwiLnRpZiIsIHNlcD0iIikNCm5vbWJyZV9kZV90aWYgPSBjYXJwZXRhX3lfYXJjaGl2bw0KdGlmZihub21icmVfZGVfdGlmLCB3aWR0aD02KmRwaSwgaGVpZ2h0PTUqZHBpLCByZXM9ZHBpKQ0KIyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioNCmhpc3RvZ3JhbWEgPC0gaGlzdChkYXRhYmFzZSROwrogLGNvbD0ieWVsbG93IixicmVha3MgPSAxMCkNCmhpc3RvZ3JhbWENCiMqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqDQpkZXYub2ZmKCkNCnByaW50KHBhc3RlKCJGaW5hbGl6YWRvIHByb2Nlc2FtaWVudG8gZGUiLGFyY2hpdm8sIiAiLHRpbWUsIHNlcD0iIikpDQojKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKg0KYGBgDQoNCmBgYHtyfQ0KY2l0YXRpb24oKQ0KY2l0YXRpb24oInJlYWR4bCIpIA0KIyANCmhlbHAoInJlYWR4bCIpICMgRG9jdW1lbnRhY2lvbiBkZSBsYSBsaWJyYXJ5IHJlYWR4bA0KDQpgYGA=