Examen de TIplE 2018 con posibles soluciones
- (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
- (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")
- (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)
- (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)
- (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)» }
- (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».