Vínculo de data frames

Contexto

Para este ejercicio vamos a hacer uso de varios archivos que ofrece el portal de datos abiertos del gobierno de México. Los datos a utilizar son los datos sobre migtración interna. Estos archivos muestran diversa información sobre las características de los migrantes y no migrantes para los años 1990-2010.

Primer paso: lectura de arhvios

Carga los archivos en dataframes. En primera instancia, guarda un archivo por variable.

Listado de documentos

  1. Migrantes_recientes_y_no_migrantes_por_grandes_grupos_de_edad_segun_entidad_federativa_1990_-*2010.csv
  2. Migrantes_recientes_y_no_migrantes_por_tipo_de_localidad_de_destino_segun_entidad_federativa_1990-2010.csv
  3. Migrantes_recientes_y_no_migrantes_por_nivel_educativo_segun_entidad_federativa_1990-2010.csv
  4. Migrantes_recientes_y_no_migrantes_por_condicion_de_actividad_economica_segun_entidad_federativa_1990-2010.csv
  5. Migrantes_recientes_por_condicion_de_habla_de_lengua_indigena_segun_entidad_federativa_1990*-_2010.csv
  6. Migrantes_recientes_y_no_migrantes_por_sexo_segun_entidad_federativa__1990_-_2010.csv

Código

En el siguiente bloque de código se hace uso de La función paste. Puedes encontrar más informaciónb acerca de esta función dando clic en el enlace o en la pestaña con su nombre.


dirraiz <- getwd() #Se obtiene el directorio de trabajo
nombresA = c(
  "Migrantes_recientes_por_condicion_de_habla_de_lengua_indigena_segun_entidad_federativa_1990_-_2010", 
             "Migrantes_recientes_y_no_migrantes_por_condicion_de_actividad_economica_segun_entidad_federativa_1990_-_2010",
  "Migrantes_recientes_y_no_migrantes_por_nivel_educativo_segun_entidad_federativa_1990_-_2010", 
  "Migrantes_recientes_y_no_migrantes_por_sexo_segun_entidad_federativa__1990_-_2010", "Migrantes_recientes_y_no_migrantes_por_tipo_de_localidad_de_destino_segun_entidad_federativa_1990_-_2010") # Vector temporal con los nombres de los documentos

paste(dirraiz, "/Ejercicio_datos/", nombresA, ".csv", sep = "") #Muestra del funcionamiento de paste
[1] "/Volumes/Perita/UAM/TPP/Ejercicio_datos/Migrantes_recientes_por_condicion_de_habla_de_lengua_indigena_segun_entidad_federativa_1990_-_2010.csv"          
[2] "/Volumes/Perita/UAM/TPP/Ejercicio_datos/Migrantes_recientes_y_no_migrantes_por_condicion_de_actividad_economica_segun_entidad_federativa_1990_-_2010.csv"
[3] "/Volumes/Perita/UAM/TPP/Ejercicio_datos/Migrantes_recientes_y_no_migrantes_por_nivel_educativo_segun_entidad_federativa_1990_-_2010.csv"                 
[4] "/Volumes/Perita/UAM/TPP/Ejercicio_datos/Migrantes_recientes_y_no_migrantes_por_sexo_segun_entidad_federativa__1990_-_2010.csv"                           
[5] "/Volumes/Perita/UAM/TPP/Ejercicio_datos/Migrantes_recientes_y_no_migrantes_por_tipo_de_localidad_de_destino_segun_entidad_federativa_1990_-_2010.csv"    
dataframes <- lapply(paste(dirraiz, "/Ejercicio_datos/", nombresA, ".csv", sep = ""), read.csv) #Lectura de los archivos en una sola lista
dataframes
[[1]]

[[2]]

[[3]]

[[4]]

[[5]]
names(dataframes) <- c("Lengua", "ActividadE", "NivelEd", "Sexo", "Destino") #Asignación de índices a los elementos de la lista de dataframes

Segundo paso: Inspeccionar los datos

Ya que hemos cargado en las variables, los documentos para tenerlos como dataframes, hay que conocerlos un poco. Esto lo podemos hacer con la función summary y la función View

sapply(dataframes, summary) #Obtención de un resumen por cada dataframe
$Lengua
   NOM_ENT             HLI_ABS          HLI_REL           NHLI_ABS          NHLI_REL        NE_ABS         
 Length:99          Min.   :   252   Min.   : 0.5726   Min.   :  27838   Min.   :71.12   Length:99         
 Class :character   1st Qu.:  1388   1st Qu.: 2.6820   1st Qu.:  41590   1st Qu.:93.26   Class :character  
 Mode  :character   Median :  2929   Median : 4.3437   Median :  69583   Median :94.98   Mode  :character  
                    Mean   : 11092   Mean   : 5.2402   Mean   : 196616   Mean   :94.03                     
                    3rd Qu.:  7440   3rd Qu.: 6.0914   3rd Qu.: 118621   3rd Qu.:96.48                     
                    Max.   :210510   Max.   :28.5049   Max.   :3359951   Max.   :99.00                     
    NE_REL              TOTAL              AÑO      
 Length:99          Min.   :  29539   Min.   :1990  
 Class :character   1st Qu.:  43980   1st Qu.:1990  
 Mode  :character   Median :  77072   Median :2000  
                    Mean   : 209182   Mean   :2000  
                    3rd Qu.: 127479   3rd Qu.:2010  
                    Max.   :3584957   Max.   :2010  

$ActividadE
   NOM_ENT             MRA_ABS           MRA_REL         MRI_ABS           MRI_REL        MRNE_ABS        
 Length:99          Min.   :  11180   Min.   :38.14   Min.   :   9770   Min.   :21.49   Length:99         
 Class :character   1st Qu.:  19394   1st Qu.:44.79   1st Qu.:  17020   1st Qu.:37.61   Class :character  
 Mode  :character   Median :  35515   Median :50.20   Median :  29781   Median :40.79   Mode  :character  
                    Mean   :  96451   Mean   :51.25   Mean   :  76148   Mean   :42.37                     
                    3rd Qu.:  57972   3rd Qu.:57.43   3rd Qu.:  45614   3rd Qu.:48.22                     
                    Max.   :1724665   Max.   :69.73   Max.   :1361610   Max.   :58.33                     
   MRNE_REL             MRTOT            NMA_ABS            NMA_REL         NMI_ABS            NMI_REL     
 Length:99          Min.   :  22700   Min.   :   92120   Min.   :29.92   Min.   :  103510   Min.   :35.26  
 Class :character   1st Qu.:  39888   1st Qu.:  413820   1st Qu.:40.35   1st Qu.:  493894   1st Qu.:42.11  
 Mode  :character   Median :  67346   Median :  770330   Median :43.70   Median :  837340   Median :47.90  
                    Mean   : 185627   Mean   : 1966563   Mean   :44.97   Mean   : 2043085   Mean   :48.11  
                    3rd Qu.: 115043   3rd Qu.: 1282046   3rd Qu.:49.77   3rd Qu.: 1456800   3rd Qu.:53.72  
                    Max.   :3584957   Max.   :42480411   Max.   :58.80   Max.   :38333353   Max.   :62.89  
   NMNE_ABS           NMNE_REL             NMTOT               AÑO      
 Length:99          Length:99          Min.   :  198390   Min.   :1990  
 Class :character   Class :character   1st Qu.:  897135   1st Qu.:1990  
 Mode  :character   Mode  :character   Median : 1857301   Median :2000  
                                       Mean   : 4331946   Mean   :2000  
                                       3rd Qu.: 3016650   3rd Qu.:2010  
                                       Max.   :80813764   Max.   :2010  

$NivelEd
   NOM_ENT             MRSE_ABS         MRSE_REL         MREB_ABS          MREB_REL        MREP_ABS      
 Length:99          Min.   :   841   Min.   : 1.716   Min.   :  17540   Min.   :44.27   Min.   :   5040  
 Class :character   1st Qu.:  3166   1st Qu.: 3.975   1st Qu.:  25698   1st Qu.:59.20   1st Qu.:  13300  
 Mode  :character   Median :  5401   Median : 8.289   Median :  46095   Median :62.17   Median :  20321  
                    Mean   : 17928   Mean   : 9.030   Mean   : 129054   Mean   :61.56   Mean   :  60445  
                    3rd Qu.: 11842   3rd Qu.:12.783   3rd Qu.:  76805   3rd Qu.:64.59   3rd Qu.:  38914  
                    Max.   :478470   Max.   :28.256   Max.   :2268090   Max.   :71.72   Max.   :1279302  
    MREP_REL       MRNE_ABS           MRNE_REL             MR_TOT           NMSE_ABS           NMSE_REL    
 Min.   :13.63   Length:99          Length:99          Min.   :  27845   Min.   :   17271   Min.   : 2.43  
 1st Qu.:22.00   Class :character   Class :character   1st Qu.:  43510   1st Qu.:   94700   1st Qu.: 6.59  
 Median :28.31   Mode  :character   Mode  :character   Median :  77034   Median :  184520   Median :11.10  
 Mean   :28.95                                         Mean   : 208414   Mean   :  565995   Mean   :12.12  
 3rd Qu.:34.44                                         3rd Qu.: 126238   3rd Qu.:  456346   3rd Qu.:15.91  
 Max.   :54.01                                         Max.   :3584957   Max.   :12645920   Max.   :34.29  
    NMEB_ABS           NMEB_REL        NMEP_ABS           NMEP_REL        NMNE_ABS           NMNE_REL        
 Min.   :  177970   Min.   :53.20   Min.   :   29960   Min.   : 5.247   Length:99          Length:99         
 1st Qu.:  803690   1st Qu.:65.99   1st Qu.:  163452   1st Qu.:12.270   Class :character   Class :character  
 Median : 1334800   Median :68.36   Median :  315090   Median :19.142   Mode  :character   Mode  :character  
 Mean   : 3299595   Mean   :68.04   Mean   : 1028752   Mean   :19.371                                        
 3rd Qu.: 2301111   3rd Qu.:70.21   3rd Qu.:  683456   3rd Qu.:25.723                                        
 Max.   :63021506   Max.   :75.96   Max.   :26559273   Max.   :44.319                                        
     NM_TOT              AÑO      
 Min.   :  248235   Min.   :1990  
 1st Qu.: 1135107   1st Qu.:1990  
 Median : 1935521   Median :2000  
 Mean   : 4915357   Mean   :2000  
 3rd Qu.: 3303669   3rd Qu.:2010  
 Max.   :95431977   Max.   :2010  

$Sexo
   NOM_ENT             MRH_ABS           MRH_REL         MRM_ABS           MRM_REL          MRTOT        
 Length:99          Min.   :  15015   Min.   :43.01   Min.   :  13970   Min.   :45.52   Min.   :  29539  
 Class :character   1st Qu.:  22044   1st Qu.:48.68   1st Qu.:  22182   1st Qu.:48.74   1st Qu.:  43980  
 Mode  :character   Median :  38575   Median :49.83   Median :  37273   Median :50.17   Median :  77072  
                    Mean   : 103188   Mean   :49.97   Mean   : 105994   Mean   :50.03   Mean   : 209182  
                    3rd Qu.:  62532   3rd Qu.:51.26   3rd Qu.:  64024   3rd Qu.:51.32   3rd Qu.: 127479  
                    Max.   :1766027   Max.   :54.48   Max.   :1818930   Max.   :56.99   Max.   :3584957  
    NMH_ABS            NMH_REL         NMM_ABS            NMM_REL          NMTOT               AÑO      
 Min.   :  123258   Min.   :47.12   Min.   :  120002   Min.   :48.59   Min.   :  243260   Min.   :1990  
 1st Qu.:  545340   1st Qu.:48.02   1st Qu.:  575006   1st Qu.:50.64   1st Qu.: 1127753   1st Qu.:1990  
 Median :  945472   Median :48.92   Median :  990049   Median :51.08   Median : 1935521   Median :2000  
 Mean   : 2376705   Mean   :48.82   Mean   : 2522255   Mean   :51.18   Mean   : 4898960   Mean   :2000  
 3rd Qu.: 1585598   3rd Qu.:49.36   3rd Qu.: 1713134   3rd Qu.:51.98   3rd Qu.: 3266232   3rd Qu.:2010  
 Max.   :46127432   Max.   :51.41   Max.   :49304545   Max.   :52.88   Max.   :95431977   Max.   :2010  

$Destino
   NOM_ENT             MRR_ABS          MRR_REL           MRM_ABS          MRM_REL           MRU_ABS       
 Length:99          Min.   :   825   Min.   : 0.2701   Min.   :  1454   Min.   : 0.4871   Min.   :  13228  
 Class :character   1st Qu.:  6870   1st Qu.: 9.3445   1st Qu.:  4977   1st Qu.: 7.9251   1st Qu.:  28948  
 Mode  :character   Median : 11345   Median :16.4928   Median :  8179   Median :11.8073   Median :  50047  
                    Mean   : 27182   Mean   :17.3586   Mean   : 22350   Mean   :13.2427   Mean   : 159650  
                    3rd Qu.: 17014   3rd Qu.:23.3566   3rd Qu.: 15912   3rd Qu.:17.5901   3rd Qu.:  97108  
                    Max.   :465855   Max.   :48.0077   Max.   :425719   Max.   :48.0682   Max.   :2795642  
    MRU_REL          MRTOT            NMR_ABS            NMR_REL           NMM_ABS            NMM_REL       
 Min.   :33.88   Min.   :  29539   Min.   :   16431   Min.   : 0.2248   Min.   :   45528   Min.   : 0.9387  
 1st Qu.:58.69   1st Qu.:  43980   1st Qu.:  198805   1st Qu.:15.4116   1st Qu.:  142962   1st Qu.: 9.9469  
 Median :71.11   Median :  77072   Median :  441688   Median :25.5306   Median :  244578   Median :15.8442  
 Mean   :69.40   Mean   : 209182   Mean   : 1253164   Mean   :27.6861   Mean   :  689789   Mean   :15.7319  
 3rd Qu.:83.87   3rd Qu.: 127479   3rd Qu.: 1133395   3rd Qu.:39.0493   3rd Qu.:  473476   3rd Qu.:19.9440  
 Max.   :99.24   Max.   :3584957   Max.   :22230110   Max.   :60.4745   Max.   :13682041   Max.   :45.3600  
    NMU_ABS            NMU_REL          NMTOT               AÑO      
 Min.   :  143392   Min.   :19.77   Min.   :  243260   Min.   :1990  
 1st Qu.:  499778   1st Qu.:41.79   1st Qu.: 1127753   1st Qu.:1990  
 Median :  955082   Median :55.42   Median : 1935521   Median :2000  
 Mean   : 2956007   Mean   :56.58   Mean   : 4898960   Mean   :2000  
 3rd Qu.: 1936099   3rd Qu.:71.65   3rd Qu.: 3266232   3rd Qu.:2010  
 Max.   :59519826   Max.   :98.84   Max.   :95431977   Max.   :2010  

Tercer paso: limpieza de archivos

Después de haber inspeccionado los dataframes, se puede notar que el marco de datos que contiene los datos sobre las migraciones por condición de habla de lengua indígena contiene algunos renglones sin valores en las columnas NE_ABS y NE_REL. Esto ocasiona que estas columnas sean consideradas como caracteres. Hay que realizar una limpieza en estas columnas.

indicesAlimipiar <- which(sapply(dataframes$Lengua, class) == "character") #Guardar en una variable temporal los índices que se van a limpiar
indicesAlimipiar #Muestra el contenido de esta variable
NOM_ENT  NE_ABS  NE_REL 
      1       6       7 
indicesAlimipiar <- indicesAlimipiar[2:length(indicesAlimipiar)] #Elimina el primer elemento de los índices pues es el que contiene el nombre de las regiones
indicesAlimipiar #Muestra el contenido de la variable
NE_ABS NE_REL 
     6      7 
# Se crea un ciclo for donde se buscará dentro de cada columna, los elementos que contengan un - para reemplazarlo por NA
# Como segundo paso, se cambiará el tipo de la columna para que pueda ser procesada como números
for( indice in indicesAlimipiar){
  dataframes$Lengua[dataframes$Lengua[,indice] == "-", indice] <- NA
  dataframes$Lengua[,indice] <- as.numeric(dataframes$Lengua[,indice])
}
summary(dataframes$Lengua) #Comprobación de que todos los datos están limpios y correctos
   NOM_ENT             HLI_ABS          HLI_REL           NHLI_ABS          NHLI_REL         NE_ABS       
 Length:99          Min.   :   252   Min.   : 0.5726   Min.   :  27838   Min.   :71.12   Min.   :   97.0  
 Class :character   1st Qu.:  1388   1st Qu.: 2.6820   1st Qu.:  41590   1st Qu.:93.26   1st Qu.:  304.8  
 Mode  :character   Median :  2929   Median : 4.3437   Median :  69583   Median :94.98   Median :  665.0  
                    Mean   : 11092   Mean   : 5.2402   Mean   : 196616   Mean   :94.03   Mean   : 2211.1  
                    3rd Qu.:  7440   3rd Qu.: 6.0914   3rd Qu.: 118621   3rd Qu.:96.48   3rd Qu.: 1492.5  
                    Max.   :210510   Max.   :28.5049   Max.   :3359951   Max.   :99.00   Max.   :58469.0  
                                                                                         NA's   :33       
     NE_REL           TOTAL              AÑO      
 Min.   :0.2177   Min.   :  29539   Min.   :1990  
 1st Qu.:0.3795   1st Qu.:  43980   1st Qu.:1990  
 Median :0.8498   Median :  77072   Median :2000  
 Mean   :1.0879   Mean   : 209182   Mean   :2000  
 3rd Qu.:1.6601   3rd Qu.: 127479   3rd Qu.:2010  
 Max.   :2.8917   Max.   :3584957   Max.   :2010  
 NA's   :33                                       
#Limpieza de ActividadE
#Se va a repetir el proceso anterior desde la obtención de los índices de las columnas de tipo character
indicesAlimipiar <- which(sapply(dataframes$ActividadE, class) == "character") #Guardar en una variable temporal los índices que
indicesAlimipiar <- indicesAlimipiar[2:length(indicesAlimipiar)] #Elimina el primer elemento de los índices pues es el que
for( indice in indicesAlimipiar){
  dataframes$ActividadE[dataframes$ActividadE[,indice] == "-", indice] <- NA
  dataframes$ActividadE[,indice] <- as.numeric(dataframes$ActividadE[,indice])
}
summary(dataframes$ActividadE) #Comprobación de que todos los datos están limpios y correctos
   NOM_ENT             MRA_ABS           MRA_REL         MRI_ABS           MRI_REL         MRNE_ABS     
 Length:99          Min.   :  11180   Min.   :38.14   Min.   :   9770   Min.   :21.49   Min.   :   260  
 Class :character   1st Qu.:  19394   1st Qu.:44.79   1st Qu.:  17020   1st Qu.:37.61   1st Qu.:  1040  
 Mode  :character   Median :  35515   Median :50.20   Median :  29781   Median :40.79   Median :  6464  
                    Mean   :  96451   Mean   :51.25   Mean   :  76148   Mean   :42.37   Mean   : 19542  
                    3rd Qu.:  57972   3rd Qu.:57.43   3rd Qu.:  45614   3rd Qu.:48.22   3rd Qu.: 15183  
                    Max.   :1724665   Max.   :69.73   Max.   :1361610   Max.   :58.33   Max.   :596768  
                                                                                        NA's   :33      
    MRNE_REL          MRTOT            NMA_ABS            NMA_REL         NMI_ABS            NMI_REL     
 Min.   : 0.544   Min.   :  22700   Min.   :   92120   Min.   :29.92   Min.   :  103510   Min.   :35.26  
 1st Qu.: 1.735   1st Qu.:  39888   1st Qu.:  413820   1st Qu.:40.35   1st Qu.:  493894   1st Qu.:42.11  
 Median : 7.583   Median :  67346   Median :  770330   Median :43.70   Median :  837340   Median :47.90  
 Mean   : 9.575   Mean   : 185627   Mean   : 1966563   Mean   :44.97   Mean   : 2043085   Mean   :48.11  
 3rd Qu.:17.720   3rd Qu.: 115043   3rd Qu.: 1282046   3rd Qu.:49.77   3rd Qu.: 1456800   3rd Qu.:53.72  
 Max.   :20.934   Max.   :3584957   Max.   :42480411   Max.   :58.80   Max.   :38333353   Max.   :62.89  
 NA's   :33                                                                                              
    NMNE_ABS           NMNE_REL           NMTOT               AÑO      
 Min.   :    2760   Min.   : 0.9975   Min.   :  198390   Min.   :1990  
 1st Qu.:   26095   1st Qu.: 1.7776   1st Qu.:  897135   1st Qu.:1990  
 Median :   95105   Median : 8.6274   Median : 1857301   Median :2000  
 Mean   :  483446   Mean   :10.3792   Mean   : 4331946   Mean   :2000  
 3rd Qu.:  379560   3rd Qu.:18.6456   3rd Qu.: 3016650   3rd Qu.:2010  
 Max.   :14993013   Max.   :22.0234   Max.   :80813764   Max.   :2010  
 NA's   :33         NA's   :33                                         

El proceso de “Limpieza de ActividadE se debe repetir para cada dataframe restante.

Cuarto paso: Mezcla de dataframes

Vamos a unir un par de dataframes para comparar ciertos valores. Para esto lo mejor es asegurarnos que los datos que vamos a unir sean de un largo similar.

Este paso se subirá próximamente

Ejercicio

Obtén una gráfica de puntos entre las entidades federativas, la proporción de migración total y la proporción de migración de secundaria

La función paste

La función paste permite concatenar vectores de cadenas de caracteres. Esta función recibe como parámetros vectores con cadenas de caracteres y los va a unir por defecto con un espacio. Si deseas modificar el caracter que hará la unión, debes ingresar un valor al parámetro sep.

1

Ejemplo:

cadena1 <- c("Come")
cadena2 <- c("siempre")
cadena3 <- c("frutas")
cadena4 <- c("y", "verduras")
# Concatenación con el separador por defecto
paste(cadena1, cadena2, cadena3, cadena4)
[1] "Come siempre frutas y"        "Come siempre frutas verduras"
# Concatenación con el separador definido
paste(cadena1, cadena2, cadena3, cadena4, sep="_")
[1] "Come_siempre_frutas_y"        "Come_siempre_frutas_verduras"

Ejercicio de paste

Imprime la cadena: Come siempre frutas y verduras


  1. Esta función se usa en Primer paso: lectura de arhvios↩︎

LS0tCnRpdGxlOiAiRWplcmNpY2lvIGNvbiBkYXRhIGZyYW1lcyIKb3V0cHV0OiBodG1sX25vdGVib29rCmVkaXRvcl9vcHRpb25zOiAKICBtYXJrZG93bjogCiAgICB3cmFwOiA3MgotLS0KCiMgVsOtbmN1bG8gZGUgZGF0YSBmcmFtZXMKCiogICBbUHJpbWVyIHBhc286IGxlY3R1cmEgZGUgYXJodmlvc10KKiAgIFtTZWd1bmRvIHBhc286IEluc3BlY2Npb25hciBsb3MgZGF0b3NdCiogICBbVGVyY2VyIHBhc286IGxpbXBpZXphIGRlIGFyY2hpdm9zXQoqICAgW0xhIGZ1bmNpw7NuIHBhc3RlXQoKIyMgQ29udGV4dG8KClBhcmEgZXN0ZSBlamVyY2ljaW8gdmFtb3MgYSBoYWNlciB1c28gZGUgdmFyaW9zIGFyY2hpdm9zIHF1ZSBvZnJlY2UgZWwKcG9ydGFsIGRlIGRhdG9zIGFiaWVydG9zIGRlbCBnb2JpZXJubyBkZSBNw6l4aWNvLiBMb3MgZGF0b3MgYSB1dGlsaXphcgpzb24gbG9zIGRhdG9zIHNvYnJlICptaWd0cmFjacOzbiBpbnRlcm5hKi4gRXN0b3MgYXJjaGl2b3MgbXVlc3RyYW4KZGl2ZXJzYSBpbmZvcm1hY2nDs24gc29icmUgbGFzIGNhcmFjdGVyw61zdGljYXMgZGUgbG9zIG1pZ3JhbnRlcyB5IG5vCm1pZ3JhbnRlcyBwYXJhIGxvcyBhw7FvcyAxOTkwLTIwMTAuCgojIyBQcmltZXIgcGFzbzogbGVjdHVyYSBkZSBhcmh2aW9zIHsudGFic2V0fQoKQ2FyZ2EgbG9zIGFyY2hpdm9zIGVuIGRhdGFmcmFtZXMuIEVuIHByaW1lcmEgaW5zdGFuY2lhLCBndWFyZGEgdW4KYXJjaGl2byBwb3IgdmFyaWFibGUuCgojIyMgTGlzdGFkbyBkZSBkb2N1bWVudG9zCgoxLiAgTWlncmFudGVzX3JlY2llbnRlc195XF9ub19taWdyYW50ZXNfcG9yX2dyYW5kZXNfZ3J1cG9zX2RlX2VkYWRfc2VndW5fZW50aWRhZF9mZWRlcmF0aXZhXzE5OTBcXy1cKjIwMTAuY3N2CjIuICBNaWdyYW50ZXNfcmVjaWVudGVzX3lcX25vX21pZ3JhbnRlc19wb3JfdGlwb19kZV9sb2NhbGlkYWRfZGVfZGVzdGlub19zZWd1bl9lbnRpZGFkX2ZlZGVyYXRpdmFfMTk5MCotKjIwMTAuY3N2CjMuICBNaWdyYW50ZXNfcmVjaWVudGVzX3lcX25vX21pZ3JhbnRlc19wb3Jfbml2ZWxfZWR1Y2F0aXZvX3NlZ3VuX2VudGlkYWRfZmVkZXJhdGl2YV8xOTkwKi0qMjAxMC5jc3YKNC4gIE1pZ3JhbnRlc19yZWNpZW50ZXNfeVxfbm9fbWlncmFudGVzX3Bvcl9jb25kaWNpb25fZGVfYWN0aXZpZGFkX2Vjb25vbWljYV9zZWd1bl9lbnRpZGFkX2ZlZGVyYXRpdmFfMTk5MCotKjIwMTAuY3N2CjUuICBNaWdyYW50ZXNfcmVjaWVudGVzX3Bvcl9jb25kaWNpb25fZGVfaGFibGFfZGVfbGVuZ3VhX2luZGlnZW5hX3NlZ3VuX2VudGlkYWRfZmVkZXJhdGl2YV8xOTkwXCotXF8yMDEwLmNzdgo2LiAgTWlncmFudGVzX3JlY2llbnRlc195XF9ub19taWdyYW50ZXNfcG9yX3NleG9fc2VndW5fZW50aWRhZF9mZWRlcmF0aXZhXF9cXzE5OTBcXy1cXzIwMTAuY3N2CgojIyMgQ8OzZGlnbwoKRW4gZWwgc2lndWllbnRlIGJsb3F1ZSBkZSBjw7NkaWdvIHNlIGhhY2UgdXNvIGRlIFtMYSBmdW5jacOzbiBwYXN0ZV0uClB1ZWRlcyBlbmNvbnRyYXIgbcOhcyBpbmZvcm1hY2nDs25iIGFjZXJjYSBkZSBlc3RhIGZ1bmNpw7NuIGRhbmRvIGNsaWMgZW4KZWwgZW5sYWNlIG8gZW4gbGEgcGVzdGHDsWEgY29uIHN1IG5vbWJyZS4KCmBgYHtyIFByaW1lciBwYXNvOiBjYXJnYSBkZSBhcmNoaXZvc30KCmRpcnJhaXogPC0gZ2V0d2QoKSAjU2Ugb2J0aWVuZSBlbCBkaXJlY3RvcmlvIGRlIHRyYWJham8Kbm9tYnJlc0EgPSBjKAogICJNaWdyYW50ZXNfcmVjaWVudGVzX3Bvcl9jb25kaWNpb25fZGVfaGFibGFfZGVfbGVuZ3VhX2luZGlnZW5hX3NlZ3VuX2VudGlkYWRfZmVkZXJhdGl2YV8xOTkwXy1fMjAxMCIsIAogICAgICAgICAgICAgIk1pZ3JhbnRlc19yZWNpZW50ZXNfeV9ub19taWdyYW50ZXNfcG9yX2NvbmRpY2lvbl9kZV9hY3RpdmlkYWRfZWNvbm9taWNhX3NlZ3VuX2VudGlkYWRfZmVkZXJhdGl2YV8xOTkwXy1fMjAxMCIsCiAgIk1pZ3JhbnRlc19yZWNpZW50ZXNfeV9ub19taWdyYW50ZXNfcG9yX25pdmVsX2VkdWNhdGl2b19zZWd1bl9lbnRpZGFkX2ZlZGVyYXRpdmFfMTk5MF8tXzIwMTAiLCAKICAiTWlncmFudGVzX3JlY2llbnRlc195X25vX21pZ3JhbnRlc19wb3Jfc2V4b19zZWd1bl9lbnRpZGFkX2ZlZGVyYXRpdmFfXzE5OTBfLV8yMDEwIiwgIk1pZ3JhbnRlc19yZWNpZW50ZXNfeV9ub19taWdyYW50ZXNfcG9yX3RpcG9fZGVfbG9jYWxpZGFkX2RlX2Rlc3Rpbm9fc2VndW5fZW50aWRhZF9mZWRlcmF0aXZhXzE5OTBfLV8yMDEwIikgIyBWZWN0b3IgdGVtcG9yYWwgY29uIGxvcyBub21icmVzIGRlIGxvcyBkb2N1bWVudG9zCgpwYXN0ZShkaXJyYWl6LCAiL0VqZXJjaWNpb19kYXRvcy8iLCBub21icmVzQSwgIi5jc3YiLCBzZXAgPSAiIikgI011ZXN0cmEgZGVsIGZ1bmNpb25hbWllbnRvIGRlIHBhc3RlCgpkYXRhZnJhbWVzIDwtIGxhcHBseShwYXN0ZShkaXJyYWl6LCAiL0VqZXJjaWNpb19kYXRvcy8iLCBub21icmVzQSwgIi5jc3YiLCBzZXAgPSAiIiksIHJlYWQuY3N2KSAjTGVjdHVyYSBkZSBsb3MgYXJjaGl2b3MgZW4gdW5hIHNvbGEgbGlzdGEKZGF0YWZyYW1lcwpuYW1lcyhkYXRhZnJhbWVzKSA8LSBjKCJMZW5ndWEiLCAiQWN0aXZpZGFkRSIsICJOaXZlbEVkIiwgIlNleG8iLCAiRGVzdGlubyIpICNBc2lnbmFjacOzbiBkZSDDrW5kaWNlcyBhIGxvcyBlbGVtZW50b3MgZGUgbGEgbGlzdGEgZGUgZGF0YWZyYW1lcwpgYGAKCiMjIFNlZ3VuZG8gcGFzbzogSW5zcGVjY2lvbmFyIGxvcyBkYXRvcwoKWWEgcXVlIGhlbW9zIGNhcmdhZG8gZW4gbGFzIHZhcmlhYmxlcywgbG9zIGRvY3VtZW50b3MgcGFyYSB0ZW5lcmxvcyBjb21vCmRhdGFmcmFtZXMsIGhheSBxdWUgY29ub2NlcmxvcyB1biBwb2NvLiBFc3RvIGxvIHBvZGVtb3MgaGFjZXIgY29uIGxhCmZ1bmNpw7NuIHN1bW1hcnkgeSBsYSBmdW5jacOzbiBWaWV3CgpgYGB7ciBTZWd1bmRvIHBhc286IGluc3BlY2Npw7NufQpzYXBwbHkoZGF0YWZyYW1lcywgc3VtbWFyeSkgI09idGVuY2nDs24gZGUgdW4gcmVzdW1lbiBwb3IgY2FkYSBkYXRhZnJhbWUKYGBgCgojIyBUZXJjZXIgcGFzbzogbGltcGllemEgZGUgYXJjaGl2b3MKCkRlc3B1w6lzIGRlIGhhYmVyIGluc3BlY2Npb25hZG8gbG9zIGRhdGFmcmFtZXMsIHNlIHB1ZWRlIG5vdGFyIHF1ZSBlbAptYXJjbyBkZSBkYXRvcyBxdWUgY29udGllbmUgbG9zIGRhdG9zIHNvYnJlIGxhcyBtaWdyYWNpb25lcyBwb3IKY29uZGljacOzbiBkZSBoYWJsYSBkZSBsZW5ndWEgaW5kw61nZW5hIGNvbnRpZW5lIGFsZ3Vub3MgcmVuZ2xvbmVzIHNpbgp2YWxvcmVzIGVuIGxhcyBjb2x1bW5hcyBORV9BQlMgeSBORV9SRUwuIEVzdG8gb2Nhc2lvbmEgcXVlIGVzdGFzCmNvbHVtbmFzIHNlYW4gY29uc2lkZXJhZGFzIGNvbW8gY2FyYWN0ZXJlcy4gSGF5IHF1ZSByZWFsaXphciB1bmEgbGltcGllemEgZW4gZXN0YXMgY29sdW1uYXMuCgpgYGB7ciBMaW1waWV6YSBkZSBsb3MgZGF0b3N9CmluZGljZXNBbGltaXBpYXIgPC0gd2hpY2goc2FwcGx5KGRhdGFmcmFtZXMkTGVuZ3VhLCBjbGFzcykgPT0gImNoYXJhY3RlciIpICNHdWFyZGFyIGVuIHVuYSB2YXJpYWJsZSB0ZW1wb3JhbCBsb3Mgw61uZGljZXMgcXVlIHNlIHZhbiBhIGxpbXBpYXIKaW5kaWNlc0FsaW1pcGlhciAjTXVlc3RyYSBlbCBjb250ZW5pZG8gZGUgZXN0YSB2YXJpYWJsZQppbmRpY2VzQWxpbWlwaWFyIDwtIGluZGljZXNBbGltaXBpYXJbMjpsZW5ndGgoaW5kaWNlc0FsaW1pcGlhcildICNFbGltaW5hIGVsIHByaW1lciBlbGVtZW50byBkZSBsb3Mgw61uZGljZXMgcHVlcyBlcyBlbCBxdWUgY29udGllbmUgZWwgbm9tYnJlIGRlIGxhcyByZWdpb25lcwppbmRpY2VzQWxpbWlwaWFyICNNdWVzdHJhIGVsIGNvbnRlbmlkbyBkZSBsYSB2YXJpYWJsZQoKIyBTZSBjcmVhIHVuIGNpY2xvIGZvciBkb25kZSBzZSBidXNjYXLDoSBkZW50cm8gZGUgY2FkYSBjb2x1bW5hLCBsb3MgZWxlbWVudG9zIHF1ZSBjb250ZW5nYW4gdW4gLSBwYXJhIHJlZW1wbGF6YXJsbyBwb3IgTkEKIyBDb21vIHNlZ3VuZG8gcGFzbywgc2UgY2FtYmlhcsOhIGVsIHRpcG8gZGUgbGEgY29sdW1uYSBwYXJhIHF1ZSBwdWVkYSBzZXIgcHJvY2VzYWRhIGNvbW8gbsO6bWVyb3MKZm9yKCBpbmRpY2UgaW4gaW5kaWNlc0FsaW1pcGlhcil7CiAgZGF0YWZyYW1lcyRMZW5ndWFbZGF0YWZyYW1lcyRMZW5ndWFbLGluZGljZV0gPT0gIi0iLCBpbmRpY2VdIDwtIE5BCiAgZGF0YWZyYW1lcyRMZW5ndWFbLGluZGljZV0gPC0gYXMubnVtZXJpYyhkYXRhZnJhbWVzJExlbmd1YVssaW5kaWNlXSkKfQpzdW1tYXJ5KGRhdGFmcmFtZXMkTGVuZ3VhKSAjQ29tcHJvYmFjacOzbiBkZSBxdWUgdG9kb3MgbG9zIGRhdG9zIGVzdMOhbiBsaW1waW9zIHkgY29ycmVjdG9zCgojTGltcGllemEgZGUgQWN0aXZpZGFkRQojU2UgdmEgYSByZXBldGlyIGVsIHByb2Nlc28gYW50ZXJpb3IgZGVzZGUgbGEgb2J0ZW5jacOzbiBkZSBsb3Mgw61uZGljZXMgZGUgbGFzIGNvbHVtbmFzIGRlIHRpcG8gY2hhcmFjdGVyCmluZGljZXNBbGltaXBpYXIgPC0gd2hpY2goc2FwcGx5KGRhdGFmcmFtZXMkQWN0aXZpZGFkRSwgY2xhc3MpID09ICJjaGFyYWN0ZXIiKSAjR3VhcmRhciBlbiB1bmEgdmFyaWFibGUgdGVtcG9yYWwgbG9zIMOtbmRpY2VzIHF1ZQppbmRpY2VzQWxpbWlwaWFyIDwtIGluZGljZXNBbGltaXBpYXJbMjpsZW5ndGgoaW5kaWNlc0FsaW1pcGlhcildICNFbGltaW5hIGVsIHByaW1lciBlbGVtZW50byBkZSBsb3Mgw61uZGljZXMgcHVlcyBlcyBlbCBxdWUKZm9yKCBpbmRpY2UgaW4gaW5kaWNlc0FsaW1pcGlhcil7CiAgZGF0YWZyYW1lcyRBY3RpdmlkYWRFW2RhdGFmcmFtZXMkQWN0aXZpZGFkRVssaW5kaWNlXSA9PSAiLSIsIGluZGljZV0gPC0gTkEKICBkYXRhZnJhbWVzJEFjdGl2aWRhZEVbLGluZGljZV0gPC0gYXMubnVtZXJpYyhkYXRhZnJhbWVzJEFjdGl2aWRhZEVbLGluZGljZV0pCn0Kc3VtbWFyeShkYXRhZnJhbWVzJEFjdGl2aWRhZEUpICNDb21wcm9iYWNpw7NuIGRlIHF1ZSB0b2RvcyBsb3MgZGF0b3MgZXN0w6FuIGxpbXBpb3MgeSBjb3JyZWN0b3MKCmBgYApFbCBwcm9jZXNvIGRlICJMaW1waWV6YSBkZSBBY3RpdmlkYWRFIHNlIGRlYmUgcmVwZXRpciBwYXJhIGNhZGEgZGF0YWZyYW1lIHJlc3RhbnRlLgoKCiMjIEN1YXJ0byBwYXNvOiBNZXpjbGEgZGUgZGF0YWZyYW1lcwoKVmFtb3MgYSB1bmlyIHVuIHBhciBkZSBkYXRhZnJhbWVzIHBhcmEgY29tcGFyYXIgY2llcnRvcyB2YWxvcmVzLiBQYXJhIGVzdG8gbG8gbWVqb3IgZXMgYXNlZ3VyYXJub3MgcXVlIGxvcyBkYXRvcyBxdWUgdmFtb3MgYSB1bmlyIHNlYW4gZGUgdW4gbGFyZ28gc2ltaWxhci4KCkVzdGUgcGFzbyBzZSBzdWJpcsOhIHByw7N4aW1hbWVudGUKCiMjIEVqZXJjaWNpbwoKT2J0w6luIHVuYSBncsOhZmljYSBkZSBwdW50b3MgZW50cmUgbGFzIGVudGlkYWRlcyBmZWRlcmF0aXZhcywgbGEgcHJvcG9yY2nDs24gZGUgbWlncmFjacOzbiB0b3RhbCB5IGxhIHByb3BvcmNpw7NuIGRlIG1pZ3JhY2nDs24gZGUgc2VjdW5kYXJpYQoKCiMjIExhIGZ1bmNpw7NuIHBhc3RlCgpMYSBmdW5jacOzbiBwYXN0ZSBwZXJtaXRlIGNvbmNhdGVuYXIgdmVjdG9yZXMgZGUgY2FkZW5hcyBkZSBjYXJhY3RlcmVzLgpFc3RhIGZ1bmNpw7NuIHJlY2liZSBjb21vIHBhcsOhbWV0cm9zIHZlY3RvcmVzIGNvbiBjYWRlbmFzIGRlIGNhcmFjdGVyZXMgeQpsb3MgdmEgYSB1bmlyIHBvciBkZWZlY3RvIGNvbiB1biBlc3BhY2lvLiBTaSBkZXNlYXMgbW9kaWZpY2FyIGVsCmNhcmFjdGVyIHF1ZSBoYXLDoSBsYSB1bmnDs24sIGRlYmVzIGluZ3Jlc2FyIHVuIHZhbG9yIGFsIHBhcsOhbWV0cm8KKipzZXAqKi4KClteMV0KClteMV06IEVzdGEgZnVuY2nDs24gc2UgdXNhIGVuIFtQcmltZXIgcGFzbzogbGVjdHVyYSBkZSBhcmh2aW9zXQoKRWplbXBsbzoKCmBgYHtyIEVqZW1wbG8gZGUgcGFzdGV9CmNhZGVuYTEgPC0gYygiQ29tZSIpCmNhZGVuYTIgPC0gYygic2llbXByZSIpCmNhZGVuYTMgPC0gYygiZnJ1dGFzIikKY2FkZW5hNCA8LSBjKCJ5IiwgInZlcmR1cmFzIikKIyBDb25jYXRlbmFjacOzbiBjb24gZWwgc2VwYXJhZG9yIHBvciBkZWZlY3RvCnBhc3RlKGNhZGVuYTEsIGNhZGVuYTIsIGNhZGVuYTMsIGNhZGVuYTQpCiMgQ29uY2F0ZW5hY2nDs24gY29uIGVsIHNlcGFyYWRvciBkZWZpbmlkbwpwYXN0ZShjYWRlbmExLCBjYWRlbmEyLCBjYWRlbmEzLCBjYWRlbmE0LCBzZXA9Il8iKQoKYGBgCgojIyMgRWplcmNpY2lvIGRlIHBhc3RlCgpJbXByaW1lIGxhIGNhZGVuYTogQ29tZSBzaWVtcHJlIGZydXRhcyB5IHZlcmR1cmFzCgpgYGB7ciBTb2x1Y2nDs24gZGVsIGVqZXJjaWNpb30KCmBgYAo=