Profesor del programa de Ingeniería Industrial, Universidad Sergio Arboleda. Candidato a doctor en Ingeniería de la Universidad de los Andes.

Sesión 1: Introducción a R

R es un entorno y lenguaje de programación con un enfoque al análisis estadístico. A través de este curso veremos cuáles son las funcionalidades y herramientas con las cuales podrás desarrollar tareas tan sencillas como sumas y restas hasta modelos de analítica de datos que usan compañías como Airbnb, Uber o Twitter.

En este curso haremos una introducción a los conceptos básicos para el manejo de datos y el desarrollo de análisis estadísticos básicos. Así pues, ¡empecemos!

Bloques básicos de programación en R

En su forma más sencilla, R puede ser utilizado como una calculadora interactiva.

5+7
## [1] 12

R simplemente imprime el resultado 12 por defecto. Sin embargo, R es un lenguaje de programación y, en ocasiones, la utilizamos porque queremos automatizar procesos o evitar repeticiones innecesarias.

En este caso, queremos usar este resultado más adelante. En lugar de volver a escribir todo el código, crearemos una variable que guarde el resultado. La expresión que utilizaremos para esto es <-.

x <- 5 + 7

Notarán que R no imprime el resultado en este momento. Cuando se asigna información, R asume que no necesita mostrar el resultado. Para ver el resultado, solamente hay que nombrar la variable.

x

Con R puedes realizar la mayoría de las operaciones básicas. Estas expresiones van a depender del tipo de datos que utilicemos, lo cual lo veremos a lo largo de esta sesión. Cualquier objeto que contenga datos en R se llama estructura de datos y la primera que veremos serán los vectores numéricos.

La forma más sencilla de crear vectores es con la función c() que significa concatenar o combinar. Probemos unir las expresiones x+3, 5, 23 y asignarlo a la variable z

z <- c (x + 3, 5, 23)

Los vectores numéricos, como en la primera expresión, tambien pueden incluir expresiones y podemos realizar operaciones con ellas. Probemos multiplicar el vector por 2 y sumarle 100.

z*2 + 100
## [1] 130 110 146

Como pueden ver, R aplicó las operaciones a cada elemento del vector. Otras operaciones disponibles son +, -, /, and ^. Para realizar una raíz cuadrada, use la función sqrt(). Probemos la raíz cuadrada de z -1 y asignarlo a la variable rc_z

rc_z <- sqrt(z-1)
rc_z

¿Y qué pasa si dividimos vectores entre si? Probemos que pasa si dividimos z entre su raíz cuadrada.

z/rc_z

En efecto, divide el valor de cada elemento de z por el de la misma posición. ¿ Y qué pasa si son de diferente longitud? Recicla los elementos! Probemos un ejemplo.

a <- c (1, 2, 3, 4)
b <- c (0, 10)
c <- a + b
c

Probemos otro ejemplo:

a <- c (1, 2, 3, 4)
b <- c (0, 10, 100)
c <- a + b
## Warning in a + b: longitud de objeto mayor no es múltiplo de la longitud de
## uno menor
c

En el caso de que no sean de igual longitud, el sistema sacará una alerta. Finalmente, si queremos hacer operaciones con los elementos dentro de un vector. Por ejemplo, podemos sumar sus elementos o contar sus elementos. Veamos un ejemplo:

sum(a)
length(a)

Otras funciones que podrían ser útiles son min(), max(), mean(), median(), unique() y sort()

EJERCICIO Usted ha sido escogido por el director del área de producción de su compañía para realizar un análisis de la demanda mensual de la empresa y realizar una estimación de las variaciones de la demanda, de acuerdo con la información del área de mercadeo. La información que posee es la siguiente:

  1. La demanda del mes 1 es de 250 unidades y cada mes aumenta en 15% el número de unidades.
  2. De acuerdo con las estimaciones del área de mercadeo, existen tres escenarios posibles:
  • Duplicar la producción actual
  • Tener un aumento trimestral de 0, 50 y 100 unidades a lo largo del año
  • La demanda aumentará en 1,8 más 25 unidades mensuales

¿En cuál de los escenarios presentados se venden, en promedio, más unidades al final del año?

Listas en R

La siguiente estructura de datos que nos interesa son las listas. Las listas contienen valores de cualquier tipo simple (numerico o no numérico), y podrían ser estructuras completas (lista de listas). Si usamos como referencia a una hoja de calculo con datos sobre individuos, una lista podria ser una fila que tiene los datos de los individuos. Para crear una lista, el comando que utilizaremos es list(). Veamos un ejemplo:

DetailStudent=list(fullName="Fred Meyers", age=40,female=FALSE)

El objeto ‘DetailStudent’ almacena temporalmente la lista en la computadora. Los nombres de las variables pueden contener letras del alfabeto y números (y algunos caracteres de puntuación), pero no debe comenzar con un número.

En el codigo anterior, solo se ha pedido crear la lista. R lo ejecuta y nada mas, no tienes que esperar ningun mensaje ni resultado. Si quieres ver lo que has creado, escribelo de manera explicita, así:

DetailStudent
## $fullName
## [1] "Fred Meyers"
## 
## $age
## [1] 40
## 
## $female
## [1] FALSE

Nota que hay varios tipos de datos en la lista:

fullName es texto o caracteres. age es un numero. female es un valor lógico.

Para acceder a cada uno de los elemento tu lista:

#Opción 1: La posición del dato
DetailStudent[[1]]
## [1] "Fred Meyers"
#Opción 2: El nombre de la variable
DetailStudent[['fullName']]
## [1] "Fred Meyers"
#Opción 3: Usar el signo de dolar (o peso)
DetailStudent$fullName
## [1] "Fred Meyers"

Hasta el momento creamos y consultamos una lista. ¿Cómo cambiamos la información de una lista? Si queremos cambiar un valor de la lista, solamente debemos asignar el valor

DetailStudent$fullName='Camilo Pinto'

¿Y si queremos es añadir un elemento a nuestra lista? Funciona igual que nuestro caso anterior, asignando el valor a este elemento

DetailStudent$city = 'Seattle'

Si queremos dejarlo vacío debemos asignar el comando NA o eliminarlo con NULL. ¿Y si ya no necesito la lista? Para eliminar una lista necesio usar rm()

list1=list(1,2,3,4)
rm(list1)

EJERCICIO Como parte de su práctica en la escuela de Ingeniería, el decano le solicite que organice la información de los casos disciplinarios a revisar en el próximo comité. Es necesario que la información que :

  1. Crea un objeto tipo lista con los datos de los estudiantes. Los nombres son Freddy Patiño, Luis Ferrucho, Danna Rodriguez y Pedro Meléndez. Cada uno está en un semestre mayor que el anterior, empezando en tercer semestre. Además, todos están acusados de fraude y el estado del proceso es activo.

  2. Antes de llegar al comité se decidió que a todos se les agregaría si hubo confesión. En los estudiantes que hay, solamente Pedro confesó su pena.

3.Después del comité se decidió que todos los estudiantes que no confesaron serán suspendidos por un semestre y los que confesaron recibirán una amonestación escrita.

Vectores

Los vectores deben contener un único tipo de datos. En un archivo de Excel, un vector puede ser una columna.

names=c("Fred Meyers","Sarah Jones", "Lou Ferrigno","Sky Turner")
ages=c(40,35, 60,77)
female=c(F,T,T,T)

Los tres objectos almacenas temporalmente listas. Los nombre pueden contener letras del alfabeto y números (y algunos caracteres de puntuación), pero no debe comenzar con un número.

Si quieres acceder a ciertos elementos solamente debemos usar corchetes cuadrados simples:

names[1]
## [1] "Fred Meyers"
# o también
ages[1]
## [1] 40
# o también
female[1]
## [1] FALSE

Podemos alterar el vector al asignar nueva información de esta manera (igual que en las listas):

names[1]='Alfred Mayer'

Para añadir un nuevo elemento, usaremos una estructura recursiva:

elements=c(1,2,3)
elements=c(elements,40) 

Sin embargo, para eliminar los datos no podemos utilizar la operación Null que usamos en las listas. Para eliminar el elemento debemos encoger el vector usando la siguiente expresión:

elements= elements[-4]

¿Y qué podemos hacer si tenemos valores repetidos en nuestro vector? En este caso, podemos usar la función unique:

weekdays=c('M','T','W','Th','S','Su','Su')
weekdays
## [1] "M"  "T"  "W"  "Th" "S"  "Su" "Su"
unique(weekdays)
## [1] "M"  "T"  "W"  "Th" "S"  "Su"

Vectores versus Listas

¿Y cómo hacemos para saber qué tipo de datos tenemos? ¿Es un vector o es una lista? Para esto, la función que nos interesa es str. Dependiendo del tipo de datos que tengamos, podremos obtener:

str(elements)
str(DetailStudent)
str(rc_z)

Además, cuando crees y uses operaciones debes considerar cuáles aplican para cada estructura. Probemos la operación length:

listTest=list(1,2,3,3)
vectorTest=c(1,2,3,4,4)
length(listTest)
length(vectorTest)

Data Frames

Los Data frames pueden interpretarse como estructuras compuestas a partir de las estructuras simples. Si partieramos de usar vectores, cada uno corresponde a las columnas. Para crear un data frame, el comando es `data.frame:

# Usaremos cuatr vectores sobre estudiantes extranjeros
names=c("Qing", "Françoise", "Raúl", "Bjork")
ages=c(32,33,28,30)
country=c("China", "Senegal", "Spain", "Norway")
education=c("Bach", "Bach", "Master", "PhD")

#DF es una composición de vectores:
DF_vectors=data.frame(names,ages,country,education)
DF_vectors
##       names ages country education
## 1      Qing   32   China      Bach
## 2 Françoise   33 Senegal      Bach
## 3      Raúl   28   Spain    Master
## 4     Bjork   30  Norway       PhD

¿Y si tenemos listas? Usaremos el comando data.list en conjunto con do.call. La forma de aplicarla es así:

# Listas por fila
row1=list(name="Qing", age=32, country="China", deg="Bach")
row2=list(name="Françoise", age=33, country="Senegal", deg="Bach")
row3=list(name="Raúl", age=28, country="Spain", deg="Master")
row4=list(name="Bjork", age=30, country="Norway", deg="PhD")
# lista de listas
dataList=list(row1,row2,row3,row4)

#DF es una composición de listas:
DF_lists=do.call(rbind.data.frame,dataList)
row.names(DF_lists)=NULL
DF_lists
##        name age country    deg
## 1      Qing  32   China   Bach
## 2 Françoise  33 Senegal   Bach
## 3      Raúl  28   Spain Master
## 4     Bjork  30  Norway    PhD

Y ¿qué tipo de cosas nos interesa saber de un data frame?

#Conocer si es un Data Frame
str(DF_vectors)
str(DF_lists)

#Dimensiones del Data Frame
dim(DF_vectors)

#Filas del Data Frame
nrow(DF_vectors)

#Columnas del Data Frame
length(DF_vectors)

#Ver las primeras filas
head(DF_vectors,2)

#Ver las últimas filas
tail(DF_vectors,2)

#¿Qué variables tenemos?
names(DF_vectors)

Al leer los datos, la estructura que deben tener en cuenta es [Filas, columnas]. Para leer las columnas, tenemos varias opciones:

#Puedo tomar una columna si sé la columna
DF_vectors$names
## [1] Qing      Françoise Raúl      Bjork    
## Levels: Bjork Françoise Qing Raúl
#Puedo tomar una columna si sé su posición
DF_vectors[,1]
## [1] Qing      Françoise Raúl      Bjork    
## Levels: Bjork Françoise Qing Raúl
#Varias columnas (con posiciones)
DF_vectors[,c(1,4)]
##       names education
## 1      Qing      Bach
## 2 Françoise      Bach
## 3      Raúl    Master
## 4     Bjork       PhD
#Varias columnas (con nombres)
DF_vectors[,c('names','education')]
##       names education
## 1      Qing      Bach
## 2 Françoise      Bach
## 3      Raúl    Master
## 4     Bjork       PhD

Además, para la lectura de las filas tenemos dos opciones:

#una fila
DF_vectors[2,]
##       names ages country education
## 2 Françoise   33 Senegal      Bach
#varias filas
DF_vectors[c(2,3),]
##       names ages country education
## 2 Françoise   33 Senegal      Bach
## 3      Raúl   28   Spain    Master

Nótese en los casos anteriores, que si no indicabas filas, tenías toda la fila; y que si no indicas columnas, vienen todas las columnas. Si solo quieres un valor:

students=DF_vectors[1,3]

A veces nos va interesar tomar una parte del Data Frame, esto lo llamaremos subset y lo haremos asignando esta información que obtuvimos:

studentsCopy= DF_vectors

Ahora haremos las modificaciones a los valores que obtenemos:

# cambio el valor de una edad:
studentsCopy[1,2]=23
# No hay advertencia, el cambio ya se hizo:
studentsCopy[1,]
##   names ages country education
## 1  Qing   23   China      Bach

Podemos tener una nueva columna con valores vacios:

studentsCopy$lastName=NA
studentsCopy
##       names ages country education lastName
## 1      Qing   23   China      Bach       NA
## 2 Françoise   33 Senegal      Bach       NA
## 3      Raúl   28   Spain    Master       NA
## 4     Bjork   30  Norway       PhD       NA

Y puedo eliminarla con NULL:

studentsCopy$lastName=NULL
studentsCopy
##       names ages country education
## 1      Qing   23   China      Bach
## 2 Françoise   33 Senegal      Bach
## 3      Raúl   28   Spain    Master
## 4     Bjork   30  Norway       PhD

Lectura y cargue de datos

Aunque las estructuras de datos son útiles para trabajar en R, los datos que vamos a utilizar vienen en diferentes formatos de datos. Por tanto, es vital establecer una conexión entre la máquina y R. Este espacio en el cual estaremos trabajando se denomina Workspace y varía entre máquina y máquina. Sin embargo, R hace que funcione en diferentes tipos de computadores.

Lo primero que nos interesa es conocer nuestro actual directorio con la función getwd().

getwd()
## [1] "C:/Users/AndresEsteban/Dropbox/Sergio Arboleda/Curso R/Clases/Clase 1"

Una vez sabemos dónde estamos, queremos saber qué tenemos. Para esto, usamos el comando dir().

dir()
##  [1] "Clase 1.csv"     "Clase 1.nb.html" "Clase 1.pptx"   
##  [4] "Clase 1.Rmd"     "Clase 1.txt"     "Clase 1.xlsx"   
##  [7] "Clase_1.html"    "Clase_1.Rmd"     "test.R"         
## [10] "testdir"

Si queremos guardar nuestra ubicación actual, solamente debemos asignarlo a una variable.

old.dir <- getwd()

Ahora, sabemos que ahí no está el archivo que necesitamos. Vamos a crear un nuevo directorio que nos lleve a dónde está la información que necesito. Para eso, voy a usar la función dir.create()

dir.create("testdir")
## Warning in dir.create("testdir"): 'testdir' already exists

Recuerden que queremos cambiar tan poco como sea posible la información, o como dicen los creadores de R “Solamente toma foto, deja únicamente huellas”. Por eso, asignaremos nuestro trabajo a esta carpeta con el comando setwd()

setwd("testdir")

Ahora, crearemos y agregaremos archivos a esta carpeta con el comando file.create(). Para empezar crearemos un script de R al que llamaremos test.

file.create("test.R")
## [1] TRUE

En general, pueden revisar todas las funciones asociadas con file como exists, rename, copy, path

Ahora, lo que necesitamos hacer ahora es conseguir la información que tenemos en este directorio. Con el archivo de excel llamado “Clase 1” cargaremos esta información. Carguen este archivo en su directorio.

Hay una serie de formatos de datos comunes que se pueden leer dentro y fuera de R. Esto incluye archivos de texto en formatos como csv, txt, html y json. También incluye archivos de salida de aplicaciones estadísticas como SAS y SPSS. Los recursos en línea que incluyen servicios web y páginas HTML también se pueden leer en R.

Leyendo un archivo CSV

La primera función que examinaremos es read.table(). Esta es una función incorporada en R que puede utilizarse para leer varios formatos de archivo en un Data Frame. Esta es probablemente la función interna más común utilizada para leer archivos simples en R.

df = read.table("Clase 1.csv", header = TRUE, sep=",")

La función read.csv() también es una función incorporada en R que es casi idéntica a la read.table(), con la excepción de que los argumentos de encabezado y relleno se establecen en TRUE de forma predeterminada. En este paso, verás lo fácil que es cargar un archivo csv utilizando read.csv().

df2 = read.csv("Clase 1.csv")

Leyendo archivos de texto

La función read.table() se usa con más frecuencia para leer el contenido de un archivo delimitado por tabulaciones. En este paso aprenderás cómo hacerlo.

df3 = read.table("Clase 1.txt", header=TRUE, sep="\t", quote="")
## Warning in read.table("Clase 1.txt", header = TRUE, sep = "\t", quote =
## ""): line 1 appears to contain embedded nulls
## Warning in read.table("Clase 1.txt", header = TRUE, sep = "\t", quote =
## ""): line 2 appears to contain embedded nulls
## Warning in read.table("Clase 1.txt", header = TRUE, sep = "\t", quote =
## ""): line 3 appears to contain embedded nulls
## Warning in read.table("Clase 1.txt", header = TRUE, sep = "\t", quote =
## ""): line 4 appears to contain embedded nulls
## Warning in read.table("Clase 1.txt", header = TRUE, sep = "\t", quote =
## ""): line 5 appears to contain embedded nulls
## Warning in scan(file = file, what = what, sep = sep, quote = quote, dec =
## dec, : embedded nul(s) found in input

El uso de paquetes en R

En R, la unidad fundamental de código compartible es el paquete. Un paquete agrupa código, datos, documentación y pruebas, y es fácil de compartir con otros. A partir de enero de 2015, había más de 6,000 paquetes disponibles en Comprehensive R Archive Network, o CRAN, la cámara de compensación pública para paquetes de R. Esta gran variedad de paquetes es una de las razones por las que R es tan exitosa: lo más probable es que alguien ya haya resuelto un problema en el que estás trabajando, y puedes beneficiarte de su trabajo al descargar su paquete.

Si estás leyendo este libro, ya sabes cómo usar los paquetes:

Los instalas desde CRAN con install.packages("X"). Los usas en R con library("x"). *Recibes ayuda con package?X y help(package = "x").

En la próxima clase aprenderemos a trabajar con dos paquetes tidyverse() y readr().