Examen de TIplE 2018 con posibles soluciones

  1. (1 punto) En esta carpeta hay datos sobre contaminación del aire en Asturias. Hay una carpeta por cada año. En cada carpeta de ésas, el nombre del fichero contiene el identificador de la estación. En esta tabla mira cuál te corresponde:
    ALICIA       vale002
    SERGIO	vale003
    Judith	vale004
    Denise	vale005
    Aida		vale006
    PAULA	vale007
    Cristina	vale008
    Nadia	vale009
    Adrián	vale010
    Mario	vale011
    CESAR	vale012
    Sara		vale015
    Elisabeth	vale016
    PATRICIA	vale018
    Pablo	vale021
    Iván		vale022
    Joaquín	vale027
    

    Carga los datos en R del fichero de 2018 que te corresponda y haz una descripción general de las variables (qué variables hay [fecha, hora…]) y cuáles contienen un número considerable de datos.

    ## por ejemplo, uso vale001.csv
    a <- read.csv ("http://carleos.epv.uniovi.es/~carleos/aireUO/dat/csv/2018/vale001.csv")
    summary (a)
    ## FECHA_HI contiene la fecha desde 2018-01-01 a 2018-12-31
    ## PERIODO_UI toma valores de 1 a 24 (parece la hora)
    diff((a$NLEC_HI))[1:100]
    table (diff((a$NLEC_HI)))
    ## NLEC_HI aumenta de 60 en 60 (¿minuto?) salvo cada 24 horas
    length(unique(a$NLEC_HI)) == nrow(a)
    ## NLEC_HI es un identificador único para cada observación (¿número de lectura?)
    ## SO2_HI NO_HI NO2_HI CO_HI PST_HI DD_HI VV_HI TMP_HI HR_HI PRB_HI RS_HI LL_HI
    ## ésas del renglón anterior parecen variables con datos (¿concentración de contaminante?)
    ## O3_HI (¿ozono?) es constante: -9999 en todos los casos
    ## el valor -9999 parece indicar un dato ausente; para las concentraciones
    ## hay que considerar solamente los casos positivos;
    ## FL_SO2 FL_NO FL_NO2 FL_CO FL_PST FL_O3 DD_HI FL_DD FL_VV FL_TMP FL_HR FL_PRB FL_RS FL_LL
    ## ésas del resglón anterior parecen indicadores de la validez del dato;
    ## los números «buenos» parecen estar asociados a la etiqueta V
    ## los números -9999 parecen estar asociados a valores no V (como N)
    
    ## por tanto, éstas son las variables con un número considerable de datos:
    ## SO2_HI NO_HI NO2_HI CO_HI PST_HI DD_HI VV_HI TMP_HI HR_HI PRB_HI RS_HI LL_HI
    
  2. (1 punto) Haz una gráfica de la evolución de la concentración de algún contaminante (partículas PM10; partículas2,5; SO2…) en función de la fecha.
    ## considero la primera, SO2_HI
    plot (SO2_HI ~ FECHA_HI, a, subset = SO2_HI>0) # con cajas
    b <- a [order(a$FECHA_HI,a$PERIODO_HI), ]      # para líneas
    plot (SO2_HI ~ as.Date(FECHA_HI), b, subset = SO2_HI>0, type="l") # de línea
    ## versión que aprovecha las horas:
    plot (SO2_HI ~ I(as.numeric(as.Date(FECHA_HI))+PERIODO_HI/24), b, subset = SO2_HI>0, type="l")
    
  3. (1 punto) Haz una gráfica de la concentración de algún contaminante (partículas PM10; partículas2,5; SO2…) en función de la hora (PERIODO_HI).
    boxplot (SO2_HI ~ PERIODO_HI, a, subset = SO2_HI>0)
    
  4. (1 punto) Haz una gráfica de la concentración de algún contaminante (partículas PM10; partículas2,5; SO2…) en función del día de la semana.
    boxplot (SO2_HI ~ weekdays(as.Date(FECHA_HI)), a, subset = SO2_HI>0) # días desordenados
    
    diassem <- weekdays (as.Date (1:7, origin="2019-01-13"))
    ## "lunes" "martes" "miércoles" "jueves" "viernes" "sábado" "domingo"
    boxplot (SO2_HI ~ factor (weekdays(as.Date(FECHA_HI)), levels=diassem),
             a, subset = SO2_HI>0)
    
  5. (1 punto) Puedes generar un dataframe a partir de un fichero remoto mediante una orden como
    d <- read.csv (url ("http://..."))
    

    Haz un bucle en R para leer los datos de la estación que te corresponda desde 2010 hasta 2018 y júntalos todos en dataframe único. Si no puedes hacerlo para todas las columnas, hazlo al menos para las fechas y horas y algún contaminante con datos.

    ## ahora con vale002.csv porque de vale001.csv no hay todos los años
    todos <- data.frame ()
    for (anno in 2010:2018) 
    { 
       a <- read.csv (paste0 ("http://carleos.epv.uniovi.es/",
                              "~carleos/aireUO/dat/csv/",
                              anno,
                              "/vale002.csv"))
       todos <- rbind (todos, a)
    }
    ## para vale001.csv podría hacerse así (suppressWarnings y opción silent, opcionales)
    todos <- data.frame ()
    for (anno in 2010:2018) 
    { 
       a <- suppressWarnings (try (read.csv (paste0 ("http://carleos.epv.uniovi.es/",
                                                     "~carleos/aireUO/dat/csv/",
                                                     anno,
                                                     "/vale001.csv")),
                                   silent=TRUE))
       if (!inherits (a, "try-error")) todos <- rbind (todos, a) # véase «example(try)»
    }
    
  6. (2 puntos) Considera este fichero cuyo contenido es
    "id interno moodle";"identificador uniovi";Apellidos;Nombre
    369399;uo273033;"MARTINEZ GARCIA";"ALICIA MARIA"
    304760;uo240113;"FERNÁNDEZ FERNÁNDEZ";SERGIO
    303179;uo238865;"Marcos Verdejo";Judith
    293151;uo231086;"Cuervo Suárez";Denise
    374709;uo73854;"Riesgo Alonso";Aida
    310129;uo244665;"MARRON SANTOS";PAULA
    280543;uo220998;"Fernández González";Cristina
    296064;uo232749;"Díaz Fernández";Nadia
    310426;uo244809;"López Fernández";Adrián
    286157;uo224854;"Merlo Bárcena";Mario
    371273;uo273824;"CARREÑO JIMENEZ";"CESAR EDUARDO"
    367649;uo272276;"Álvarez Quintana";Sara
    368416;uo183153;"Martínez Medina";Elisabeth
    250257;uo158957;"ACEBES TAMARGO";PATRICIA
    311670;uo246251;"Menéndez Landa";Pablo
    295870;uo232616;"Rodríguez Aparicio";Iván
    368544;uo798;"García Abad";Joaquín
    370203;uo273262;LIU;YUXIN
    

    Considera este programa que contiene las siguientes órdenes de Bash:

    iconv -f ISO-8859-1 -t UTF-8 Usuarios_T_S,A_MANADINE-1-006.csv > usuarios.csv
    ## +2 para quitar cabecera
    tail -n +2 usuarios.csv | cut -d';' -f4 | tr '[A-Z]' '[a-z]' | tr -d '"' | cut -d' ' -f1 | iconv -f UTF-8 -t ASCII//TRANSLIT | grep -v yuxin > nombres.txt
    tail -n +2 usuarios.csv | grep -vi yuxin | cut -d';' -f2 | cut -c 3- > contras.txt
    tail -n +2 usuarios.csv | cut -d';' -f4,3 --output-delimiter=', ' | tr -d '"' | grep -v YUXIN > nombres-completos.txt
    ## como "root":
    addgroup manadine18
    addgroup manadine
    cat useradd.R | R --vanilla
    

    Considera este otro programa en R cuyo contenido es

    anno <- "18"
    contras <- as.character (read.table("contras.txt")[[1]])
    nombres <- as.character (read.table("nombres.txt")[[1]])
    nombres.completos <- as.character (read.delim ("nombres-completos.txt", header=FALSE) [[1]])
    stopifnot (length (contras) == length (nombres))
    stopifnot (length (contras) == length (nombres.completos))
    for (i in 1 : length(contras))
    {
        nombre <- paste0 (nombres[[i]], anno) # para que no coincidan con los de otros an~os
        contra <- contras[[i]]
        nombre.completo <- nombres.completos[[i]]
        cadena <- paste0 ("useradd -b /home/manadine/2018-20/ -c '", nombre.completo, "' ",
                          "  -g manadine18 -G users,manadine -m -N ",
                          "  -p ", system (paste ("mkpasswd", contra, anno), intern=TRUE),
                          "  -s /bin/bash ",
                          nombre)
        system (cadena)
    }
    

    El objetivo de todo lo anterior fue crear las cuentas de alumno en el ordenador carleos2.epv.uniovi.es.

    Explica cómo funcionan los anteriores programas de Bash y R. Por ejemplo se puede empezar así:

    El fichero Usuarios_T_S,A_MANADINE-1-006.csv es un fichero de texto con formato CSV, 
    es decir, con un registro por cada renglón y campos separados por punto y coma.
    Contiene información de alumnos: un identificador que desconozco; un identificador del correo
    de la uni; apellidos; nombre.  El primer renglón del fichero es una cabecera con los 
    nombres de los campos y los datos están a partir del segundo renglón.
    
    El programa de Bash empieza ejecutando la orden «iconv».  Si hago «man iconv» leo que 
    «convert text from one character encoding to another», así que cambia la codificación
    de un texto.  Parece que la cambia de ISO-8859-1 a UTF-8, porque la opción «-f» equivale a
    «--from-code» y la opción «-t» equivale a «--to-code» según «man iconv».  El resultado
    se guarda (mediante la redirección «>») en el fichero «usuarios.csv».  A mí este comando
    no me hace falta porque en vez de descargar el fichero he copiado y pegado su contenido
    directamente desde el navegador, y veo bien las eñes y las vocales acentuadas.
    
    El renglón «## +2 para quitar cabecera» empieza por almohadilla y es un comentario.
    No se ejecuta.
    
    El siguiente renglón encadena muchas órdenes:
    tail -n +2 usuarios.csv | cut -d';' -f4 | tr '[A-Z]' '[a-z]' | tr -d '"' | cut -d' ' -f1 | iconv -f UTF-8 -t ASCII//TRANSLIT | grep -v yuxin > nombres.txt
    
    La orden «tail» saca el final de un fichero.  Según «man tail» la opción significa: 
    «use -n +NUM to output starting with line NUM», así que «tail -n +2» saca a partir
    del segundo renglón, o sea, que se usa para omitir la cabecera (el primer renglón).
    [...]
    

    Seguimos:

    La orden «cut -d';' -f4» extrae el cuarto campo (el nombre de pila).  
    La opción «-d» indica que el delimitador de campos es un punto y coma.
    
    La orden «tr '[A-Z]' '[a-z]'» trasforma mayúsculas a minúsculas.
    La orden «tr -d '"'» elimina las comillas.
    
    La orden «cut -d' ' -f1» divide por espacios y se queda con el primer campo, es decir, 
    la primera palabra.
    
    La orden «iconv -f UTF-8 -t ASCII//TRANSLIT» quita tildes.  Véase la sección EXAMPLE
    de «man iconv».
    
    La orden «grep -v yuxin > nombres.txt» elimina el renglón «yuxin» y guarda el 
    resultado en el fichero «nombres.txt» (nombres de pila sin tildes).
    
    La siguiente cadena de órdenes genera un archivo «contras.txt» (contaseñas) a partir 
    también de «usuarios.csv»:
     tail -n +2 usuarios.csv | grep -vi yuxin | cut -d';' -f2 | cut -c 3- > contras.txt
    
    El «tail -n +2» elimina el renglón de cabecera.
    
    El «grep -vi yuxin» elimina («-v») los renglones con «yuxin» sin diferenciar mayúsculas de minúsculas («-i»).
    
    El «cut -d';' -f2» se queda con el segundo campo de cada registro (el identificador UO).
    
    El «cut -c 3-» se queda con los caracteres («-c») a partir del tercero («3-») por lo que quita el «uo»
    inicial y se queda sólo con los dígitos.  Por tanto, las contraseñas serán los dígitos del identificador UO.
    
    La siguiente cadena de órdenes genera un archivo llamado «nombres-completos.txt»:
    tail -n +2 usuarios.csv | cut -d';' -f4,3 --output-delimiter=', ' | tr -d '"' | grep -v YUXIN > nombres-completos.txt
    
    El «tail -n +2» elimina la cabecera.
    
    El «cut -d';' -f4,3 --output-delimiter', '» extrae los campos apellidos y nombre de pila y los junta con 
    una coma más espacio. (¿Error: «cut» mantiene el orden original; «-f4,3» es lo mismo que «-f3,4»?)
    
    El «tr -d '"'» elimina las comillas.
    
    El «grep -v YUXIN» elimina los registros que contienen «YUXIN».
    
    Las órdenes «addgroup» sólo puede ejecutarlas el superusuario «root» o un usuario administrador con «sudo».
    Sirven para añadir grupos de usuarios al sistema (en este caso, grupos «manadine» y «manadine18»).
    
    La orden «cat useradd.R | R --vanilla» hace que el programa «R» ejecute las órdenes de «useradd.R»,
    fichero que paso a comentar.
    
    La orden «anno <- "18"» define la variable «anno» como el año actual, como cadena de texto.
    
    La orden «contras <- as.character (read.table("contras.txt")[[1]])» lee el fichero de contraseñas y las mete
    en un vector «contras».  De «read-table» se obtiene un dataframe, mediante el doble corchete extraemos
    la primera columna (sólo tiene una, pero así ya tenemos el vector) y mediante «as.character» aseguramos que
    sean meras cadenas y no un factor o un número.
    
    La siguiente orden «nombres <- ...» hace algo parecido con el fichero de nombres de pila.
    
    La siguiente orden «nombres.completos <- ...» ídem pero con los nombres completos.
    
    Las dos órdenes «stopifnot...» aseguran que todos los vectores tengan la misma longitud.
    
    El bucle «for» realiza una iteración por cada registro:
    
    - «nombre <- paste0 (...)» genera un nombre pegando al nombre de pila original el «18» del año.
    
    - «contra» pasa a ser la «i»-ésima contaseña
    
    - ídem con «nombre.completo»
    
    - se genera la variable «cadena» pegando mediante «paste0» unas cuantas cadenas:
      - unas cadenas patrón que generan una orden «useradd»;
      - la cadena «nombre.completo»;
      - la cadena «nombre»;
      - una cadena generada a partir de «contra», usando la orden «mkpasswd» que parece que genera una
        contraseña cifrada a partir de la cadena con la contraseña;  para ejecutar «mkpasswd» se usa la 
        orden «system» con la opción «intern=TRUE», lo que devuelve una cadena;
    
    - al final se genera una orden «useradd» (añadir usuario) con estas opciones:
      - «-b» directorio donde irá la carpeta de inicio del usuario («/home/manadine/2018-20»)
      - «-c» nombre completo
      - «-g» grupo principal «manadine18»
      - «-m» crea la carpeta de inicio si no existe
      - «-N» no genera un grupo con el mismo nombre que el usuario
      - «-p» contraseña
      - «-s» intérprete de comandos por omisión («/bin/bash», más completa que la «/bin/sh»)
    - la cadena generada se ejecuta mediante «system».
    

Author: Carleos Artime

Created: 2019-01-15 mar 23:19

Emacs 25.1.1 (Org mode 8.2.10)

Validate