2 R Base

2.1 El proyecto

Un proyecto es el marco en el cual realizás tu investigación o trabajo. Contiene los insumos, procesos y resultados. Empecemos por crear uno desde el menú: File/New Project, seleccionando el directorio de trabajo. Allí encontrarás un archivo con extensión R.proj. Creemos la carpeta de esta unidad, y también un script (File/New File/R Script) de extensión “.R”, que llamemos Unidad1.R, en el que seguiremos los contenidos y resolveremos los ejercicios.

Para conocer “dónde estamos parados”, nuestro directorio de trabajo (working directory) se encuentra por default en la carpeta del proyecto:

getwd()

2.1.1 Variables

Para adentrarnos en las características de R, “entrevistaremos” un hogar en el marco de la Encuesta Demográfica Retrospectiva. Pero… ¿qué es un hogar? Es una unidad de análisis demográfica, definida en un marco operativo de encuesta o censo: “se entiende por hogar una persona que vive sola o un grupo de personas que pueden o no estar emparentadas pero que comparten el presupuesto para los gastos de alimentación” (ONU, 2011) (ojo, no confundir con vivienda y/o familia).

Resulta que nos fue asignada determinada vivienda, con un solo hogar. Al llegar a la cuadra vemos lo siguiente…

Por suerte nos fue asignada la siguiente vivienda. Son 6 miembros. ¿Cómo se listan los miembros del hogar en este formulario?

fuente: EDER CABA 2019

Figure 2.2: fuente: EDER CABA 2019

Dentro de la EDER CABA de 2019, el cuestionario de Composición del Hogar y Seguimiento (CHo-S) permite seleccionar a la población objetivo y caracterizarla según atributos del hogar y de sus integrantes: (sexo, fecha de nacimiento, edad en años cumplidos, relación de parentesco entre los miembros, condición de asistencia al sistema de educación formal y máximo nivel educativo). Mientras que el cuestionario de Trayectoria Individual y Antecedentes (TI-A) releva información de un miembro seleccionado para eventos de al menos un año de duración en los siguientes temas. Una vez completados los formularios para cada miembro, nos retiramos dando las gracias y nos sentamos a inspeccionar las características del hogar en R. Para esto empezaremos con los atributos del jefe o persona de referencia: Horacio .

La asignación de variables (y de todo tipo de objeto) se realiza mediante el operador (veáse la direccionalidad objeto valor). También, fácilmente se obtiene con Alt + -.

edad <- 55 

Es recomendable no nombrar objetos con números al inicio, y sin incluir coma u otros caracteres especiales. También pueden encontrar el uso de = para asignar. ¿Qué usar?

Para ver el contenido del objeto creado, podemos ejecutar su nombre en la consola, o desde el script pintando el objeto y presionando el botón Run (o ctrl+enter):

edad 
## [1] 55

Las operaciones lógicas estan por detrás de la mayoría de los procesos que realizaremos en el taller. ¿Es de equivalencia la siguiente relación?

edad == 50 
## [1] FALSE

¿Es menor que…?

edad < 40 
## [1] FALSE

Otras operaciones lógicas son: >, <=, >=, != (distinto), etc. (luego veremos algunas más).
Las operaciones sin asignación no cambian el valor de la variable creada:

edad + 10
## [1] 65

¡Atención! lenguaje sensible a mayúsculas:

Edad <- 45
Edad != edad
## [1] TRUE

Los tipos de variable más relevantes son:

  • numeric (decimales con “.”)
edad_exacta <- 55.19
edad == trunc(edad_exacta)
## [1] TRUE
  • character (string)
nombre <- "Horacio"

# Qué clase de objeto es? (esto es un comentario en R)
class(nombre)
## [1] "character"
  • logic (verdadero/falso)
autoRespondente <- TRUE
autoRespondente == FALSE
## [1] FALSE
  • date (fecha)
f_nacim <- "1970/01/01"

Mmm pero f_nacim es character (class(f_nacim)), por lo que deberíamos transformarlo. La función base para cambio de tipos comienza con as. Utilicemos el predictor de comando, a ver qué nos sugiere… (presiona “as.” para ver la lista desplegable de sugerencias). En este caso:

f_nacim <- as.Date(f_nacim)

Fechas: si quisiéramos interpretar una fecha con el formato que utilizamos en Argentina, tendríamos que especificarlo:
f_nacim <- as.Date("01/01/1960", format = "%d/%m/%Y").
Por suerte hay paquetes como lubridate que nos harán las cosas más fáciles. Lo veremos más adelante.

La ausencia de valor se representa con NA (missing/vacío):

sexo <- NA 
#un operador lógico  importante es preguntar si un objeto es vacío:
is.na(sexo)
## [1] TRUE

2.1.2 Actividad

El hogar que te fue asignado tambien tiene un jefe/a o persona de referencia. Te proponemos lo siguiente:

  1. Crear los atributos nombre, sexo, edad, f_nacim.

  2. El cuestionario lo respondió otra persona. Asigna un valor a autoRespondente.

  3. Crear la variable edad_en_10_años que tenga la edad cumplida en 10 años. Corroborar que no son equivalentes.

  4. Obtener la diferencia entre ambas edades: edad_en_10_años - edad_hoy.


2.2 Vectores

Es la estructura de datos más simple en R. Un vector es un arreglo de elementos del mismo tipo (podés comprobarlo). Inicializamos un vector combinando elementos mediante c(…). Por ejemplo c(1,2,3). Las variables son vectores de 1 elemento.

Creemos los vectores de atributos de los miembros del hogar censado, cuyo orden refiere a cada unidad de análisis persona:

nombre_jefe     <- "Horacio"
nombre_conyuge  <- "Jose"
nombre_hijos    <- c("Iván", "Facundo", "Cristian", "Florencia")
nombre          <- c(nombre_jefe, nombre_conyuge, nombre_hijos) # unión de vectores mediante c(), los "apilo"
edad            <- c(55, 53, 29, 28, 21, 31)
f_nacim         <- as.Date(c("1970/01/01", "1971/11/05", "1995/11/08", "1997/01/21", "2003/10/23", "1993/11/19"))
sexo            <- c("v", "m", "v", NA, "v", "m")
autoRespondente <- c(T, rep(F, 5)) # repetí un valor 5 veces

# ¿Acabo de "pisar" objetos? ¿Qué significa? 

¿Qué tipo de objetos son? ¿Qué información contienen? Algunas funciones útiles de exploración…

class(f_nacim)          # tipo de objeto
## [1] "Date"
length(autoRespondente) # cantidad de elementos de un vector
## [1] 6
str(nombre)               # estructura
##  chr [1:6] "Horacio" "Jose" "Iván" "Facundo" "Cristian" "Florencia"
summary(edad)           # resumen de elementos
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   21.00   28.25   30.00   36.17   47.50   55.00
unique(sexo)            # valores únicos
## [1] "v" "m" NA

¿Cómo extraer información de un vector? con […]. Por ejemplo, el nombre de la cuarta persona listada en mi hogar.

nombre[4]
## [1] "Facundo"

¿Y de los tres últimos? Incluyo como referencia el vector de posiciones c(4,5,6).

nombre[c(4,5,6)] 
## [1] "Facundo"   "Cristian"  "Florencia"
nombre[4:6] # equivalente
## [1] "Facundo"   "Cristian"  "Florencia"

Un aspecto muuuy útil de R: vectorizar operaciones. Por default aplica la operación a cada uno de los elementos de un vector, sin necesidad de loopear a lo largo del mismo. Veamos qué pasa con los operadores lógicos que vimos en las variables:

nombre == "Facundo"
## [1] FALSE FALSE FALSE  TRUE FALSE FALSE

¿Qué personas tienen una edad menor a 33?

edad < 33
## [1] FALSE FALSE  TRUE  TRUE  TRUE  TRUE

¡Pero decime los nombres che!

nombre[edad < 33]
## [1] "Iván"      "Facundo"   "Cristian"  "Florencia"

Podemos comparar internamente elementos de un vector. ¿Qué estamos preguntando aquí?

f_nacim[1] < f_nacim 
## [1] FALSE  TRUE  TRUE  TRUE  TRUE  TRUE

Más sobre extracción de elementos de un vector:
¿En qué orden fui listado yo?: which(nombre=="Florencia")
¿Quiénes me caen bien? Puedo usar un operador lógico para excluir una posición (y dejar el resto). Todos menos Cristian:
nombre[nombre!="Cristian"]
Otra forma de verlo, en dos pasos:
posicion_de_Cristian <- which(nombre=="Cristian")
nombre[-posicion_de_Cristian]

Medidas resúmen útiles sobre vectores numéricos:

mean(edad)
## [1] 36.16667
min(f_nacim)
## [1] "1970-01-01"
range(edad)
## [1] 21 55

Antes de continuar: si queremos reemplazar por ejemplo f_nacim por fecha_nacim, podemos utilizar lo que nos ofrece RStudio para buscar y reemplazar (con CRTL+f ) recreando el objeto desde el inicio, o crear un vector idéntico (y eliminar el anterior).

fecha_nacim <- f_nacim
# remover (bienvenido si no quieres ir dejando basura pesada por allí)
rm(f_nacim) 

Ayuda!!! Se puede pedir ayuda consultando la documentación de las funciones:?range o help(range). Y muy probablmente alguien ya se topó con tu problema:
Caption for the picture.

2.2.1 Actividad

Considerando el hogar de Horacio, responder:

  1. ¿Qué valores únicos tiene la variable autoRespondente?

  2. ¿Cuales son los nombres de las personas que censé con una edad mayor a 50?

  3. ¿En qué fecha nació Florencia?

  4. Toma 4 personas que conozcas e incorpóralos como miembros de tu hogar: crear los vectores de atributos nombre, sexo , edad y fecha de nacimiento de los miembros del hogar del grupo. Tener en cuenta el orden .

  5. ¿Cómo se llama la segunda persona listada? Obtener el nombre utilizando corchetes [].

  6. Obtener el rango de la edad de los miembros del hogar y su promedio. Para lo primero se puede usar min y max o directamente la función range.

  7. Mediante Sys.Date() se puede ontener la fecha de hoy (guardarla en una variable si es preferible). Calcular la edad exacta de los miembros, al día de la fecha, de la siguiente manera: (fecha_hoy - fecha_nacim)/365 (restamos fechas y las convertimos en años de manera aproximada).

  8. ¿Y la edad cumplida de los miembros cuál es? ¿El respondente informó correctamente la edad de todos los miembros?

  9. Con la función nchar() podés obtener el largo de un texto. ¿Cuál es el nombre más largo?


2.3 Data.frames

El objeto más flexible en R es el data.frame: permite combinar múltiples variables de distintas clases, símil a las tablas que tratamos en otros softwares estadísticos o excel. Organicemos los atributos de los miembros de mi hogar en un data.frame:

hogar <- data.frame(nombre, sexo, edad, fecha_nacim, autoRespondente, stringsAsFactors = F) 
hogar
##      nombre sexo edad fecha_nacim autoRespondente
## 1   Horacio    v   55  1970-01-01            TRUE
## 2      Jose    m   53  1971-11-05           FALSE
## 3      Iván    v   29  1995-11-08           FALSE
## 4   Facundo <NA>   28  1997-01-21           FALSE
## 5  Cristian    v   21  2003-10-23           FALSE
## 6 Florencia    m   31  1993-11-19           FALSE

¿Características?

dim(hogar)       # dimensiones del objeto: filas x columnas
## [1] 6 5
class(hogar)     # clase de objeto
## [1] "data.frame"
str(hogar)       # estructura
## 'data.frame':    6 obs. of  5 variables:
##  $ nombre         : chr  "Horacio" "Jose" "Iván" "Facundo" ...
##  $ sexo           : chr  "v" "m" "v" NA ...
##  $ edad           : num  55 53 29 28 21 31
##  $ fecha_nacim    : Date, format: "1970-01-01" "1971-11-05" ...
##  $ autoRespondente: logi  TRUE FALSE FALSE FALSE FALSE FALSE
summary(hogar)   # resumen
##     nombre              sexo                edad        fecha_nacim        
##  Length:6           Length:6           Min.   :21.00   Min.   :1970-01-01  
##  Class :character   Class :character   1st Qu.:28.25   1st Qu.:1977-05-09  
##  Mode  :character   Mode  :character   Median :30.00   Median :1994-11-13  
##                                        Mean   :36.17   Mean   :1988-09-27  
##                                        3rd Qu.:47.50   3rd Qu.:1996-10-03  
##                                        Max.   :55.00   Max.   :2003-10-23  
##  autoRespondente
##  Mode :logical  
##  FALSE:5        
##  TRUE :1        
##                 
##                 
## 
colnames(hogar)  # nombres de columnas
## [1] "nombre"          "sexo"            "edad"            "fecha_nacim"    
## [5] "autoRespondente"
ncol(hogar)      # número de columnas
## [1] 5
nrow(hogar)      # número de filas
## [1] 6

Para verlo tipo excel puedes usar View(hogar) o directamente desde el tab Environment haciendo click en el objeto. La selección de variables en un data.frame puede realizarse de distintas maneras. Por ejemplo para la variable sexo:

# con "$": al tipear el signo te sugiere las variables que contiene
hogar$sexo 
## [1] "v" "m" "v" NA  "v" "m"
# Una vez dentro del vector, vale lo que vimos en la sección previa de vectores. ¿Cuál es el miembro con sexo sin valor?
hogar$nombre[is.na(hogar$sexo)]
## [1] "Facundo"

También podemos seleccionar datos mediante coordendas del tipo [fila, columna], o condicionado a la variable elegida.

hogar[2,3]    # fila 2, columna 3
## [1] 53
hogar$edad[2] # en la variable edad, seleccionar el segundo elemento
## [1] 53
hogar[2,]     # ¿Y esto?
##   nombre sexo edad fecha_nacim autoRespondente
## 2   Jose    m   53  1971-11-05           FALSE
hogar[,2]     # ¿Y esto cuando lo vimos?
## [1] "v" "m" "v" NA  "v" "m"

Al crear el data.frame forzamos la no existencia de variables de tipo factor (stringsAsFactors = F). Los tipos de variable factor son variables categóricas (nominales u ordinales), con niveles (o códigos) y etiquetas (al estilo SPSS). Son muy relevantes para algunos paquetes que veremos más adelante, como ggplot2, para dar jerarquía al orden de visualización de las series. Por ejemplo, podemos crear la variable relación de parentezco rp respecto al jefe del hogar o persona de referencia.

hogar$rp <- factor(c("jefe", "cónyuge", "hije", "hije", "hije", "hije"))

# característica
class(hogar$rp)
## [1] "factor"
str(hogar$rp) # para R siempre la variable será esencialmente un entero
##  Factor w/ 3 levels "cónyuge","hije",..: 3 1 2 2 2 2
levels(hogar$rp)
## [1] "cónyuge" "hije"    "jefe"
nlevels(hogar$rp)
## [1] 3

Al parecer el respondente fue el cónyuge. Hagamos el cambio seleccionando de la variable autoRespondete aquellla observación (persona) que sea:

hogar$autoRespondente[hogar$rp == "jefe"]    <- FALSE  # ¿Cómo se lee esto?
hogar$autoRespondente[hogar$rp == "cónyuge"] <- TRUE

2.3.1 Actividad

  1. A partir de los vectores creados en la actividad previa, generar un data.frame con los miembros del hogar.

  2. Inspeccionar sus características.

  3. Obtener todos los datos del segundo miembro listado con el uso de corchetes [].

  4. Luego de una revisita al hogar encontramos que el tercer miembro listado prefiere que no conste su sexo, y que el cuarto miembro pefiere ser listado con su apodo “Pepe”. Hacer los cambios correspondientes.

  5. Agregar una variable con el número de caracteres de cada nombre. Informar el promedio.


2.4 Listas

¿Te preguntarás si hay vida más allá del data.frame? Por supuesto, las listas. Una lista es una colección de objetos de cualquier tipo (incluidos los data.frame). Por ejemplo si el último miembro es Florencia y se construye en el terreno de los padres y forma su propio hogar dentro de la vivienda, el listado de hogares tendría dos data.frame:

hogar_1 <- hogar[-6,] 
hogar_2 <- hogar[6,]
lista_de_hogares <- list(hogar_1 = hogar_1, 
                         hogar_2 = hogar_2)

# inspecciono
str(lista_de_hogares)
## List of 2
##  $ hogar_1:'data.frame': 5 obs. of  6 variables:
##   ..$ nombre         : chr [1:5] "Horacio" "Jose" "Iván" "Facundo" ...
##   ..$ sexo           : chr [1:5] "v" "m" "v" NA ...
##   ..$ edad           : num [1:5] 55 53 29 28 21
##   ..$ fecha_nacim    : Date[1:5], format: "1970-01-01" "1971-11-05" ...
##   ..$ autoRespondente: logi [1:5] FALSE TRUE FALSE FALSE FALSE
##   ..$ rp             : Factor w/ 3 levels "cónyuge","hije",..: 3 1 2 2 2
##  $ hogar_2:'data.frame': 1 obs. of  6 variables:
##   ..$ nombre         : chr "Florencia"
##   ..$ sexo           : chr "m"
##   ..$ edad           : num 31
##   ..$ fecha_nacim    : Date[1:1], format: "1993-11-19"
##   ..$ autoRespondente: logi FALSE
##   ..$ rp             : Factor w/ 3 levels "cónyuge","hije",..: 2

Para acceder a un elemento de la lista utilizamos doble corchete:

# el primer hogar del listado es:
lista_de_hogares[[1]]
##     nombre sexo edad fecha_nacim autoRespondente      rp
## 1  Horacio    v   55  1970-01-01           FALSE    jefe
## 2     Jose    m   53  1971-11-05            TRUE cónyuge
## 3     Iván    v   29  1995-11-08           FALSE    hije
## 4  Facundo <NA>   28  1997-01-21           FALSE    hije
## 5 Cristian    v   21  2003-10-23           FALSE    hije
# el nombre del miembro 3 del segundo hogar, mi antigua casa, ahora es:
lista_de_hogares[[1]]$nombre[3]
## [1] "Iván"
# puedo utilizar también el nombre del objeto dentro de la lista, en vez de su posición:
lista_de_hogares[["hogar_1"]]$nombre[3]
## [1] "Iván"

Una buena explicación sobre la estructura de selección la dió el mismísimo Hadley Wickham acá.

Estimadxs, considerando que no llego a fin de mes, decido incorporarme de nuevo a mi hogar natal, por lo que el hogar número 2 debe ser removido. ¿Cómo incorporo una nueva fila a un data.frame? Se puede utilizar rbind (r de rows, que tiene su primo cbind para unir columnas, con c de columns).

# junto los hogares
hogar_reunificado <- rbind(hogar_1, hogar_2)

# lo asigno de vuelta al hogar_natal original
lista_de_hogares[["hogar_1"]] <- hogar_reunificado

# borro de la lista el hogar independiente
lista_de_hogares$hogar_2 <- NULL

Y debo tener el mismo hogar que antes, pero ahora como elemento de un listado:

str(lista_de_hogares)
## List of 1
##  $ hogar_1:'data.frame': 6 obs. of  6 variables:
##   ..$ nombre         : chr [1:6] "Horacio" "Jose" "Iván" "Facundo" ...
##   ..$ sexo           : chr [1:6] "v" "m" "v" NA ...
##   ..$ edad           : num [1:6] 55 53 29 28 21 31
##   ..$ fecha_nacim    : Date[1:6], format: "1970-01-01" "1971-11-05" ...
##   ..$ autoRespondente: logi [1:6] FALSE TRUE FALSE FALSE FALSE FALSE
##   ..$ rp             : Factor w/ 3 levels "cónyuge","hije",..: 3 1 2 2 2 2

2.4.1 Actividad

  1. Antes que cierres la puerta, el respondente te avisa que se alquila una pieza al fondo del terreno, donde vive Luis: varón, nacido el 3 de junio del 2000, en su hogar unipersonal. Incorporalo a la lista de hogares de la vivienda.
hogar_luis <- data.frame(nombre = "Luis", sexo = "v", edad = 25, fecha_nacim = "2000-06-03", autoRespondente = TRUE, rp = "jefe")
  1. Al querer irte Luis te avisa que en verdad él colabora monetariamente con la comida diaria, y hasta cenan juntos por las noches. Probablemente sea mejor unificar todo en un solo hogar. Hacelo recordando eliminar el hogar unipersonal de Luis asignando NULL a ese elemento de la lista, o en todo caso creando un nuevo objeto lista_de_hogares sin un segundo elemento (pisarlo).
lista_de_hogares <- list(hogar_1 = rbind(hogar, hogar_luis))

2.5 Referencias y materiales adicionales