R es un lenguaje de programación de código abierto y un entorno de software para la computación estadística.

El lenguaje R se utiliza ampliamente entre los estadísticos y los mineros de datos para el desarrollo de software estadístico y el análisis de datos.

Todo el código R manipula objetos. El objeto, es el concepto principal sobre el cual se fundamenta la tecnología orientada a objetos. Un objeto puede ser visto como una entidad que posee atributos y efectúa acciones. Ejemplos de objetos en R incluyen las funciones, symbols (nombre objetos) e incluso las expresiones.

Principales características de R

  • Open Source y multiplataforma

  • Alto y creciente número de “paquetes”

  • Amplia comunidad de usuarios (individuos y empresas)

  • Ciclo completo de trabajo:

    • Implementación

    • Preparación de datos

    • Análisis

    • Despliegue

    • Documentación

    • Completo IDE (RStudio)

Tipos de datos

Para el caso de vectores, matrices y array, todos los elementos deben ser del mismo tipo.

# enteros forzados con "L"
numeros <- c(1L, 2L, 5L, 65L, 78L, 2L, 12L)
typeof(numeros)
## [1] "integer"
# agregando un double '9'
numeros <- c(1L, 2L, 5L, 65L, 78L, 2L, 12L, 9)
typeof(numeros)
## [1] "double"
# agregamos un caracter
numeros <- c(1L,2L,5L,65L,78L,2L,12L, 9, "a")
typeof(numeros)
## [1] "character"
# cuantos datos hay
length(numeros)
## [1] 9
# caracteres
letras <- c("a", "b", "c")
typeof(letras)
## [1] "character"

Expresiones

Expresiones de asignación:

x <- 1
x
## [1] 1

Vector

Un vector es un arreglo de datos. En R, es el tipo básico de almacenaminto de datos. El vector puede ser numerico, caracter, y logico basado en sus elementos.

vector1 <- c(1,3,5,7,9)
vector1
## [1] 1 3 5 7 9
numbers.vec <- c(-3,-2,-1,0,1,2,3)
numbers.vec
## [1] -3 -2 -1  0  1  2  3
num2char <- as.character(numbers.vec)
num2char
## [1] "-3" "-2" "-1" "0"  "1"  "2"  "3"
num2logical <- as.logical(numbers.vec)
num2logical
## [1]  TRUE  TRUE  TRUE FALSE  TRUE  TRUE  TRUE
char.vec <- c("1","3","five","7")
char.vec
## [1] "1"    "3"    "five" "7"
# acceso al segundo elemento del "vector1"
vector1[2]
## [1] 3
# accediendo a los 3 elementos iniciado desde el segundo elemento.
vector1[2:4]
## [1] 3 5 7

Factor

Un factor es otro tipo de dato importante en R, especialmente cuando se trata de variables categóricas. En un vector R, no hay límite en el número de elementos distintos, pero en las variables factoriales, sólo se requiere un número limitado de elementos distintos.

#
factor1 <- factor(c(1,2,3,4,5,6,7,8,9))
factor1
## [1] 1 2 3 4 5 6 7 8 9
## Levels: 1 2 3 4 5 6 7 8 9

Arrays

Un arreglo es una entrada de datos de múltiples suscripciones que permite el almacenamiento de tramas de datos, matrices o vectores de diferentes tipos. Los marcos y matrices de datos son de dos dimensiones solamente, pero un arreglo puede ser de cualquier número de dimensiones.

mat.array=array(dim=c(2,2,3))
# To produce the same results over time we set a seed value
set.seed(12345)
mat.array[,,1]<-rnorm(4)
mat.array[,,2]<-rnorm(4)
mat.array[,,3]<-rnorm(4)
mat.array
## , , 1
## 
##           [,1]       [,2]
## [1,] 0.5855288 -0.1093033
## [2,] 0.7094660 -0.4534972
## 
## , , 2
## 
##            [,1]       [,2]
## [1,]  0.6058875  0.6300986
## [2,] -1.8179560 -0.2761841
## 
## , , 3
## 
##            [,1]       [,2]
## [1,] -0.2841597 -0.1162478
## [2,] -0.9193220  1.8173120

Para poder realizar operaciones matemáticas en matrices deben ser valores numéricos.

# creating a matrix with numeric elements only
# To produce the same matrix over time we set a seed value
set.seed(12345)
num.mat <- matrix(rnorm(9),nrow=3,ncol=3)
num.mat
##            [,1]       [,2]       [,3]
## [1,]  0.5855288 -0.4534972  0.6300986
## [2,]  0.7094660  0.6058875 -0.2761841
## [3,] -0.1093033 -1.8179560 -0.2841597
# matrix multiplication
t(num.mat) %*% num.mat
##           [,1]       [,2]       [,3]
## [1,] 0.8581332 0.36302951 0.20405722
## [2,] 0.3630295 3.87772320 0.06350551
## [3,] 0.2040572 0.06350551 0.55404860
resultado <- 2 * (5 + 1)
resultado
## [1] 12

list

Es un objeto que puede almacenar otros objetos de cualquier tipo.

var1 <- c(101,102,103,104,105)
var2 <- c(25,22,29,34,33)
var3 <- c("Non-Diabetic", "Diabetic", "Non-Diabetic", "Non-Diabetic",
"Diabetic")
var4 <- factor(c("male","male","female","female","male"))
diab.dat <- data.frame(var1,var2,var3,var4)
mat.array=array(dim=c(2,2,3))
set.seed(12345)
mat.array[,,1]<-rnorm(4)
mat.array[,,2]<-rnorm(4)
mat.array[,,3]<-rnorm(4)
# creating list
obj.list <- list(elem1=var1, elem2=var2, elem3=var3, elem4=var4, elem5=diab.dat, elem6=mat.array)
obj.list
## $elem1
## [1] 101 102 103 104 105
## 
## $elem2
## [1] 25 22 29 34 33
## 
## $elem3
## [1] "Non-Diabetic" "Diabetic"     "Non-Diabetic" "Non-Diabetic" "Diabetic"    
## 
## $elem4
## [1] male   male   female female male  
## Levels: female male
## 
## $elem5
##   var1 var2         var3   var4
## 1  101   25 Non-Diabetic   male
## 2  102   22     Diabetic   male
## 3  103   29 Non-Diabetic female
## 4  104   34 Non-Diabetic female
## 5  105   33     Diabetic   male
## 
## $elem6
## , , 1
## 
##           [,1]       [,2]
## [1,] 0.5855288 -0.1093033
## [2,] 0.7094660 -0.4534972
## 
## , , 2
## 
##            [,1]       [,2]
## [1,]  0.6058875  0.6300986
## [2,] -1.8179560 -0.2761841
## 
## , , 3
## 
##            [,1]       [,2]
## [1,] -0.2841597 -0.1162478
## [2,] -0.9193220  1.8173120

Acceso a elementos de la lista.

obj.list[[1]]
## [1] 101 102 103 104 105

Data frame

Un marco de datos es una disposición rectangular de filas y columnas de vectores y/o factores, como una hoja de cálculo en MS Excel.

#creating vector of different variables and then creating data frame
var1 <- c(101,102,103,104,105)
var2 <- c(25,22,29,34,33)
var3 <- c("Non-Diabetic", "Diabetic", "Non-Diabetic", "Non-Diabetic", "Diabetic")
var4 <- factor(c("male","male","female","female","male"))
# now we will create data frame using two numeric vectors one
# character vector and one factor
midata <- data.frame(var1,var2,var3,var4)
midata
##   var1 var2         var3   var4
## 1  101   25 Non-Diabetic   male
## 2  102   22     Diabetic   male
## 3  103   29 Non-Diabetic female
## 4  104   34 Non-Diabetic female
## 5  105   33     Diabetic   male

Determinar las clases de cada columna.

#class of each column before creating data frame
class(var1)
## [1] "numeric"

Para acceder a columnas individuales de un dataframe use (“$”)

midata$var1
## [1] 101 102 103 104 105
midata[["var1"]]
## [1] 101 102 103 104 105
midata[,1]
## [1] 101 102 103 104 105

Funciones

# secuencia de numeros
seq(from = 1, to = 7)
## [1] 1 2 3 4 5 6 7
# una forma abreviada de generar una secuencia de datos
seq(1, 7)
## [1] 1 2 3 4 5 6 7
print(vector)
## function (mode = "logical", length = 0L) 
## .Internal(vector(mode, length))
## <bytecode: 0x7f9992aa4f28>
## <environment: namespace:base>
str(vector)
## function (mode = "logical", length = 0L)

Crear una función personalizada

# generación de una función anónima
f <- function() {
  x <- 1
  y <- 3
  x + y
}
f()
## [1] 4
imc <- function(peso, altura) {
  peso / (altura/100)^2
}
print(imc(120, 180))
## [1] 37.03704

Comprobación de tipos

typeof muestra el tipo de dato que contiene el objeto.

vector <- c(1,2,5,65,78,2,12)
typeof(vector)
## [1] "double"
# Comprobación mediante is.*(objeto) devuelve TRUE o FALSE si cumple el tipo según la función usada.
is.logical
## function (x)  .Primitive("is.logical")
is.integer
## function (x)  .Primitive("is.integer")
is.double
## function (x)  .Primitive("is.double")
is.numeric
## function (x)  .Primitive("is.numeric")
is.character
## function (x)  .Primitive("is.character")

Coerción de tipos

Transforma un tipo de datos en otro, uso de as.*(objeto).

as.logical
## function (x, ...)  .Primitive("as.logical")
as.numeric
## function (x, ...)  .Primitive("as.double")
as.double
## function (x, ...)  .Primitive("as.double")
as.character
## function (x, ...)  .Primitive("as.character")
as.list
## function (x, ...) 
## UseMethod("as.list")
## <bytecode: 0x7f998c822630>
## <environment: namespace:base>
as.vector
## function (x, mode = "any") 
## .Internal(as.vector(x, mode))
## <bytecode: 0x7f998ea42c98>
## <environment: namespace:base>

Selecciones de datos

Vectores

vector <- c(1,3,5,6,8,9,0)
vector
## [1] 1 3 5 6 8 9 0
# posiciones 3, 5 y 7
vector[c(3,5,7)]
## [1] 5 8 0
# posiciones 2 x tres veces, 5 y 7
vector[c(2,2,2,5,7)]
## [1] 3 3 3 8 0

Matrices

matriz <- matrix(1:20, nrow = 4)
matriz
##      [,1] [,2] [,3] [,4] [,5]
## [1,]    1    5    9   13   17
## [2,]    2    6   10   14   18
## [3,]    3    7   11   15   19
## [4,]    4    8   12   16   20
matriz[1, 3]
## [1] 9
# toda la fila 1
matriz[1,] 
## [1]  1  5  9 13 17
# toda la columna 2
matriz[,2] 
## [1] 5 6 7 8
# elimina la fila 2
matriz[-2,]
##      [,1] [,2] [,3] [,4] [,5]
## [1,]    1    5    9   13   17
## [2,]    3    7   11   15   19
## [3,]    4    8   12   16   20
# elimina la columna 4
matriz[,-4] 
##      [,1] [,2] [,3] [,4]
## [1,]    1    5    9   17
## [2,]    2    6   10   18
## [3,]    3    7   11   19
## [4,]    4    8   12   20

Listas

lista <- list(1:4, "casa", list(c(4:8),8))
lista
## [[1]]
## [1] 1 2 3 4
## 
## [[2]]
## [1] "casa"
## 
## [[3]]
## [[3]][[1]]
## [1] 4 5 6 7 8
## 
## [[3]][[2]]
## [1] 8
# estructura de la lista
str(lista) 
## List of 3
##  $ : int [1:4] 1 2 3 4
##  $ : chr "casa"
##  $ :List of 2
##   ..$ : int [1:5] 4 5 6 7 8
##   ..$ : num 8
# asigna nombres a los elementos de la lista
names(lista) <- c("A", "B", "C")
lista
## $A
## [1] 1 2 3 4
## 
## $B
## [1] "casa"
## 
## $C
## $C[[1]]
## [1] 4 5 6 7 8
## 
## $C[[2]]
## [1] 8
# extrae elementos del nombre B
lista$B 
## [1] "casa"
# equivalente a lo anterior
lista[["B"]] 
## [1] "casa"
# el numero 2 de elemento 1
lista[[1]][2] 
## [1] 2

Controles iterativos

n <- 5
n
## [1] 5

Operadores iterativos

res <- seq(1,n)
res
## [1] 1 2 3 4 5
for (i in seq_len(n)) {
res[i] <- i^2
}
res
## [1]  1  4  9 16 25

Instalar paquetes

Los paquetes son la forma normal de instalar nuevas funcionalidades dentro de RStudio. Estos contienen las funciones y documentación necesaria.

El paquete consta de una librería de funciones orientadas a resolver un determinadao problema.

# desde un repositorio especifico
install.packages("tidyverse", repos = "http://cran.us.r-project.org")
## 
## The downloaded binary packages are in
##  /var/folders/n1/zsbrkfs97sd_4fdl4mnf21g00000gn/T//RtmpsDCetw/downloaded_packages
# luego de instalar un paquete se requiere activar la librería del paquete 
library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.1.0     ✔ readr     2.1.4
## ✔ forcats   1.0.0     ✔ stringr   1.5.0
## ✔ ggplot2   3.4.2     ✔ tibble    3.1.8
## ✔ lubridate 1.9.2     ✔ tidyr     1.3.0
## ✔ purrr     1.0.1     
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors

Cálculos básicos

Media aritmética

# vector de muestra
x <- c(2, 4, 3, 6, 3, 7, 5, 8, 12, 23, 24, 27)
# uso de mean
mean(x) # 10.33
## [1] 10.33333
# Equivalente a:
sum(x)/length(x) # 10.33
## [1] 10.33333
# Si hay valores nulos o ausentes presenta errores.
x <- c(2, 4, 3, 6, 3, 7, 5, 8, 12, 23, 24, 27, NA)

# Si el vector contiene algún valor NA, el resultado será NA
mean(x) # NA
## [1] NA
# Eliminar los valores NA
mean(x, na.rm = TRUE) # 10.33
## [1] 10.33333
# media aritmetica truncada
# La media aritmética truncada elimina una fracción de las observaciones de cada lado del vector antes de que se calcule la media. Para descartar valores atípicos.
mean(x, trim = 0.1, na.rm = TRUE) # 9.5
## [1] 9.5

Varianza

g <- c(2, 4, 3, 6, 3, 7, 5, 8, 12, 23, 24, 27)
# Varianza
var(g) # 82.60606
## [1] 82.60606

Desviación típica

# Desviación típica
sd(g)
## [1] 9.088788
# Equivalente a:
sqrt(var(g))
## [1] 9.088788

Moda

mode <- function(x) {
   return(as.numeric(names(which.max(table(x)))))
}

mode(g)
## [1] 3
barplot(table(g), col = c(4, rep("gray", 4)))
legend("topright", "Moda", fill = 4)

Ejercicio

exporta el siguiente dataframe a txt, csv y luego importalo a R.

df <- data.frame(x = rnorm(10), y = rnorm(10))
df
##             x          y
## 1   0.3706279 -0.6443284
## 2   0.5202165 -1.5531374
## 3  -0.7505320 -1.5977095
## 4   0.8168998  1.8050975
## 5  -0.8863575 -0.4816474
## 6  -0.3315776  0.6203798
## 7   1.1207127  0.6121235
## 8   0.2987237 -0.1623110
## 9   0.7796219  0.8118732
## 10  1.4557851  2.1968335

Missing values

missing_dat <- data.frame(v1=c(1,NA,0,1),v2=c("M","F",NA,"M"))
missing_dat
##   v1   v2
## 1  1    M
## 2 NA    F
## 3  0 <NA>
## 4  1    M
is.na(missing_dat$v1)
## [1] FALSE  TRUE FALSE FALSE
is.na(missing_dat$v2)
## [1] FALSE FALSE  TRUE FALSE
any(is.na(missing_dat))
## [1] TRUE

Manipulación básica de datos

Capturando datos

Formatos comunes:

  • Comma separated values (.csv)

  • Text file with Tab delimited

  • Microsoft Excel file (.xls or .xlsx)

  • R data object (.RData)

# Antes de correr el siguiente comando ya que no se indica una ruta absoluta (sin directorio) se necesita establecer la ruta a la carpeta donde estén los datos.
# location using setwd(). For example 
setwd("~/Documents/Clases/R-basico")
anscombe <- read.csv("data/iris.csv",skip=2)
#skip=2 indica que se salte 2 filas y por tanto los datos se inician en la tercera fila.
# import csv file that contains both numeric and character variable
# firstly using default and then using stringsAsFActors=FALSE
iris_a <- read.csv("data/iris.csv")
str(iris_a) # muestra la estructura de los datos
## 'data.frame':    150 obs. of  5 variables:
##  $ sepal_length: num  5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...
##  $ sepal_width : num  3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ...
##  $ petal_length: num  1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ...
##  $ petal_width : num  0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ...
##  $ species     : chr  "setosa" "setosa" "setosa" "setosa" ...
# Now using stringsAsFactors=FALSE
iris_b <- read.csv("data/iris.csv",stringsAsFactors=F)

Importar archivo csv separado por semicolon (“;”)

iris_semicolon <- read.csv("data/iris.csv",stringsAsFactors=FALSE,sep=";")
str(iris_semicolon)
## 'data.frame':    150 obs. of  1 variable:
##  $ sepal_length.sepal_width.petal_length.petal_width.species: chr  "5.1,3.5,1.4,0.2,setosa" "4.9,3.0,1.4,0.2,setosa" "4.7,3.2,1.3,0.2,setosa" "4.6,3.1,1.5,0.2,setosa" ...

Importar archivo csv separado por tab (“)

# anscombe_tab <- read.csv("anscombe.txt",sep="\t")
# anscombe_tab_2 <- read.table("anscombe.txt",header=TRUE)

Importar un archivo Excel

# Calling xlsx library
library(xlsx)
# importing xlsxanscombe.xlsx
ans_xlsx <- read.xlsx2("data/Libro1.xlsx",sheetIndex=1)

Escritura

# Coma como separador y punto como separador decimal
write.csv(df, "data/datos.csv")

# archivo de texto
write.table(df, "data/datos.txt")

# Punto y coma como separador y coma como separador decimal
write.csv2(df, "data/datos.csv")

Procesando fechas

# creando fechas usando la función estandar as.Date()
as.Date("1970-01-01")
## [1] "1970-01-01"
# vieno el valor interno de un objeto de tipo fecha
   as.numeric(as.Date("1970-01-01"))
## [1] 0
# viendo iun objeto de fecha.
as.Date("1970-01-02")
## [1] "1970-01-02"
as.numeric(as.Date("1970-01-02"))
## [1] 1
# creando una fecha especificando el formato
as.Date("Jan-01-1970",format="%b-%d-%Y")
## [1] NA
# uso del paquete lubridate 
library(lubridate)
# creando una fecha usando la funcion mdy() 
mdy("Jan-01-1970")
## [1] "1970-01-01"
# Creating date object using based R functionality
   date <- as.POSIXct("23-07-2013",format = "%d-%m-%Y", tz = "UTC")
# extracting month from the date object
   as.numeric(format(date, "%m"))
## [1] 7
# accediendo a la fecha y hora del sistema
   current_time <- now()
   current_time
## [1] "2023-04-23 20:25:05 -04"
# cambiar la zona a "GMT"
   current_time_gmt <- with_tz(current_time,"GMT")
   current_time_gmt
## [1] "2023-04-24 00:25:05 GMT"
# redondeando la fecha al día mas cercano
   round_date(current_time_gmt,"day")
## [1] "2023-04-24 GMT"

Subconjuntos

# creating a 10 element vector
num10 <- c(3,2,5,3,9,6,7,9,2,3)
# accessing fifth element
num10[5]
## [1] 9
# checking whether there is any value of num10 object greater
# than 6
num10 > 6
##  [1] FALSE FALSE FALSE FALSE  TRUE FALSE  TRUE  TRUE FALSE FALSE
# keeping only values greater than 6
num10[num10 > 6]
## [1] 9 7 9
# use of negative subscript removes first element "3"
num10[-1]
## [1] 2 5 3 9 6 7 9 2 3

Graficación