Francisco Guijarro
Universidad Politécnica de Valencia
Creative Commons Attribution 4.0 International License (CC BY 4.0)
La mayor parte de la información puede representarse mediantes dos tipos básicos: números y texto. Por ejemplo, la siguiente línea de código suma dos números, cuyo resultado es, obviamente, otro número:
3+5
## [1] 8
Los números pueden ser cantidades enteras o pueden contener decimales
3+5.5
## [1] 8.5
Pero igualmente el resultado de la suma sigue siendo un número. Lo que no podemos hacer es sumar un número con una cadena de texto:
3+"casa"
La última línea de código deberá generar un error con el siguiene mensaje:
Error in 3 + "casa" : argumento no-numérico para operador binario
que traducido del austro-húngaro viene a decir que estamos intentando sumar cosas que no son compatibles. Esto es, que el operador suma + no está definido para el caso de que alguno de los argumentos no sea numérico. Cuestión diferente hubiera sido hacer lo siguiente:
casa <- 10
3+casa
## [1] 13
Observa la diferencia entre "casa" y casa. En el primer caso, el término "casa" se refiere a una simple cadena de texto. Al quitar las comillas, nos estamos refiriendo a la variable recién creada casa, a la que hemos asignado el valor numérico 10. Es decir, que es un número y no una cadena de texto.
Otro tipo de datos con los que habitualmente vamos a trabajar son los valores lógicos, de tipo logical al que se asocian los valores TRUE y FALSE:
casa == 10
## [1] TRUE
casa != 10
## [1] FALSE
is.logical(casa)
## [1] FALSE
is.logical(casa == 10)
## [1] TRUE
Para borrar del Environment una variable que no vamos a utilizar más, podemos emplear la función rm. De esta manera mantendremos limpio nuestro entorno de variables.
rm(casa)
Los factores son variables que tienen acotado el número de valores que pueden tomar. Los factores suelen estar referidos a variables categóricas. Un ejemplo es la variable passengerClass en el dataframe TitanicSurvival:
class(TitanicSurvival$passengerClass)
## [1] "factor"
Los diferenes valores que puede tomar un factor se denominan niveles, y puedes ser accesibles a través de la función levels:
levels(TitanicSurvival$passengerClass)
## [1] "1st" "2nd" "3rd"
levels(TitanicSurvival$sex)
## [1] "female" "male"
En este caso los valores representan cadenas de texto, como también ocurre con la variable survived:
levels(TitanicSurvival$survived)
## [1] "no" "yes"
Puedes observar como en todos los casos los niveles aparecen ordenados alfabéticamente, pudiendo acceder individualmente a cada uno de ellos de la siguiente forma:
levels(TitanicSurvival$passengerClass)[1]
## [1] "1st"
levels(TitanicSurvival$sex)[2]
## [1] "male"
Podemos utilizar la siguiente expresión para conocer qué niveles de la variable passengerClass se corresponde con la cadena de texto "2nd":
levels(TitanicSurvival$passengerClass) == "2nd"
## [1] FALSE TRUE FALSE
Fíjate como la respuesta es que de los 3 niveles del factor, únicamente el segundo se corresponde con la segunda clase. Si escribes lo siguiente, entonces obtendrás la respuesta a qué pasajeros de la base de datos viajaron en segunda clase:
TitanicSurvival$passengerClass == "2nd"
## [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [13] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [25] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [37] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [49] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [61] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [73] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [85] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [97] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [109] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [121] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [133] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [145] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [157] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [169] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [181] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [193] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [205] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [217] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [229] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [241] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [253] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [265] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [277] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [289] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [301] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [313] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE TRUE
## [325] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
## [337] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
## [349] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
## [361] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
## [373] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
## [385] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
## [397] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
## [409] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
## [421] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
## [433] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
## [445] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
## [457] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
## [469] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
## [481] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
## [493] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
## [505] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
## [517] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
## [529] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
## [541] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
## [553] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
## [565] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
## [577] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
## [589] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
## [601] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [613] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [625] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [637] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [649] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [661] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [673] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [685] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [697] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [709] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [721] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [733] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [745] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [757] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [769] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [781] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [793] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [805] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [817] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [829] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [841] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [853] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [865] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [877] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [889] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [901] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [913] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [925] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [937] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [949] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [961] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [973] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [985] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [997] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [1009] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [1021] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [1033] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [1045] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [1057] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [1069] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [1081] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [1093] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [1105] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [1117] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [1129] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [1141] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [1153] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [1165] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [1177] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [1189] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [1201] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [1213] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [1225] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [1237] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [1249] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [1261] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [1273] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [1285] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [1297] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
## [1309] FALSE
En los dos últimos casos, observa que la respuesta obtenida es de tipo logical.
Ejercicio
1A partir de la última expresión y la función
sum, escribe el código que permita calcular el número de pasajeros que viajaron en primera clase. El resultado debería coincidir con el siguiente valor:
## [1] 323
Otra función interesante es which, que permite identificar aquellas observaciones que cumplen determinada condición:
which(TitanicSurvival$passengerClass == "1st")
## [1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
## [19] 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
## [37] 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
## [55] 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
## [73] 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
## [91] 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
## [109] 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
## [127] 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
## [145] 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
## [163] 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
## [181] 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198
## [199] 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216
## [217] 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234
## [235] 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252
## [253] 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
## [271] 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288
## [289] 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306
## [307] 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323
Como ves, la función which devuelve las posiciones (filas) que ocupan los pasajeros que cumplen la condición: viajar en primera clase.
Ejercicio
2Calcula el número de pasajeros que cumplen la siguiente doble condición: viajaban en primera clase y eran mujeres. Identifica qué filas ocupan en la base de datos. Para configurar diferentes condiciones emplea el símbolo
&, que permite concatenar cuantas condiciones necesitemos.
Una vez analizados los tipos básicos de datos que podemos manejar en R, vamos a ver cómo se pueden estructurar en elementos algo más complejos.
Apoyándonos en la siguiente figura, vamos a explicar las principales estructuras de datos que pueden manejarse en R:
Resumen de estructuras de datos en R.
Un escalar representa el elemento más básico en la estructura de datos diseñada en R. Podemos crear una variable y asignarle un escalar de la siguiente forma:
a <- 3.7
En este caso la variable a es un escalar que toma el valor 3.7. Los escalares pueden ser número enteros o fraccionarios. La variable a es numérica, representa un número fraccionario (double), pero no es un número entero (integer)
is.numeric(a)
is.double(a)
is.integer(a)
Tip
R es case-sensitive. Es decir, no es lo mismo la variable
aque la variableA. Prueba a escribiris.numeric(A).
También podemos crear elementos básicos que no sean numéricos:
b <- "Hola"
Y comprobar qué tipo de dato estamos almacenando en b:
is.numeric(b)
is.character(b)
Las anteriores funciones, así como cualquier otra de R, siempre van a tener la siguiente estructura:
nombre.función(parámetro/s)
Por ejemplo, en el comando is.character(b), is.character es el nombre de la función, mientras que b es el único parámetro. Algunas funciones admitirán más de un parámetro.
Para conocer el detalle de los parámetros se puede acudir a la ayuda de R:
?is.character
Un vector se define como un conjunto ordenado de elementos, todos del mismo tipo, que en R se pueden concatenar con la función c:
dias <- c("lunes", "martes", "miércoles", "jueves", "viernes", "sábado", "domingo")
temperaturas <- c(24, 22, 23, 15, 17, 22, 21)
Puede accederse a un elemento concreto o a varios de ellos:
dias[3]
dias[3:5]
dias[c(3,5)]
También puedes aplicar operaciones accediendo a los diferentes elementos de estas variables. Aquí algunos ejemplos:
mean(temperaturas)
## [1] 20.57143
summary(temperaturas)
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 15.00 19.00 22.00 20.57 22.50 24.00
2*temperaturas[3]
## [1] 46
temperaturas[1]+temperaturas[2]+temperaturas[3]
## [1] 69
plot(temperaturas)
Ejercicio
3Observa como
3:5genera la secuencia3 4 5. Escribeprint(0:10)y comprueba qué resultado se obtiene ¿Cómo crearías una secuencia de 10 a 0? ¿Y una secuencia de 10 a 0 pero de 2 en 2? Para la última pregunta ayúdate de la funciónseq.
Ejercicio
4Obtén con una sólo línea de código qué elementos del vector
temperaturasestán por encima del valor 20. El resultado debería ser el siguiente:
## [1] TRUE TRUE TRUE FALSE FALSE TRUE TRUE
Las matrices son estructuras de datos con dos dimensiones: filas y columnas. Se definen a través de la función matrix:
matrix(c(1:10, 10:1), ncol = 10, nrow = 2)
## [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
## [1,] 1 3 5 7 9 10 8 6 4 2
## [2,] 2 4 6 8 10 9 7 5 3 1
Observa cómo los parámetros ncoly nrow permiten definir completamente la dimensión de la matriz. Es más, en realidad podemos definir esta dimensión asignando valor a uno de los parámetros, y dejando el otro vacío para que lo infiera R:
secuencia <- matrix(c(1:10, 10:1), ncol = 2)
secuencia
## [,1] [,2]
## [1,] 1 10
## [2,] 2 9
## [3,] 3 8
## [4,] 4 7
## [5,] 5 6
## [6,] 6 5
## [7,] 7 4
## [8,] 8 3
## [9,] 9 2
## [10,] 10 1
Para referirse a un elemento concreto o una fila/columna:
secuencia[4, 2]
secuencia[3, ]
secuencia[, 1]
El data frame es una matriz donde las columnas tienen nombre:
temp_semana <- data.frame(dias, temperaturas)
temp_semana
## dias temperaturas
## 1 lunes 24
## 2 martes 22
## 3 miércoles 23
## 4 jueves 15
## 5 viernes 17
## 6 sábado 22
## 7 domingo 21
Podemos referirnos a las columas bien a través del nombre de las mismas, o bien a través del número de columna que ocupan:
temp_semana$dias
temp_semana[, 1]
Al ejecutar el código anterior, se puede comprobar cómo la variable original dias ha pasado de ser de tipo character a Factor. Como se comentó en un punto anterior, el tipo factor está diseñado para representar variables categóricas.
Además de seleccionar columnas mediante el número de las mimas o mediante el símbolo $, también podemos seleccionar subgrupos de observaciones que, por ejemplo, cumplan determinada condición. Por ejemplo, el siguiente código mostrará los días donde la temperatura fue mayor que 22 grados:
temp_semana$temperaturas > 22
## [1] TRUE FALSE TRUE FALSE FALSE FALSE FALSE
temp_semana$dias[temp_semana$temperaturas > 22]
## [1] "lunes" "miércoles"
Si queremos conocer los días en los que la temperatura fue exactamente de 22 grados:
temp_semana$dias[temp_semana$temperaturas == 22]
## [1] "martes" "sábado"
Añadir columnas a un data frame es sencillo. Por ejemplo, la siguiente línea de código añade una columna qué indica qué días se superaron los 20 grados:
temp_semana$temp_mayor_20 <- temp_semana$temperatura > 20
temp_semana
## dias temperaturas temp_mayor_20
## 1 lunes 24 TRUE
## 2 martes 22 TRUE
## 3 miércoles 23 TRUE
## 4 jueves 15 FALSE
## 5 viernes 17 FALSE
## 6 sábado 22 TRUE
## 7 domingo 21 TRUE
También se puede eliminar fácilmente una columna asignándole el valor NULL:
temp_semana$temp_mayor_20 <- NULL
temp_semana
## dias temperaturas
## 1 lunes 24
## 2 martes 22
## 3 miércoles 23
## 4 jueves 15
## 5 viernes 17
## 6 sábado 22
## 7 domingo 21
Una lista es un conjunto ordenado de objetos o variables. Por lo general, se utilizan para combinar elementos de origen y formato diferente bajo una misma denominación. Por ejemplo, y aunque en este caso los elementos sí guardan relación, podríamos combinar las temperaturas y los días de la semana en una lista:
lista <- list(dias, temperaturas)
lista
## [[1]]
## [1] "lunes" "martes" "miércoles" "jueves" "viernes" "sábado"
## [7] "domingo"
##
## [[2]]
## [1] 24 22 23 15 17 22 21
Podemos acceder a sus elementos de diferentes formas:
lista[1]
## [[1]]
## [1] "lunes" "martes" "miércoles" "jueves" "viernes" "sábado"
## [7] "domingo"
lista[2]
## [[1]]
## [1] 24 22 23 15 17 22 21
class(lista[2])
## [1] "list"
lista[[2]]
## [1] 24 22 23 15 17 22 21
class(lista[[2]])
## [1] "numeric"
lista[[2]][4]
## [1] 15
Observa como se ha mantenido el orden de los elementos que integran la lista. En primer lugar los días de la semana, en segundo las temperaturas. Observa como lista[2] es un objeto tipo lista, mientras que lista[[2]] es un vector de números. Como indicábamos anteriormente, una lista puede incluir elementos que nada tengan que ver entre sí:
lista <- list(dias = dias, temperaturas = temperaturas, nombres = c("Federico", "María", "Mikel", "Andrea"))
lista
## $dias
## [1] "lunes" "martes" "miércoles" "jueves" "viernes" "sábado"
## [7] "domingo"
##
## $temperaturas
## [1] 24 22 23 15 17 22 21
##
## $nombres
## [1] "Federico" "María" "Mikel" "Andrea"
A diferencia de la primera definición, ahora estamos asignando un nombre a cada una de las 3 listas que componen la variable lista. Esto permite poder acceder a sus elementos de formas alternativas:
lista[[3]]
## [1] "Federico" "María" "Mikel" "Andrea"
lista$nombres
## [1] "Federico" "María" "Mikel" "Andrea"
Las listas definidas en R pueden tener la complejidad que necesitemos en nuestros cálculos, pudiendo combinar vectores de diferente tamaño como en el caso anterior, o incluso escalares, vectores, matrices, etc:
lista <- list(dias = dias, numero = runif(1), nombres = c("Federico", "María", "Mikel", "Andrea"), matriz = secuencia)
lista
## $dias
## [1] "lunes" "martes" "miércoles" "jueves" "viernes" "sábado"
## [7] "domingo"
##
## $numero
## [1] 0.598173
##
## $nombres
## [1] "Federico" "María" "Mikel" "Andrea"
##
## $matriz
## [,1] [,2]
## [1,] 1 10
## [2,] 2 9
## [3,] 3 8
## [4,] 4 7
## [5,] 5 6
## [6,] 6 5
## [7,] 7 4
## [8,] 8 3
## [9,] 9 2
## [10,] 10 1
dplyrLa librería dplyr es una de las librerías de R más potentes para el manejo y transformación de datos. La siguiente cheatsheet de RStudio muestra alguna de sus funcionalidades más relevantes, algunas de las cuales iremos introduciendo poco a poco:
De momento, vamos a hacer uso de los denominados pipes %>% que sirven para encadenar funciones y pasar dataframes a dichas funciones, así como las funciones filter y select (recuerda instalar la librería dplyr antes de correr el siguiente código:
library(dplyr)
temp_semana %>%
filter(temperaturas == 22) %>%
select(dias)
## dias
## 1 martes
## 2 sábado
En el siguiente bloque se introducirá otra función de dplyr muy socorrida: group_by.
En este ejercicio vamos a repasar algunas de las funciones vistas hasta ahora, así como aprender algunas nuevas. Para ello, utilizaremos el dataframe Salaries de la librería carData, que incluye información sobre los salarios de diferentes categorías de profesores en universidades de EEUU durante el periodo 2008-09:
data(Salaries)
head(Salaries)
## rank discipline yrs.since.phd yrs.service sex salary
## 1 Prof B 19 18 Male 139750
## 2 Prof B 20 16 Male 173200
## 3 AsstProf B 4 3 Male 79750
## 4 Prof B 45 39 Male 115000
## 5 Prof B 40 41 Male 141500
## 6 AssocProf B 6 6 Male 97000
str(Salaries)
## 'data.frame': 397 obs. of 6 variables:
## $ rank : Factor w/ 3 levels "AsstProf","AssocProf",..: 3 3 1 3 3 2 3 3 3 3 ...
## $ discipline : Factor w/ 2 levels "A","B": 2 2 2 2 2 2 2 2 2 2 ...
## $ yrs.since.phd: int 19 20 4 45 40 6 30 45 21 18 ...
## $ yrs.service : int 18 16 3 39 41 6 23 45 20 18 ...
## $ sex : Factor w/ 2 levels "Female","Male": 2 2 2 2 2 2 2 2 2 1 ...
## $ salary : int 139750 173200 79750 115000 141500 97000 175000 147765 119250 129000 ...
La columna rank se refiere a 3 categorías distintas de profesores:
AsstProf, o profesor asistente. Según el siguiente enlace de Wikipedia, “el rango de profesor asistente en general se mantiene durante un período de prueba de cinco a siete años, después de lo cual o bien se promovió el individuo a profesor asociado y concedió la tenencia (es decir, no puede ser despedido sin causa y un proceso de audiencia formal) o se dará por terminado de empleo”. Es decir, sería el equivalente a nuestros profesores contratados, como los perfiles de Profesor Ayudante o Profesor Colaborador.
AssocProf, o profesor asociado, cuya definición es muy diferente al del caso español: “Después de varios años en la categoría de profesor asistente, los individuos son considerados para un ascenso y la tenencia . La tenencia constituye generalmente un acuerdo de empleo de por vida”. El equivalente español sería Profesor Titular de Universidad
Prof, equivalente a Catedrático de Universidad.
La columna discipline hace referencia al tipo de departamento al que está adscrito el profesor:
A: teórico.
B: aplicado.
Además, tenemos el género de los profesores (sex), los años desde que obtuvieron el título de Doctor (yrs.since.phd), los años de servicio (yrs.service), y el salario en dólares (salary).
Ejercicio
5Obtén los estadísticos descriptivos básicos (mínimo, percentil del 25%, media, etc) de la variable
salary:
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 57800 91000 107300 113706 134185 231545
Lo anterior también puede realizarse para cada una de las categorías de profesor. La función group_by de la librería dplyr permite agrupar las observaciones que cumplen con un determinado criterio. Por ejemplo, podemos querer calcular algunos estadísticos descriptivos de salary para los 3 grupos de profesores que tenemos en el dataframe:
Salaries %>%
group_by(rank) %>%
summarise(media = mean(salary), sd = sd(salary))
## # A tibble: 3 x 3
## rank media sd
## <fct> <dbl> <dbl>
## 1 AsstProf 80776. 8174.
## 2 AssocProf 93876. 13832.
## 3 Prof 126772. 27719.
Observa que el resultado en una nueva estructura de datos denominada tibble, una combinación de las palabras table y bible; esto es, una tabla de proporciones (a priori) bíblicas.
También podemos incluir en el anterior resultado el número de profesores en cada categoría a través de la función n():
Salaries %>%
group_by(rank) %>%
summarise(media = mean(salary), sd = sd(salary), n_profesores = n())
## # A tibble: 3 x 4
## rank media sd n_profesores
## <fct> <dbl> <dbl> <int>
## 1 AsstProf 80776. 8174. 67
## 2 AssocProf 93876. 13832. 64
## 3 Prof 126772. 27719. 266
O que el resultado se ordene en función de una varible de interés. Por ejemplo, que la tabla aparezca ordenada en función del número de profesores por categoría. Para ellos podemos utilizar la función arrange:
Salaries %>%
group_by(rank) %>%
summarise(media = mean(salary), sd = sd(salary), n_profesores = n()) %>%
arrange(n_profesores)
## # A tibble: 3 x 4
## rank media sd n_profesores
## <fct> <dbl> <dbl> <int>
## 1 AssocProf 93876. 13832. 64
## 2 AsstProf 80776. 8174. 67
## 3 Prof 126772. 27719. 266
Si quisiéramos representarlo en orden inverso:
Salaries %>%
group_by(rank) %>%
summarise(media = mean(salary), sd = sd(salary), n_profesores = n()) %>%
arrange(-n_profesores)
## # A tibble: 3 x 4
## rank media sd n_profesores
## <fct> <dbl> <dbl> <int>
## 1 Prof 126772. 27719. 266
## 2 AsstProf 80776. 8174. 67
## 3 AssocProf 93876. 13832. 64
Si, además, quieres que el resultado no sea de tipo tibble sino el clásico dataframe:
Salaries %>%
group_by(rank) %>%
summarise(media = mean(salary), sd = sd(salary), n_profesores = n()) %>%
arrange(-n_profesores) %>%
as.data.frame()
## rank media sd n_profesores
## 1 Prof 126772.11 27718.675 266
## 2 AsstProf 80775.99 8174.113 67
## 3 AssocProf 93876.44 13831.700 64
También podemos querer visualizar a través de un histograma:
Ejercicio
6Obtén un histograma de los salarios utilizando el parámetro
breakspara configurar el número de barras; por ejemplobreaks = 50. Los parámetrosxlabeylabte servirán para colocar las leyendas en los ejes, mientras que conmainpodrás indicar el nombre del gráfico:
Ejercicio
7Calcula los salarios medios de cada categoría de profesorado pero diferenciando por género. Deberías obtener algo similar a:
Mujeres:
## # A tibble: 3 x 3
## rank media sd
## <fct> <dbl> <dbl>
## 1 AsstProf 78050. 9372.
## 2 AssocProf 88513. 17965.
## 3 Prof 121968. 19620.
Hombres:
## # A tibble: 3 x 3
## rank media sd
## <fct> <dbl> <dbl>
## 1 AsstProf 81311. 7901.
## 2 AssocProf 94870. 12891.
## 3 Prof 127121. 28214.
Ejercicio
8Habrás observado diferencias en cuanto a medias y dispersión en los salarios según el género. ¿Podría haber otra variable que explicara estas diferencias?
Ejercicio
9Calcula la matriz de correlaciones entre las siguientes variables numéricas:
salary,yrs.since.phd,yrs.service:
## salary yrs.since.phd yrs.service
## salary 1.0000000 0.4192311 0.3347447
## yrs.since.phd 0.4192311 1.0000000 0.9096491
## yrs.service 0.3347447 0.9096491 1.0000000
A continuación tienes una imagen que puede recordarte cómo interpretar los coeficientes de correlación:
Imagen de correlación (tomada de https://commons.wikimedia.org/wiki/File:Correlation_examples2.svg)
Ejercicio
10Realiza un análisis de regresión múltiple que explique el precio en función del resto de variables. Emplea la función
lm, cuyo formato tienes que encontrar a partir de la ayuda. Una vez realizada la regresión, cuyos resultados aparecen a continuaión, responde a estas cuestiones. ¿Te parece adecuado el valor del \(R^2\) ajustado? ¿Cuál es la variables menos significativa (o no significativa en este caso)? Observa los coeficientes deyrs.serviceyyrs.since.phd. ¿Te parecen coherentes respecto del signo que tenían en la matriz de correlaciones? Cuando un coeficiente cambia su signo respecto del inicialmente pautado por el análisis de correlación, podemos estar ante un problema de multicolinealidad. El problema de la multicolinealidad puede afectar a los resultados de la regresión. El modelo de regresión asume que las variables independientes no están correlacionadas entre sí; es decir, que pueden explicar partes diferentes del salario. Cuando esta hipótesis no se cumple, podemos encontrarnos problemas al aplicar el modelo de regresión sobre datos fuera de la muestra considerada.
help('lm')
##
## Call:
## lm(formula = salary ~ ., data = Salaries)
##
## Residuals:
## Min 1Q Median 3Q Max
## -65248 -13211 -1775 10384 99592
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 65955.2 4588.6 14.374 < 2e-16 ***
## rankAssocProf 12907.6 4145.3 3.114 0.00198 **
## rankProf 45066.0 4237.5 10.635 < 2e-16 ***
## disciplineB 14417.6 2342.9 6.154 1.88e-09 ***
## yrs.since.phd 535.1 241.0 2.220 0.02698 *
## yrs.service -489.5 211.9 -2.310 0.02143 *
## sexMale 4783.5 3858.7 1.240 0.21584
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 22540 on 390 degrees of freedom
## Multiple R-squared: 0.4547, Adjusted R-squared: 0.4463
## F-statistic: 54.2 on 6 and 390 DF, p-value: < 2.2e-16
Ejercicio
11Según el anterior modelo, ¿cuál es la diferencia media en el salario entre un catedrático (professor) y un contratado (assistant professor), suponiendo que el resto de variables se mantienen constantes?
Ejercicio
12En cualquier caso, parece que el género no influye en el salario. Repite la regresión múltiple pero excluyendo la variable
sex. ¿Ha habido cambios en el valor del \(R^2\) ajustado? ¿Realmente perdemos algo por eliminar una variable cuyo coeficiente no ha resultado significativo? ¿Seguimos teniendo problemas con el signo de algún coeficiente?
##
## Call:
## lm(formula = salary ~ discipline + yrs.since.phd + yrs.service +
## rank, data = Salaries)
##
## Residuals:
## Min 1Q Median 3Q Max
## -65244 -13498 -1455 9638 99682
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 69869.0 3332.1 20.968 < 2e-16 ***
## disciplineB 14505.2 2343.4 6.190 1.52e-09 ***
## yrs.since.phd 534.6 241.2 2.217 0.02720 *
## yrs.service -476.7 211.8 -2.250 0.02497 *
## rankAssocProf 12831.5 4147.7 3.094 0.00212 **
## rankProf 45287.7 4236.7 10.689 < 2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 22550 on 391 degrees of freedom
## Multiple R-squared: 0.4525, Adjusted R-squared: 0.4455
## F-statistic: 64.64 on 5 and 391 DF, p-value: < 2.2e-16
Los problemas de multicolinealidad se pueden investigar a través del factor de inflado de la varianza (VIF):
library(car)
##
## Attaching package: 'car'
## The following object is masked from 'package:dplyr':
##
## recode
vif(regresion)
## GVIF Df GVIF^(1/(2*Df))
## discipline 1.063139 1 1.031086
## yrs.since.phd 7.518920 1 2.742065
## yrs.service 5.908984 1 2.430840
## rank 2.003562 2 1.189736
Un VIF entre 5 y 10 puede suponer problemas leves de multicolinealidad, mientras que si el VIF es superior a 10 tendríamos problemas graves de multicolinealidad.
Ejercicio
13A raíz de los valores obtenidos del VIF, repite el modelo de regresión eliminando alguna de las variables
yrs.serviceoyrs.since.phd, hasta obtener un modelo de regresión sin problemas de multicolinealidad. ¿Ha afectado severamente la eliminación de alguna de estas variables al valor del \(R^2\) ajustado? ¿Qué otras variables no presentes en este estudio podrían explicar las diferencias salariales?
&arrangeclassdata.framegroup_byis.characteris.doubleis.integeris.logicalis.numericlevelslistlmmatrixn()runifseqsummarisevifwhich