- Introducción y objetivos
- Instalación R, Rstudio, paquetes
- Data managment, parte I
- ¿Cómo leer archivos en R?
- Funciones
- Estructuras de control
Introducción al uso de R como lenguaje de programación estadístico
El presente módulo introduce al participante en el manejo del software R, lo cual comprende la instalación y configuración del software necesario para el entorno de programación estadístico, la discusión de los conceptos del lenguaje de programación genéricos. Además, temas teórico-prácticos de la estadística, programación básica con el uso del script, manipulación de bases de datos, funciones y herramientas gráficas.
El objetivo del curso es actualizar-ampliar los conocimientos en la optimización de la gestión de información cuantitativa empoderando al participante de destrezas en el manejo del soft- ware R en data management, estadística descriptiva, gráficos, modelos lineales, clasificación, series de tiempo, con base a aplicaciones y casos prácticos.
- Introducir al participante en el uso del software R como lenguaje de programación.
- Mejorar las habilidades de gestión de información del participante.
- Incrementar el conocimiento de modelos y su aplicación.
Visión general de R: instalación RStudio y otros
Introducción
R es un sistema para análisis estadístico y gráficos creado por Robert Gentleman y Ross Ihaka, profesores del departamento de Estadística de University of Auckland - New Zealand.
Ventajas
- Open Source (Costo nulo) Comunidad dinámica integrada por estadísticos de renombre(R User Group Ecuador, Stackoverflow, Comunidad R Hispano, R en español,. . . )
- Multi-plataforma: Disponible para Windows, Mac, Linux y Android.
- Es de código abierto.
- Facilidad de enlace con LateX y generar reportes dinámicos.
- Amplia bibliografía en la web y libros publicados por editoriales prestigiosas (Springer, Wiley, Chapman & Hall,. . . )
- Lenguaje intuitivo para la lectura de funciones y algoritmos.
Desventajas
- Por ser un programa libre, no posee garantía ni un departamento de atención al cliente.
- R no posee una interfaz amigable, las tareas se llevan a través de líneas de código, lo cual puede ser incómodo para el usuario.
- R particularmente no es un lenguaje de programación rápida.
Instalación de R
- Ingresar a https://www.r-project.org/
- Elegir el CRAN (Comprehensive R Archive Network)
- Escoger versión del sistema operativo.
- Instalar R por primera vez.
R como una calculadora
3*8
## [1] 24
2.8/6.8
## [1] 0.4117647
sqrt(25)
## [1] 5
Además, cada operación anterior puede ser almacenada en un “objeto”
a<-3*8
b<-2.8/6.8
D<-sqrt(25)
Instalación de RStudio
- Ingresar a https://www.rstudio.com/
- Productos
- Escoger versión según el Sistema Operativo
Instalación de paquetes
Además de las funciones básicas, R tiene un gran número de paquetes especializados.
Los paquetes se instalan una sola vez y deben ser cargados en cada inicio de sesión.
Se utiliza la siguiente función:
install.packages("dplyr",dependencies = TRUE)
Una vez instalado, debemos cargarlo con cualquiera de estos comandos:
require(dplyr)
library("dplyr")
Para instalar un paquete desde otro repositorio:
install.packages("survey", repos="http://r-forge.r-project.org", type="source")
library(survey)
Desde github y con otra forma de cargar una función de una librería:
install.packages("githubinstall")
githubinstall::githubinstall("twitter/AnomalyDetection")
Otra forma de cargar desde github:
source("https://install-github.me/r-lib/callr")
library("callr")
Para poder ver los paquetes instalados y disponibles podemos utilizar:
library()
installed.packages()
.packages(all.available=TRUE)
available.packages()
Para saber cuál fue el último paquete instalado utilizamos:
(.packages())
Es importante saber que funciones tiene cada paquete, para esto utilizamos:
ls("package:dplyr")
Estructuras de Datos
Las estructuras de datos en R se organizan por: Dimensionalidad y Homogeneidad o heterogeneidad.
R no tiene estructuras 0d (tipo escalar). Los números y strings individuales son considerados como vectores de longitud 1.
# no mostrar advertencias
options(warn = -1)
x <- 9
x
## [1] 9
El texto luego de # es un comentario (no es interpretado por R). Para crear un objeto se utiliza el operador de asignación <-, =, ->.
y="SSh"
y
## [1] "SSh"
Vectores
La estructura de datos básica de R son los vectores, estos se dividen en Vectores atómicos y listas.
Propiedades:
Tipo: ¿Qué es?
typeof(x)
## [1] "double"
Longitud: Número de elementos.
length(x)
## [1] 1
Atributos: Características.
attributes(x)
## NULL
Vectores Atómicos
Los elementos de un vector atómico son del mismo tipo a diferencia de los elementos de una lista que pueden ser de diferente tipo. Los tipos comunes son:
- double (numeric)
- integer
- character
- logical
Función combinar
Un vector es creado mediante la función c( ) (combinar).
vec <- c(1, 2)
vec
## [1] 1 2
Tipos de Vectores Atómicos:
Vector double;
dbl_vec <- c(3.5, 2, -1)
Vector entero: Use el sufijo L para crear un vector entero;
int_vec <- c(3L, 7L, 1L)
Vector caracter: Use “ ” para crear un vector caracter;
chr_vec <- c("R", "Users", "Group - Ecuador")
Vector lógico: Use TRUE y FALSE o T y F para crear un vector lógico.
log_vec <- c(FALSE, TRUE, F, T)
Para determinar si un vector vec es atómico utilizamos is.atomic(vec).
vec <- c(3.5, 2, -1)
is.atomic(vec)
## [1] TRUE
Para determinar el tipo de un vector vec utilizamos typeof(vec).
vec <- c("R", "Users", "Group - Ecuador")
typeof(vec)
## [1] "character"
Para verificar si un vector vec es de un tipo en específico, se utilizan las funciones “is”:
is.character(vec)
## [1] TRUE
is.double(vec)
## [1] FALSE
is.integer(vec)
## [1] FALSE
is.logical(vec)
## [1] FALSE
Elementos de un vector atómico: La componente i de vec se obtiene mediante vec[i].
Componente 5 de vec:
vec <- c(6, 1, 3, 6, 10, 5)
vec[5]
## [1] 10
Para seleccionar varios elementos utilizamos vec[c(elementos)].
# elementos 2 y 4
vec[c(2, 4)]
## [1] 1 6
Para omitir el elemento i de vec se utiliza vec[-i].
vec <- c(6, 1, 3, 6, 10, 5)
vec[-5]
## [1] 6 1 3 6 5
Para omitir varios elementos utilizamos vec[-c(elementos)].
# omitir los elementos 2 y 4
vec[-c(2, 4)]
## [1] 6 3 10 5
Generación de secuencias: El operador a:b genera el vector a, a+1, a+2, …, b.
1:10
## [1] 1 2 3 4 5 6 7 8 9 10
5:-5
## [1] 5 4 3 2 1 0 -1 -2 -3 -4 -5
La función seq( ) genera secuencias controlando: inicio, fin y salto.
seq(from = 1, to = 10, by = 0.5)
## [1] 1.0 1.5 2.0 2.5 3.0 3.5 4.0 4.5 5.0 5.5 6.0 6.5 7.0 7.5
## [15] 8.0 8.5 9.0 9.5 10.0
seq(from = -4, to = 4, length = 5)
## [1] -4 -2 0 2 4
vec[c(TRUE, FALSE)] permite obtener determinados elementos:
# elementos 2, 4, 6
vec <- c(6, 1, 3, 6, 10, 5)
vec[c(FALSE, TRUE, FALSE, TRUE, FALSE, TRUE)]
## [1] 1 6 5
Equivalente a:
vec[c(2, 4, 6)]
## [1] 1 6 5
Operaciones con vectores
A continuación, se resumen las operaciones básicas con vectores atómicos:
Función all(x) retorna TRUE si todas las componentes de x son TRUE.
x <- c(TRUE, TRUE, TRUE)
all(x)
## [1] TRUE
y <- c(TRUE, FALSE, TRUE)
all(y)
## [1] FALSE
Función any(x) retorna TRUE si al menos una componente de x es TRUE.
x <- c(FALSE, FALSE, FALSE)
any(x)
## [1] FALSE
y <- c(FALSE, TRUE, FALSE)
any(y)
## [1] TRUE
Negación !x cambia las componentes de x de: TRUE a FALSE y de FALSE a TRUE:
x <- c(TRUE, FALSE, TRUE)
!x
## [1] FALSE TRUE FALSE
Conjunción x & y retorna TRUE solo si las componentes de x & y son TRUE:
x <- c(TRUE, TRUE, FALSE)
y <- c(FALSE, TRUE, TRUE)
x & y
## [1] FALSE TRUE FALSE
x && y # conjuncion para escalares
## [1] FALSE
Disyunción x | y retorna TRUE si al menos una componente de x o y es TRUE
x <- c(TRUE, TRUE, FALSE)
y <- c(FALSE, TRUE, TRUE)
x | y
## [1] TRUE TRUE TRUE
x || y # disyuncion para escalares
## [1] TRUE
Dado un vector lógico x:
x <- c(TRUE, TRUE, FALSE, TRUE, FALSE)
sum(x). Cuenta el número de TRUE en x.
sum(x)
## [1] 3
mean(x). Muestra el porcentaje de TRUE en x.
mean(x)
## [1] 0.6
sum(x)/length(x)
## [1] 0.6
Test de igualdad y desigualdad
x <- c(3, 5, 2, 3, 1)
x==3
## [1] TRUE FALSE FALSE TRUE FALSE
y <- x==3 # componentes iguales a 3
z <- x!=3 # componentes distintas a 3
data.frame(x, y, z)
## x y z
## 1 3 TRUE FALSE
## 2 5 FALSE TRUE
## 3 2 FALSE TRUE
## 4 3 TRUE FALSE
## 5 1 FALSE TRUE
x[x!=3] # componentes de x distintas a 3
## [1] 5 2 1
Coerción: Si combinamos tipos diferentes, serán coercionados al tipo más flexible dado por la jerarquía:
Para coercionar un vector x a un determinado tipo, se utilizan las funciones “as”
as.character(x)
## [1] "3" "5" "2" "3" "1"
as.double(x)
## [1] 3 5 2 3 1
as.integer(x)
## [1] 3 5 2 3 1
as.logical(x)
## [1] TRUE TRUE TRUE TRUE TRUE
as.numeric(x)
## [1] 3 5 2 3 1
Listas
Una lista es un vector que puede contener elementos de cualquier tipo y de distinta longitud.
Para crear una lista se utiliza la función list() en lugar de c().
lst <- list(c(1, 2), c(TRUE), c("a", "b", "c"))
lst
## [[1]]
## [1] 1 2
##
## [[2]]
## [1] TRUE
##
## [[3]]
## [1] "a" "b" "c"
Tests para una lista:
lst <- list(1:3, c("R", "Users", "Group - Ecuador"), c(TRUE, FALSE), c(1.3, 4.5))
typeof(lst)
## [1] "list"
is.atomic(lst)
## [1] FALSE
Para probar si lst es una lista se utiliza:
is.list(lst)
## [1] TRUE
Coerción de vector atómico lst a una lista
lst <- c("ssl", 4, 0.5)
as.list(lst)
## [[1]]
## [1] "ssl"
##
## [[2]]
## [1] "4"
##
## [[3]]
## [1] "0.5"
Coerción de lista lst a vector atómico (reglas de coerción)
lst <- list(1:3, c("R", "Users", "Group - Ecuador"), c(TRUE, FALSE), c(1.3, 4.5))
unlist(lst)
## [1] "1" "2" "3"
## [4] "R" "Users" "Group - Ecuador"
## [7] "TRUE" "FALSE" "1.3"
## [10] "4.5"
Elementos de una lista: Para acceder al elemento i de la lista se utiliza x[i]. Para acceder al objeto que contiene el elemento i se utiliza x[[i]].
lst <- list(c(1, 2), c(TRUE), c("a", "b", "c"))
lst[1]
## [[1]]
## [1] 1 2
lst[[1]]
## [1] 1 2
En una lista con nombre podemos utilizar el simbolo $ para extraer determinados elementos:
lst <- list(v=1:3, w=c("R", "Users", "Group - Ecuador"), x=c(TRUE, FALSE), y=c(1.3, 4.5))
lst$w
## [1] "R" "Users" "Group - Ecuador"
Utilizar lst$w resulta equivalente a utilizar lst[[2]]
lst[[2]]
## [1] "R" "Users" "Group - Ecuador"
Atributos
Los objetos en R poseen varios atributos tales como: names, class, dim, etc. La función attributes(x) muestra los atributos de un objeto x.
Vector atómico:
# Vector sin el atributo names
vec <- c(3, 6, -1, 0.5)
attributes(vec)
## NULL
# Vector con el atributo names
vec <- c(a=3, b=6, c=-1, d=0.5)
attributes(vec)
## $names
## [1] "a" "b" "c" "d"
Lista:
# Lista sin el atributo names
lst <- list(1:3, c("R", "Users", "Group - Ecuador"), c(TRUE, FALSE))
attributes(lst)
## NULL
# Lista con el atributo names
lst <- list(nomb1=1:3, nomb2=c("R", "Users", "Group - Ecuador"), nomb3=c(TRUE,FALSE))
attributes(lst)
## $names
## [1] "nomb1" "nomb2" "nomb3"
Matrices
Una matriz es un vector con el atributo dimensión dim. El atributo dim es un vector de longitud 2: c(nrow, ncol).
mtx <- matrix (1:12,nrow=3, ncol=4, byrow=FALSE)
# se construye por columnas por default (byrow=FALSE)
mtx
## [,1] [,2] [,3] [,4]
## [1,] 1 4 7 10
## [2,] 2 5 8 11
## [3,] 3 6 9 12
dim() se usa para añadir el atributo dimensión a un vector, o para hallar la dimensión de una matriz.
mtx <- 1:12
mtx
## [1] 1 2 3 4 5 6 7 8 9 10 11 12
dim(mtx) <- c(3,4)
mtx
## [,1] [,2] [,3] [,4]
## [1,] 1 4 7 10
## [2,] 2 5 8 11
## [3,] 3 6 9 12
mtx <- matrix (1:12, nrow=3, ncol=4, byrow=FALSE)
dim(mtx)
## [1] 3 4
Elementos de una matriz:
(mtx <- matrix (1:12, nrow=3, ncol=4, byrow=FALSE))
## [,1] [,2] [,3] [,4]
## [1,] 1 4 7 10
## [2,] 2 5 8 11
## [3,] 3 6 9 12
mtx[1,2] # componente 1, 2
## [1] 4
mtx[,3] # columna 3
## [1] 7 8 9
mtx[1,] # fila 1
## [1] 1 4 7 10
mtx[,c(2,4)] # columnas 2 y 4
## [,1] [,2]
## [1,] 4 10
## [2,] 5 11
## [3,] 6 12
mtx[c(1,3),] # filas 1 y 3
## [,1] [,2] [,3] [,4]
## [1,] 1 4 7 10
## [2,] 3 6 9 12
mtx[,c(FALSE, TRUE, TRUE, FALSE)] # columnas 2 y 4
## [,1] [,2]
## [1,] 4 7
## [2,] 5 8
## [3,] 6 9
mtx[c(TRUE, FALSE, TRUE),] # filas 1 y 3
## [,1] [,2] [,3] [,4]
## [1,] 1 4 7 10
## [2,] 3 6 9 12
Factores
Es la estructura de datos utilizada para almacenar variables categóricas. ¿Por qué utilizar factores?
Un vector c(Femenino, Masculino) (factor) presenta mayor información que un vector c(1, 2).
Un vector character c(“Femenino”, “Masculino”) no pueden ser incluido en modelos de regresión, un factor c(Femenino, Masculino) si.
Un factor se crea mediante la función: factor()
Si se dispone de un vector integer:
vec <- c(1, 2, 2, 1, 2, 1, 2)
vec
## [1] 1 2 2 1 2 1 2
La función factor asigna labels a los levels (o categorías) de la variable. Los levels del vector vec son los valores 1, 2.
# Creación de un factor
fac <- factor(vec, levels=c(1,2), labels = c("Femenino", "Masculino"))
fac
## [1] Femenino Masculino Masculino Femenino Masculino Femenino Masculino
## Levels: Femenino Masculino
Si se dispone de un vector character:
# Creación de un factor
vec <- c("Femenino","Masculino","Masculino","Femenino","Masculino", "Femenino","Masculino")
vec
## [1] "Femenino" "Masculino" "Masculino" "Femenino" "Masculino" "Femenino"
## [7] "Masculino"
La función factor asigna labels a los levels (o categorías) de la variable. En este caso los levels del vector vec son los valores “Femenino”, “Masculino”.
# Creación de un factor
# por defecto labels = levels
fac <- factor(vec, levels= c("Femenino", "Masculino"), labels=c("FEM", "MASC"))
fac
## [1] FEM MASC MASC FEM MASC FEM MASC
## Levels: FEM MASC
Para obtener los atributos de un factor utilizamos attributes().
vec <- c(1, 2, 2, 1, 2, 1, 2)
fac <- factor(vec, levels=c(1,2), labels = c("Femenino", "Masculino"))
# Atributos de un factor
attributes(fac)
## $levels
## [1] "Femenino" "Masculino"
##
## $class
## [1] "factor"
Para considerar el vector entero utilizamos unclass().
# eliminación del atributo class
unclass(fac)
## [1] 1 2 2 1 2 1 2
## attr(,"levels")
## [1] "Femenino" "Masculino"
Para realizar conteos por categoría, se utiliza la función table().
fac <- factor(vec, levels=c(1,2), labels = c("Femenino", "Masculino"))
# frecuencias table(fac)
# porcentaje
prop.table(table(fac))
## fac
## Femenino Masculino
## 0.4285714 0.5714286
Data Frame
Es una lista en la cual todos los elementos tienen la misma longitud. A diferencia de las matrices, pueden almacenar vectores atómicos de cualquier tipo. Presenta varios atributos adicionales class, rownames, names. Es la estructura de datos más utilizada para almacenar data tabulada.
Para crear un data frame se utiliza la función data.frame(). Con los siguientes vectores atómicos:
dbl_vec <- c(1, 2, 3)
chr_vec <- c("R", "S", "T")
log_vec <- c(TRUE, FALSE, TRUE)
Creamos el data frame df:
df <- data.frame(dbl_vec, chr_vec, log_vec)
df
## dbl_vec chr_vec log_vec
## 1 1 R TRUE
## 2 2 S FALSE
## 3 3 T TRUE
Un data frame es una lista:
typeof(df) # Tipo de un data frame
## [1] "list"
Su clase es data.frame:
class(df)
## [1] "data.frame"
Atributos de un data frame:
attributes(df)
## $names
## [1] "dbl_vec" "chr_vec" "log_vec"
##
## $row.names
## [1] 1 2 3
##
## $class
## [1] "data.frame"
Nombres de las columnas de df:
names(df)
## [1] "dbl_vec" "chr_vec" "log_vec"
Nombres de las filas de df:
rownames(df)
## [1] "1" "2" "3"
Dimensión: Filas y columnas
dim(df)
## [1] 3 3
Número de filas y columnas
nrow(df)
## [1] 3
Elementos de un data frame:
Mediante df[i, j] se obtiene la componente i, j del data frame.
nomb <- c("John", "Paul", "George", "Ringo")
nac <- c(1940, 1941, 1943, 1940)
instr <- c("guitar", "bass", "guitar", "drums")
df <- data.frame(nomb, nac, instr)
df[2, c(2,3)]
## nac instr
## 2 1941 bass
print(df)
## nomb nac instr
## 1 John 1940 guitar
## 2 Paul 1941 bass
## 3 George 1943 guitar
## 4 Ringo 1940 drums
df[2, 2] # componente 2, 2
## [1] 1941
df[3, 1] # componente 3, 1
## [1] George
## Levels: George John Paul Ringo
df[c(1, 4), ] # filas 1, 4
## nomb nac instr
## 1 John 1940 guitar
## 4 Ringo 1940 drums
Se pueden seleccionar ciertas filas mediante TRUE y FALSE.
df[c(TRUE, TRUE, FALSE, TRUE), ] # equivalente a df[c(1, 2, 4), ]
## nomb nac instr
## 1 John 1940 guitar
## 2 Paul 1941 bass
## 4 Ringo 1940 drums
Importante: Reciclado:
df[c(TRUE, FALSE), ] # equivalente a df[c(1, 3), ]
## nomb nac instr
## 1 John 1940 guitar
## 3 George 1943 guitar
Importante: Filtrado o subsetting:
df[ , 3]=="guitar" # columna 3 de df igual a "guitar"
## [1] TRUE FALSE TRUE FALSE
f_guitar <- df[ , 3]=="guitar"
Filas donde la columna 3 es igual a “guitar”
df[f_guitar, ]
## nomb nac instr
## 1 John 1940 guitar
## 3 George 1943 guitar
df[ , c(1, 3)] # columnas 1, 3
## nomb instr
## 1 John guitar
## 2 Paul bass
## 3 George guitar
## 4 Ringo drums
Columna de nombre “nac”
df[ , "nac"] # equivalente a df[ , 2]
## [1] 1940 1941 1943 1940
Columnas de nombres “nomb y nac”
df[ , c("nomb", "nac")] # equivalente a df[ , c(1, 2)]
## nomb nac
## 1 John 1940
## 2 Paul 1941
## 3 George 1943
## 4 Ringo 1940
Se pueden seleccionar ciertas columnas mediante TRUE y FALSE:
df[ , c(TRUE, FALSE, TRUE)] # equivalente a df[ , c(1, 3)]
## nomb instr
## 1 John guitar
## 2 Paul bass
## 3 George guitar
## 4 Ringo drums
Importante: Reciclado
df[ , c(TRUE, FALSE)] # equivalente a df[ , c(1, 3)]
## nomb instr
## 1 John guitar
## 2 Paul bass
## 3 George guitar
## 4 Ringo drums
R Data Frames
R posee varios data frames en sus bases de datos internas, por ejemplo: mtcars
data(mtcars)
Visualización:
View(mtcars)
# n primeras filas
head(mtcars,n = 2)
## mpg cyl disp hp drat wt qsec vs am gear carb
## Mazda RX4 21 6 160 110 3.9 2.620 16.46 0 1 4 4
## Mazda RX4 Wag 21 6 160 110 3.9 2.875 17.02 0 1 4 4
# n últimas filas
tail(mtcars,n = 2)
## mpg cyl disp hp drat wt qsec vs am gear carb
## Maserati Bora 15.0 8 301 335 3.54 3.57 14.6 0 1 5 8
## Volvo 142E 21.4 4 121 109 4.11 2.78 18.6 1 1 4 2
Atributos del data frame:
attributes(mtcars)
## $names
## [1] "mpg" "cyl" "disp" "hp" "drat" "wt" "qsec" "vs" "am" "gear"
## [11] "carb"
##
## $row.names
## [1] "Mazda RX4" "Mazda RX4 Wag" "Datsun 710"
## [4] "Hornet 4 Drive" "Hornet Sportabout" "Valiant"
## [7] "Duster 360" "Merc 240D" "Merc 230"
## [10] "Merc 280" "Merc 280C" "Merc 450SE"
## [13] "Merc 450SL" "Merc 450SLC" "Cadillac Fleetwood"
## [16] "Lincoln Continental" "Chrysler Imperial" "Fiat 128"
## [19] "Honda Civic" "Toyota Corolla" "Toyota Corona"
## [22] "Dodge Challenger" "AMC Javelin" "Camaro Z28"
## [25] "Pontiac Firebird" "Fiat X1-9" "Porsche 914-2"
## [28] "Lotus Europa" "Ford Pantera L" "Ferrari Dino"
## [31] "Maserati Bora" "Volvo 142E"
##
## $class
## [1] "data.frame"
Nombres de las columnas:
names(mtcars)
## [1] "mpg" "cyl" "disp" "hp" "drat" "wt" "qsec" "vs" "am" "gear"
## [11] "carb"
colnames(mtcars)
## [1] "mpg" "cyl" "disp" "hp" "drat" "wt" "qsec" "vs" "am" "gear"
## [11] "carb"
Nombres de las filas
rownames(mtcars)
## [1] "Mazda RX4" "Mazda RX4 Wag" "Datsun 710"
## [4] "Hornet 4 Drive" "Hornet Sportabout" "Valiant"
## [7] "Duster 360" "Merc 240D" "Merc 230"
## [10] "Merc 280" "Merc 280C" "Merc 450SE"
## [13] "Merc 450SL" "Merc 450SLC" "Cadillac Fleetwood"
## [16] "Lincoln Continental" "Chrysler Imperial" "Fiat 128"
## [19] "Honda Civic" "Toyota Corolla" "Toyota Corona"
## [22] "Dodge Challenger" "AMC Javelin" "Camaro Z28"
## [25] "Pontiac Firebird" "Fiat X1-9" "Porsche 914-2"
## [28] "Lotus Europa" "Ford Pantera L" "Ferrari Dino"
## [31] "Maserati Bora" "Volvo 142E"
Dimensiones en un data frame:
# Dimensión
dim(mtcars)
## [1] 32 11
# Número columnas
ncol(mtcars)
## [1] 11
# Número filas
nrow(mtcars)
## [1] 32
Función structure
La función str() (structure) presenta una descripción compacta de la estructura de datos. Usar View() es costoso computacionalmente.
str(mtcars)
## 'data.frame': 32 obs. of 11 variables:
## $ mpg : num 21 21 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 ...
## $ cyl : num 6 6 4 6 8 6 8 4 4 6 ...
## $ disp: num 160 160 108 258 360 ...
## $ hp : num 110 110 93 110 175 105 245 62 95 123 ...
## $ drat: num 3.9 3.9 3.85 3.08 3.15 2.76 3.21 3.69 3.92 3.92 ...
## $ wt : num 2.62 2.88 2.32 3.21 3.44 ...
## $ qsec: num 16.5 17 18.6 19.4 17 ...
## $ vs : num 0 0 1 1 0 1 0 1 1 1 ...
## $ am : num 1 1 1 0 0 0 0 0 0 0 ...
## $ gear: num 4 4 4 3 3 3 3 4 4 4 ...
## $ carb: num 4 4 1 1 2 1 4 2 2 4 ...
Missing Values
Los valores perdidos en R se denotan por NA, NaN. NA Not Available. Dato perdido.
x <- c(NA, 3.2, NA, 5, NA)
x
## [1] NA 3.2 NA 5.0 NA
NaN Not a Number. Resultado de una indeterminación:
y <- c(-1, 0/0, 0.8, 5, Inf*0)
y
## [1] -1.0 NaN 0.8 5.0 NaN
Inf representa infinito.
is.na(x) retorna TRUE para elementos NA de un vector atómico o lista.
x <- c(0, 3.2, NA, 5, NA)
is.na(x)
## [1] FALSE FALSE TRUE FALSE TRUE
is.nan(x) retorna TRUE para elementos NaN de un vector atómico.
y <- c(-1, 0/0, 5, Inf*0)
is.nan(y)
## [1] FALSE TRUE FALSE TRUE
Importación y Exportación de datos
Lectura de datos
R puede acceder a información almacenada en distintos formatos:
Archivos de excel .xls, .xlsx, .csv; Archivos de texto plano .txt; Archivos de spss .sav; Archivos de la web; Archivos de bases de datos, etc.
Directorio de trabajo
Working directory (wd). Es la dirección donde se almacenan, leen y escriben los archivos utilizados y generados mediante R. getwd() permite obtener el wd actual:
getwd()
## [1] "C:/Users/crbdl/Desktop"
setwd() permite setear un nuevo wd, por ejemplo:
setwd("C:/Documentos/R_users_group")
list.files() enlista los nombres de los archivos en el wd actual. El parámetro pattern se usa para enlistar los nombres de los archivos que contienen un determinado patrón.
list.files(pattern = ".R")
file.exists() verifica si existe una carpeta con un determinado nombre en el wd.
# Verifica si existe o no una carpeta con nombre "r_users"
file.exists("r_users")
## [1] FALSE
dir.create() permite crear nuevas carpetas en el wd.
# Crea una nueva carpeta con nombre "files"
dir.create("files")
R sobreescribe una carpeta sobre otra, de ahí la importancia de utilizar previamente file.exists().
Lectura de archivos .txt
Se requiere leer un archivo en formato txt: archivo.txt. Se utiliza la función read.table()
data_txt <- read.table(file = "archivo.txt",sep = "\t", dec = ",", header = TRUE)
str(data_txt)
Parámetros:
file: nombre del archivo (incluida extensión); sep: caracter utilizado para separar columnas (variables); dec: caracter utilizado para decimales; header: TRUE, si la primera fila contiene los nombres de las columnas.
str() describe la estructura de datos.
Por defecto R coerciona las variables categóricas a factor. El parametro stringsAsFactors=FALSE evita esta coerción.
data_txt <- read.table(file = "archivo.txt",sep = "\t", dec = ",", header = TRUE, stringsAsFactors = FALSE)
Lectura de archivos .csv
Se requiere leer un archivo en formato csv: archivo.csv, se utiliza las función read.csv que presenta por defecto los argumentos: sep = “,”, dec = “.”, , header = TRUE
data_csv <- read.csv(file = "archivo.csv")
read.csv2(): Se debe especificar los argumentos: sep, dec, header
data_csv2 <- read.csv2(file = "archivo.csv",sep = ",", dec = ".", header = TRUE)
Lectura de archivos .xls, .xlsx
Se requiere leer un archivo en formato xls o xlsx: archivo.xlsx. Se utiliza la función read_excel() del paquete readxl
install.packages("readxl", dependencies = TRUE)
library(readxl)
ls("package:readxl")
Lectura del archivo archivo.xlsx:
data_xlsx <- read_excel("archivo.xlsx",sheet = "datos",col_names = TRUE, na="")
read.table("clipboard",sep = "\t",header = FALSE)
Parámetros:
sheet: Nombre de la hoja que contiene la data (recibe también el número de hoja); col_names: TRUE si la primera fila contiene los nombres de las columnas; na: los caracter que se coerciona a NA.
Lectura de archivos .sav
Se requiere leer archivos desde spss, es decir en formato .sav: archivo.sav. Se utiliza la función read.spss() del paquete foreign.
install.packages("foreign", dependencies = TRUE)
library(foreign)
ls("package:foreign")
data_sav <- read.spss(file="archivo.sav", use.value.labels = TRUE, to.data.frame = TRUE)
Parámetros:
file: nombre del archivo (incluida extensión); use.value.labels: TRUE, si se consideran las etiquetas de las variables; to.data.frame: TRUE, para coercionar el archivo leído a data frame.
Introducción
Una función es un conjunto de instrucciones, que a partir de uno o más datos de entrada, permiten generar y retornar un detrminado resultado.
¿Porqué construir funciones?
Practicidad: Permiten ejecutar un conjunto de instrucciones en una sola línea de código. Ejemplo: La función sort , las instrucciones necesarias para ordenar un vector.
x <- c(3, 1, 6, 2)
x
## [1] 3 1 6 2
sort (x)
## [1] 1 2 3 6
Generalización: Permiten diseñar códigos para casos determinados y ajustarlos a casos generales.
Ejemplo: Hallar la media de 3 y 4
(3 + 4) / 2
## [1] 3.5
Para hallar el promedio de varios pares de números, creamos la función promedio.
promedio <- function(a, b) {
prom <- (a + b) / 2
return (prom)
}
Estructura de una función
El comando function() tiene como tarea crear funciones a partir de ciertos argumentos que son proporcionados por el usuario.
No existe un límite en la cantidad de argumentos que una función puede recibir.
promedio_pond <- function(a, b, peso1, peso2) {
prom <- peso1*a + peso2*b
return (prom)
}
Ejemplos:
promedio_pond(a= 1, b = 5, peso1 = 0.8, peso2 = 0.2)
## [1] 1.8
Argumentos por default
Existen ocasiones que no se requieren ingresar ciertos argumentos para que la función pueda ejecutarse.
Estos valores por default deben colocarse en la función:
promedio_pond <- function(a, b, peso1 = 0.5, peso2 = 0.5) {
prom <- peso1*a + peso2*b
return (prom)
}
promedio_pond(a = 1, b = 5)
## [1] 3
Lexical Scoping
Variable libre: Una variable en una función se dice libre si no ha sido definida o no es un argumento.
El lexical Scoping permite entender cómo R asocia un valor a una variable libre (crear un objeto).
f <- function(x, y) {
return(x^2 + y / z)
}
Argumentos: x, y. Variables libres: z.
f(x = 3, y = 6)
## [1] Inf 15 15 Inf 15
Considere la siguiente función:
z <- 10
f <- function(x) {
z <- 2
z^2 + g(x)
}
g <- function(x) {
x*z
}
Cuál es el valor de f(x = 3) ?
f(x = 3)
## [1] 34
Sentencia if
La sentencia if realiza una tarea para un determinado caso.
CONDICION: Vector lógico 1d TRUE/FALSE . Si condicion es TRUE se ejecuta la tarea. Forma de declarar la sentencia if:
x <- 2
if(x > 0) {
x <- x + 1
}
x
## [1] 3
Sentencia else
La sentencia else trabaja conjuntamente con la sentencia if
Si la condición es TRUE se ejecuta la Tarea 1, caso contrario se ejecuta la Tarea 2.
Sentencia if else
Forma de declarar la sentencia if else :
x <- -1
if (x >= 0) {
print("El número es positivo")
} else {
print("El número es negativo")
}
## [1] "El número es negativo"
Sentencia for
La sentencia for permite repetir una acción un número determinado de veces.
Forma de declarar la sentencia for:
Ejemplo: Suma de filas/columnas: m: matriz de 4x3 de Poisson
m <- matrix(data = rpois(n = 12, lambda = 8), nrow = 4, ncol = 3)
m
## [,1] [,2] [,3]
## [1,] 7 8 9
## [2,] 10 14 8
## [3,] 8 10 7
## [4,] 6 11 6
col_sumas <- numeric(ncol(m))
for (i in 1:4){
col_sumas[i] <- sum(m[i,])
}
col_sumas
## [1] 24 32 25 23
Funciones loop tipo ”apply”
apply
Apply se utiliza para evaluar una función (a menudo anónima) sobre los márgenes de una matriz. Se utiliza con mayor frecuencia para aplicar una función a las filas o columnas de una matriz. Se puede usar con matrices generales, p. Tomando el promedio de una matriz de matrices no es realmente más rápido que escribir un bucle, pero funciona en una línea!
str(apply)
## function (X, MARGIN, FUN, ...)
X es una matriz
MARGIN es un vector entero que indica qué márgenes deben ser retenidos“. FUN es una función a ser aplicada para que otros argumentos sean pasados a FUN
x <- matrix(rnorm(200), 20, 10)
apply(x, 2, mean)
## [1] 0.375680998 -0.386917588 -0.337469042 -0.253210969 -0.095369786
## [6] 0.006149434 -0.262256608 -0.151185842 0.030029833 -0.262586216
col/row Sumas y Medias
Para las sumas y los medias de las dimensiones de la matriz, tenemos algunos atajos:
rowSums = apply(x, 1, sum)
rowMeans = apply(x, 1, mean)
colSums = apply(x, 2, sum)
colMeans = apply(x, 2, mean)
Las funciones de acceso directo son mucho más rápidas, pero no te darás cuenta a menos que estés usando una matriz grande.
Otras Formas de Aplicar
Quantiles de las filas de una matriz.
x <- matrix(rnorm(200), 20, 10)
apply(x, 1, quantile, probs = c(0.25, 0.75))
## [,1] [,2] [,3] [,4] [,5] [,6]
## 25% -0.9986528 -1.329281 -0.6930205 -0.4490333 -0.1848993 -0.5006163
## 75% 0.1255915 0.359086 0.8898816 0.6627382 0.7923025 0.3157985
## [,7] [,8] [,9] [,10] [,11] [,12]
## 25% -0.4413362 -1.0880216 -0.3640341 -0.8919106 -0.3917338 -1.0468530
## 75% 0.4240068 0.7934426 0.3140949 0.7787425 0.8882287 0.6145108
## [,13] [,14] [,15] [,16] [,17] [,18]
## 25% -1.0982383 -0.5216335 -0.8433666 -0.3522312 -0.9730085 -0.6937552
## 75% -0.1730996 0.4500281 0.7283369 0.6748745 0.3634782 0.9827490
## [,19] [,20]
## 25% -0.7897723 0.02118837
## 75% 0.4957886 1.21741085
Matriz media en una matriz
a <- array(rnorm(2 * 2 * 10), c(2, 2, 10))
apply(a, c(1, 2), mean)
## [,1] [,2]
## [1,] 0.2332499 -0.07410178
## [2,] 0.2385339 0.49606679
tapply
tapply se utiliza para aplicar una función sobre subconjuntos de un vector.
str(tapply)
## function (X, INDEX, FUN = NULL, ..., simplify = TRUE)
X es un vector INDICE es un factor o una lista de factores (o bien son coaccionados a factores) FUN es una función a ser aplicada contiene otros argumentos para ser evaluados FUN simplificar, ¿debemos simplificar el resultado?
Tomar grupos significa:
x <- c(rnorm(10), runif(10), rnorm(10, 1))
f <- gl(3, 10)
f
## [1] 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 3 3
## Levels: 1 2 3
Tomar medias de grupos sin simplificación.
tapply(x, f, mean, simplify = FALSE)
## $`1`
## [1] -0.4014109
##
## $`2`
## [1] 0.5845753
##
## $`3`
## [1] 0.7220379
Encuentra rangos de grupo.
tapply(x, f, range)
## $`1`
## [1] -2.1083360 0.9654397
##
## $`2`
## [1] 0.3911844 0.8530016
##
## $`3`
## [1] -0.1659212 3.1330298
lapply y sapply
La escritura de while es útil cuando se programa pero no es especialmente fácil cuando se trabaja interactivamente en la línea de comandos. Hay algunas funciones que implementan bucles para facilitar la vida.
Lapply: Bucle sobre una lista y evaluar una función en cada elemento Sapply: Lo mismo que lapply pero intenta simplificar el resultado Apply: Aplicar una función sobre los márgenes de una matriz Tapply: Aplicar una función sobre subconjuntos de un vector Mapply: Versión multivariable de lapply
También es útil una división de función auxiliar, particularmente en conjunción con lapply.
lapply
Lapply toma tres argumentos: (1) una lista X; (2) una función (o el nombre de una función) FUN; (3) otros argumentos a través de su argumento. Si X no es una lista, será coaccionado a una lista usando as.list.
lapply
## function (X, FUN, ...)
## {
## FUN <- match.fun(FUN)
## if (!is.vector(X) || is.object(X))
## X <- as.list(X)
## .Internal(lapply(X, FUN))
## }
## <bytecode: 0x0000000012af6640>
## <environment: namespace:base>
El bucle real se realiza internamente en código C.
Lapply siempre devuelve una lista, independientemente de la clase de la entrada.
x <- list(a = 1:4, b = rnorm(10), c = rnorm(20, 1), d = rnorm(100, 5))
lapply(x, mean)
## $a
## [1] 2.5
##
## $b
## [1] 0.6970291
##
## $c
## [1] 1.138907
##
## $d
## [1] 5.188079
x <- 1:4
lapply(x, runif)
## [[1]]
## [1] 0.3899072
##
## [[2]]
## [1] 0.6053326 0.2631529
##
## [[3]]
## [1] 0.7674535 0.2481148 0.6048053
##
## [[4]]
## [1] 0.9630127 0.6112869 0.3498528 0.5991059
x <- 1:4
lapply(x, runif, min = 0, max = 10)
## [[1]]
## [1] 5.099684
##
## [[2]]
## [1] 6.049304 5.235927
##
## [[3]]
## [1] 5.605220 9.718606 2.388543
##
## [[4]]
## [1] 3.347105 6.844083 6.963573 1.313079
Lapply permite hacer un uso intensivo de funciones anónimas.
x <- list(a = matrix(1:4, 2, 2), b = matrix(1:6, 3, 2))
x
## $a
## [,1] [,2]
## [1,] 1 3
## [2,] 2 4
##
## $b
## [,1] [,2]
## [1,] 1 4
## [2,] 2 5
## [3,] 3 6
Una función anónima para extraer la primera columna de cada matriz.
lapply(x, function(elt) elt[,1])
## $a
## [1] 1 2
##
## $b
## [1] 1 2 3
Sapply
Sapply tratará de simplificar el resultado de lapply si es posible.
Si el resultado es una lista donde cada elemento es la longitud 1, entonces se devuelve un vector
Si el resultado es una lista donde cada elemento es un vector de la misma longitud (>1), se devuelve una matriz.
Y no puede calcular, se devuelve una lista
x <- list(a = 1:4, b = rnorm(10), c = rnorm(20, 1), d = rnorm(100, 5))
lapply(x, mean)
## $a
## [1] 2.5
##
## $b
## [1] -0.1764945
##
## $c
## [1] 0.8521396
##
## $d
## [1] 5.056278
sapply(x, mean)
## a b c d
## 2.5000000 -0.1764945 0.8521396 5.0562784
mapply
Mapply es una aplicación multivariable de tipos que aplica una función en paralelo sobre un conjunto de argumentos.
str(mapply)
## function (FUN, ..., MoreArgs = NULL, SIMPLIFY = TRUE, USE.NAMES = TRUE)
FUN es una función para aplicar … contiene argumentos para aplicar MoreArgs es una lista de otros argumentos para FUN. SIMPLIFY indica si el resultado debe ser simplificado
El siguiente listado es tedioso digitar: list(rep(1, 4), rep(2, 3), rep(3, 2), rep(4, 1)) Por lo cual se puede hacer:
mapply(rep, 1:4, 4:1)
## [[1]]
## [1] 1 1 1 1
##
## [[2]]
## [1] 2 2 2
##
## [[3]]
## [1] 3 3
##
## [[4]]
## [1] 4
Vectorizando una Función
noise <- function(n, mean, sd) {
rnorm(n, mean, sd)
}
Vectorización instantánea
mapply(noise, 1:5, 1:5, 2)
## [[1]]
## [1] 1.849743
##
## [[2]]
## [1] 2.399712 4.371152
##
## [[3]]
## [1] 4.999238 5.639152 1.006731
##
## [[4]]
## [1] 6.835012 4.930839 3.930951 3.894547
##
## [[5]]
## [1] 4.861750 5.494002 5.516326 4.588543 7.085203
Lo cual es lo mismo que:
list(noise(1, 1, 2), noise(2, 2, 2), noise(3, 3, 2), noise(4, 4, 2), noise(5, 5, 2))
## [[1]]
## [1] -0.5319374
##
## [[2]]
## [1] 5.017320 -2.580596
##
## [[3]]
## [1] 2.426552 2.616396 2.785114
##
## [[4]]
## [1] 3.581864 6.604843 6.517391 3.691458
##
## [[5]]
## [1] 6.797958 8.984205 3.492458 4.071135 3.837592
split
split toma un vector u otros objetos y lo divide en grupos determinados por un factor o una lista de factores.
str(split)
## function (x, f, drop = FALSE, ...)
X es un vector (o lista) o un marco de datos F es un factor (o coaccionado a uno) o una lista de factores Drop indica si los niveles de factores vacíos deben ser eliminados
x <- c(rnorm(10), runif(10), rnorm(10, 1))
f <- gl(3, 10)
split(x, f)
## $`1`
## [1] 0.18546082 0.70710539 -0.40715155 -1.07120272 0.22565579
## [6] 0.09808071 0.28057701 -0.25702616 -0.57604646 1.28589004
##
## $`2`
## [1] 0.8887993 0.9725940 0.3833292 0.1011196 0.2321548 0.3389057 0.9597877
## [8] 0.9047762 0.8589763 0.6351879
##
## $`3`
## [1] 0.2020942 0.8242144 0.8620720 2.4277311 -0.9836047 1.2817231
## [7] 1.7216647 2.8483862 -0.2665849 1.6397124
Una función común se divide seguido de un lapply.
lapply(split(x, f), mean)
## $`1`
## [1] 0.04713429
##
## $`2`
## [1] 0.6275631
##
## $`3`
## [1] 1.055741
División de un data frame
library(datasets)
head(airquality)
## Ozone Solar.R Wind Temp Month Day
## 1 41 190 7.4 67 5 1
## 2 36 118 8.0 72 5 2
## 3 12 149 12.6 74 5 3
## 4 18 313 11.5 62 5 4
## 5 NA NA 14.3 56 5 5
## 6 28 NA 14.9 66 5 6
s <- split(airquality, airquality$Month)
lapply(s, function(x) colMeans(x[, c("Ozone", "Solar.R", "Wind")]))
## $`5`
## Ozone Solar.R Wind
## NA NA 11.62258
##
## $`6`
## Ozone Solar.R Wind
## NA 190.16667 10.26667
##
## $`7`
## Ozone Solar.R Wind
## NA 216.483871 8.941935
##
## $`8`
## Ozone Solar.R Wind
## NA NA 8.793548
##
## $`9`
## Ozone Solar.R Wind
## NA 167.4333 10.1800
sapply(s, function(x) colMeans(x[, c("Ozone", "Solar.R", "Wind")]))
## 5 6 7 8 9
## Ozone NA NA NA NA NA
## Solar.R NA 190.16667 216.483871 NA 167.4333
## Wind 11.62258 10.26667 8.941935 8.793548 10.1800
División en más de un nivel
x <- rnorm(10)
f1 <- gl(2, 5)
f2 <- gl(5, 2)
f1
## [1] 1 1 1 1 1 2 2 2 2 2
## Levels: 1 2
Interacciones pueden crear niveles vacios:
str(split(x, list(f1, f2)))
## List of 10
## $ 1.1: num [1:2] 0.0735 0.0123
## $ 2.1: num(0)
## $ 1.2: num [1:2] 1.508 -0.774
## $ 2.2: num(0)
## $ 1.3: num -0.848
## $ 2.3: num -0.671
## $ 1.4: num(0)
## $ 2.4: num [1:2] 0.782 0.765
## $ 1.5: num(0)
## $ 2.5: num [1:2] -1.18 -0.383
Se pueden eliminar niveles vacíos:
str(split(x, list(f1, f2), drop = TRUE))
## List of 6
## $ 1.1: num [1:2] 0.0735 0.0123
## $ 1.2: num [1:2] 1.508 -0.774
## $ 1.3: num -0.848
## $ 2.3: num -0.671
## $ 2.4: num [1:2] 0.782 0.765
## $ 2.5: num [1:2] -1.18 -0.383