Tidyverse vs R base

Datos

Los datos que ocuparemos para está demostración contienen características que determinan un posible precio ($). Los datos fueron obtenidos de Link

Objetivo

Contrastar algunas funciones de R base vs Tidyverse para el manejo de datos en R.

Variables

El conjunto de datos tiene por nombre test.csv y contiene:

  • SalePrice - el precio de venta de la propiedad en dólares. Esta es la variable de destino que está tratando de predecir.

  • MSSubClass: La clase de construcción

  • MSZoning: La clasificación general de zonificación

  • LotFrontage: Pies lineales de calle conectados a la propiedad

  • LotArea: Tamaño del lote en pies cuadrados

  • Street: Tipo de acceso por carretera

  • Alley: Tipo de acceso al callejón

  • LotShape: Forma general de la propiedad.

  • LandContour: Llanura de la propiedad

  • Utilities:Tipo de utilidades disponibles

  • LotConfig: Configuración de lotes

  • LandSlope: Pendiente de la propiedad Vecindario: ubicaciones físicas dentro de los límites de la ciudad de Ames

  • Condition1: Proximidad a carretera principal o vía férrea

  • Condition2: Proximidad a la carretera principal o vía férrea (si hay una segunda presente)

  • BldgType: tipo de vivienda

  • HouseStyle: Estilo de vivienda

  • : Material general y calidad de acabado.

  • OverallCond: Calificación de condición general

  • YearBuilt: Fecha original de construcción

  • YearRemodAdd: Fecha de remodelación

  • RoofStyle: tipo de techo

  • RoofMatl: Material del techo

  • Exterior1st: Revestimiento exterior de la casa

  • Exterior2nd: Revestimiento exterior de la casa

  • MasVnrType: Tipo de chapa de mampostería

  • MoSold: Meses de edad

  • YrSold: Año vendido

  • SaleType: tipo de venta

  • SaleCondition: Condición de venta

entre otras variables.

Conjunto de datos

Comenzamos por cargar los datos

df <- read.csv("train.csv", encoding = "UTF-8", header = TRUE)
head(df, 5)
##   Id MSSubClass MSZoning LotFrontage LotArea Street Alley LotShape LandContour
## 1  1         60       RL          65    8450   Pave  <NA>      Reg         Lvl
## 2  2         20       RL          80    9600   Pave  <NA>      Reg         Lvl
## 3  3         60       RL          68   11250   Pave  <NA>      IR1         Lvl
## 4  4         70       RL          60    9550   Pave  <NA>      IR1         Lvl
## 5  5         60       RL          84   14260   Pave  <NA>      IR1         Lvl
##   Utilities LotConfig LandSlope Neighborhood Condition1 Condition2 BldgType
## 1    AllPub    Inside       Gtl      CollgCr       Norm       Norm     1Fam
## 2    AllPub       FR2       Gtl      Veenker      Feedr       Norm     1Fam
## 3    AllPub    Inside       Gtl      CollgCr       Norm       Norm     1Fam
## 4    AllPub    Corner       Gtl      Crawfor       Norm       Norm     1Fam
## 5    AllPub       FR2       Gtl      NoRidge       Norm       Norm     1Fam
##   HouseStyle OverallQual OverallCond YearBuilt YearRemodAdd RoofStyle RoofMatl
## 1     2Story           7           5      2003         2003     Gable  CompShg
## 2     1Story           6           8      1976         1976     Gable  CompShg
## 3     2Story           7           5      2001         2002     Gable  CompShg
## 4     2Story           7           5      1915         1970     Gable  CompShg
## 5     2Story           8           5      2000         2000     Gable  CompShg
##   Exterior1st Exterior2nd MasVnrType MasVnrArea ExterQual ExterCond Foundation
## 1     VinylSd     VinylSd    BrkFace        196        Gd        TA      PConc
## 2     MetalSd     MetalSd       None          0        TA        TA     CBlock
## 3     VinylSd     VinylSd    BrkFace        162        Gd        TA      PConc
## 4     Wd Sdng     Wd Shng       None          0        TA        TA     BrkTil
## 5     VinylSd     VinylSd    BrkFace        350        Gd        TA      PConc
##   BsmtQual BsmtCond BsmtExposure BsmtFinType1 BsmtFinSF1 BsmtFinType2
## 1       Gd       TA           No          GLQ        706          Unf
## 2       Gd       TA           Gd          ALQ        978          Unf
## 3       Gd       TA           Mn          GLQ        486          Unf
## 4       TA       Gd           No          ALQ        216          Unf
## 5       Gd       TA           Av          GLQ        655          Unf
##   BsmtFinSF2 BsmtUnfSF TotalBsmtSF Heating HeatingQC CentralAir Electrical
## 1          0       150         856    GasA        Ex          Y      SBrkr
## 2          0       284        1262    GasA        Ex          Y      SBrkr
## 3          0       434         920    GasA        Ex          Y      SBrkr
## 4          0       540         756    GasA        Gd          Y      SBrkr
## 5          0       490        1145    GasA        Ex          Y      SBrkr
##   X1stFlrSF X2ndFlrSF LowQualFinSF GrLivArea BsmtFullBath BsmtHalfBath FullBath
## 1       856       854            0      1710            1            0        2
## 2      1262         0            0      1262            0            1        2
## 3       920       866            0      1786            1            0        2
## 4       961       756            0      1717            1            0        1
## 5      1145      1053            0      2198            1            0        2
##   HalfBath BedroomAbvGr KitchenAbvGr KitchenQual TotRmsAbvGrd Functional
## 1        1            3            1          Gd            8        Typ
## 2        0            3            1          TA            6        Typ
## 3        1            3            1          Gd            6        Typ
## 4        0            3            1          Gd            7        Typ
## 5        1            4            1          Gd            9        Typ
##   Fireplaces FireplaceQu GarageType GarageYrBlt GarageFinish GarageCars
## 1          0        <NA>     Attchd        2003          RFn          2
## 2          1          TA     Attchd        1976          RFn          2
## 3          1          TA     Attchd        2001          RFn          2
## 4          1          Gd     Detchd        1998          Unf          3
## 5          1          TA     Attchd        2000          RFn          3
##   GarageArea GarageQual GarageCond PavedDrive WoodDeckSF OpenPorchSF
## 1        548         TA         TA          Y          0          61
## 2        460         TA         TA          Y        298           0
## 3        608         TA         TA          Y          0          42
## 4        642         TA         TA          Y          0          35
## 5        836         TA         TA          Y        192          84
##   EnclosedPorch X3SsnPorch ScreenPorch PoolArea PoolQC Fence MiscFeature
## 1             0          0           0        0   <NA>  <NA>        <NA>
## 2             0          0           0        0   <NA>  <NA>        <NA>
## 3             0          0           0        0   <NA>  <NA>        <NA>
## 4           272          0           0        0   <NA>  <NA>        <NA>
## 5             0          0           0        0   <NA>  <NA>        <NA>
##   MiscVal MoSold YrSold SaleType SaleCondition SalePrice
## 1       0      2   2008       WD        Normal    208500
## 2       0      5   2007       WD        Normal    181500
## 3       0      9   2008       WD        Normal    223500
## 4       0      2   2006       WD       Abnorml    140000
## 5       0     12   2008       WD        Normal    250000

Filtrar datos

Regularmente, necesitamos condiciones para filtrar dataframes. Estas condiciones pueden ser expresiones lógicas construidas mediante los operadores relacionales y lógicos.

Hay varias funciones que nos permiten filtrar dataframes y son (las cuales se explicarán en las secciones siguientes):

  1. Función corchete.

  2. Función subset.

  3. Función sample.

  4. Función filter de la base de R.

  5. Función filter del paquete dplyr.

La función corchete

Una opción es ejecutando datosCompleto[i,j], donde i y j son las filas y columnas que se va a utilizar o quitar, respectivamente.

Si escribimos datosCompleto[ , j] (sin información para la fila i), indicaremos que queremos construir un dataframe que tenga en cuenta todas las filas (observaciones), pero solo la columna (variable) j.

Si escribimos datosCompleto[i, ] (sin información para la columna j), indicaremos que queremos construir un dataframe que tenga en cuenta solo la fila (observación) i, pero con todas las columnas (variables).

Las expresiones -i, -j (con el signo menos), indicarán quitar la fila i y/o la columna j.

Lo anterior también es válidos para vectores.

Ejemplo 1

Supongamos que solo necesito un dataframe que contenga solo las observaciones de 1 a 4, con las columnas 2 a 5. Para ello, podemos utilizar la función corchete [] y la función dos puntos :.

# A) Un nuevo data frame: 
Muestra1 <- df[1:4, 2:5]  
Muestra1
##   MSSubClass MSZoning LotFrontage LotArea
## 1         60       RL          65    8450
## 2         20       RL          80    9600
## 3         60       RL          68   11250
## 4         70       RL          60    9550
Ejemplo 2
Muestra1[3, 2]     # A) Solo la fila 3 y la columna 2
Muestra1[, 2]      # B) Todas las filas (por el espacio en blanco) y solo la columna 2
Muestra1[3, ]      # C) Solo la fila 3 y todas las columnas (por el espacio en blanco)
Muestra1[-5, ]     # D) Quitar la fila 5 (por eso el signo menos) y dejar todas las columnas
Muestra1[,-2]      # E) Todas las filas, pero sin la columna 2 (por eso, el signo menos)
Muestra1[, 2:5]    # F) Todas las filas, pero solo columnas de 2 a 5 (por eso, dos puntos)
Muestra1[, c(2,5)] # G) Todas las filas, pero solo columnas 2 y (*c* representa un vector)
Muestra1[1:4, 2:5]      # H) Solo las filas de 1 a 4, con las columnas 2 a 5 
Muestra1[1:4, c(2,5)]   # I) Solo las filas de 1 a 4, con las columnas 2 y 5 
Muestra1[c(1,5), c(2,4)]# J) Solo las filas 1 y 5, con las columnas 2 y 4 
Muestra1[1:5, -c(2,5)]  # K) Solo las filas de 1 a 5, quitando las columnas 2 y 5 
Muestra1[-3, -c(2,5)]   # L) Quitar la fila 3, y las columnas 2 y 5 

Función subset

La función subset es otra manera utilizada para seleccionar variables, observaciones y/o niveles de una variables.

Ejemplo 1

En el siguiente ejemplo construimos una nueva base de datos que contiene solo las variables ID, SalePrice y SaleType.

# A) Una nueva base de datos

Muestra2 <- subset(df, select = c(Id,SalePrice, SaleType)) 
head(Muestra2, 5)
##   Id SalePrice SaleType
## 1  1    208500       WD
## 2  2    181500       WD
## 3  3    223500       WD
## 4  4    140000       WD
## 5  5    250000       WD
Ejemplo 2

En este otro ejemplo construimos otra base de datos seleccionando todas las filas que tienen un precio mayor o igual que $20,000,00.00, pero sin las columnas ID y SaleType (por eso, el signo menos).

# B) Otra base de datos
Muestra3 <- subset(df, SalePrice >= 2000, select = -c(Id,SaleType))
Ejemplo 3

Construiremos otra base de datos seleccionando todas las filas que tienen una precio menor o igual que 20000 o mayor que 21000, pero sin las columnas Id y SaleType. Se utilizará el símbolo | para el conectivo lógico o.

# C) Otra base de datos
Muestra4 <- subset(df, SalePrice <= 20000 | SalePrice > 21000, select = -c(Id, SaleType))  

Función sample

La función sample se utiliza para tomar una muestra aleatoria de tamaño n de un conjunto de datos. El muestreo se puede hacer con reemplazo o sin reemplazo. Es importante resaltar que, cada vez que llamamos sample, se generan muestras aleatorias diferentes. Pero, si antes fijamos una semilla de R (con set.seed), con un número específico como argumento, obtendremos los mismos resultados cada vez que se ejecute el comando.

Ejemplo
# A) Numero de filas totales de nuestro dataframe
f <- nrow(df)

# B) Tamaño de la nueva muestra aleatoria.
n <- 2    

# C) Tomeremos dos numeros aleatorios del intervalo de 
#    numeros enteros [1, f] sin reemplazo
i <- sample(1:f, n, replace=FALSE)  

#D) La nueva muestra aleatoria: seleccionaremos dos filas
#   de manera aleatoria y las columnas 1 y 2 
Muestra7 <- df[i, c(1, 2)]            
Muestra7        
##      Id MSSubClass
## 471 471        120
## 986 986        190

Función filter

La función filter nos permite filtrar filas según una condición. Es muy similar a las funciones anteriores.

Ejemplo
Muestra10a <- filter(df, df$LotArea >= 200)
Muestra10b <- filter(df, df$LotArea >= 200 & df$Id < 60)
Muestra10c <- filter(df[, 2:4], df$LotArea >= 200 & df$Street == "RL") 
Muestra10c
## [1] MSSubClass  MSZoning    LotFrontage
## <0 rows> (or 0-length row.names)

Función filter de dplyr

La librería dplyr proporciona un conjunto de funciones para la manipulación y operaciones con data frames.

  1. Una de estas “funciones” es %>% (el llamado operador pipe), el cual nos permite:
  • Concatenar múltiples operaciones.

  • Escribir una secuencia de operaciones de izquierda a derecha en una única pipeline (tubería).

  1. Otra función es la función filter, el cual es la función que nos permitirá filtrar filas según una o varias condiciones (relacionales o lógicas) dadas para una o varias variables (ya sea numérica o categórica).

En general, la instrucción básica de escritura es alguna de las dos opciones (Nuevo_nombre es el nombre del nuevo data frame):

# Primera opción:
"data.frame" %>%  filter("condiciones") -> "Nuevo_nombre"   

# Segunda opción
"Nuevo_nombre" <- "data.frame" %>%  filter("condiciones")   
Ejemplo con un filtro
# Comenzamos cargando la libreria que ocuparemos
library("dplyr")

# A) La nueva base de datos. Utilizaremos un filtro
df_pave <- df %>%  filter(Street=="Pave")

# Veamos el dataframe anterior pero solo las
# columnas 1 y 6
head(df_pave[, c(1, 6)], 5)
##   Id Street
## 1  1   Pave
## 2  2   Pave
## 3  3   Pave
## 4  4   Pave
## 5  5   Pave

donde básicamente df %>% filter(Street=="Pave") se le como: del dataframea df, filtra las filas para los cuales la calle sea Pave.

Ordenar datos.

Cuando trabajemos con una matriz o un data frame en R, podemos ordenar los datos por filas o por columnas.

# Consideremos el siguiente dataframe
mi_df <- df[, c(2, 3, 4)]

head(mi_df)
##   MSSubClass MSZoning LotFrontage
## 1         60       RL          65
## 2         20       RL          80
## 3         60       RL          68
## 4         70       RL          60
## 5         60       RL          84
## 6         50       RL          85

y ordenemos por columna utlizando dos posibles caminos: R base: Supongamos que queremos ordenar el data frame por la columna LotFrontage en orden ascendente. Para ese propósito podemos escribir:

df_ordenado <- mi_df[order(mi_df$LotFrontage), ]

# Primeras filas
head(df_ordenado, 10)
##     MSSubClass MSZoning LotFrontage
## 76         180       RM          21
## 226        160       RM          21
## 228        160       RM          21
## 233        160       RM          21
## 236        160       RM          21
## 364        160       RM          21
## 431        160       RM          21
## 435        180       RM          21
## 490        180       RM          21
## 501        160       RM          21

Nótese que en caso de empate, el orden se basa en el índice de las filas.

En caso de que necesitemos ordenar el data frame por varias columnas, especificamos más columnas dentro de la función order. Esto es muy útil cuando la columna principal que estamos ordenando tiene empates.

df_ordenado <- mi_df[order(mi_df$MSSubClass, mi_df$LotFrontage), ]

# Primeras filas
head(df_ordenado)
##      MSSubClass MSZoning LotFrontage
## 848          20       RL          36
## 1177         20       RL          37
## 207          20       RL          40
## 1389         20       RL          42
## 214          20       RL          43
## 983          20       RL          43

arrange

La función arrange() se utiliza para ordenar las filas de un data frame de acuerdo a una o varias columnas/variables.

Por defecto arrange() ordena las filas por orden ascendente:

arrange(df, MSSubClass)[1:5, c(1,2)]
##   Id MSSubClass
## 1  2         20
## 2  7         20
## 3 11         20
## 4 13         20
## 5 14         20

Si las queremos ordenar de forma descendente lo haremos del siguiente modo:

arrange(df, desc(MSSubClass))[1:5, c(1, 2)]
##    Id MSSubClass
## 1  10        190
## 2  49        190
## 3  94        190
## 4 126        190
## 5 166        190

Podemos ordenar las filas según varias variables

arrange(df, SalePrice, LotArea)

Seleccionar variables

Para esté apartado generaremos un DataFrame, para esto procedemos de la siguiente manera.

# Creando Vectores.

# Primero fijamos una semilla
set.seed(5)

edad <- sample(10:30, size = 100, replace = TRUE)
sexo <- sample(c("Masculino","Femenino"), size = 100, replace = TRUE)
ingresos <- sample(1000:5000, size = 100, replace = TRUE)

# Creamos el dataframe a partir de los vectores
# anteriores
datos <- data.frame(edad, sexo, ingresos)
head(datos)
##   edad      sexo ingresos
## 1   11  Femenino     2568
## 2   20 Masculino     1396
## 3   24  Femenino     3936
## 4   20  Femenino     1184
## 5   18 Masculino     2380
## 6   30 Masculino     2879

Seleccionar usando condiciones lógicas.

Para esta parte, usaremos lo aprendido en la guía de matrices y en la guía de operaciones lógicas.

Si sólo deseamos extraer todas las observaciones que tengan como sexo a Masculino. Usamos la siguiente sintaxis.

datos[datos$sexo=="Masculino", ][1:5,]  # Para extraer todas las observaciones que son de sexo masculino. Solo elegimos las primeras 5 columnas 
##    edad      sexo ingresos
## 2    20 Masculino     1396
## 5    18 Masculino     2380
## 6    30 Masculino     2879
## 7    16 Masculino     2193
## 14   25 Masculino     1780

donde datos[datos$sexo=="Masculino", ] estamos seleccionando todas aquellas filas que cumplen con la condición dada, asimismo, estamos seleccionando todas las columnas del dataframe. Continuando

head(datos[datos$sexo=="Femenino" & datos$ingresos >= 4000, ]) # Para extraer las observaciones de sexo femenino y con ingresos mayores iguales a 4000.
##    edad     sexo ingresos
## 9    12 Femenino     4322
## 11   24 Femenino     4332
## 17   19 Femenino     4610
## 18   30 Femenino     4549
## 42   28 Femenino     4437
## 65   11 Femenino     4585

Por ejemplo, si sólo se desea seleccionar de las primeras 20 filas, a las personas que son de 24 años o más y que tienen ingresos mayores o iguales a 4000:

datos[1:20, ][datos$edad >= 24 & datos$ingresos >= 4000, ]  # Para extraer las observaciones con edad mayor igual a 24 años, pero sólo de las primeras 20 filas.
##      edad     sexo ingresos
## 11     24 Femenino     4332
## 18     30 Femenino     4549
## NA     NA     <NA>       NA
## NA.1   NA     <NA>       NA
## NA.2   NA     <NA>       NA
## NA.3   NA     <NA>       NA
## NA.4   NA     <NA>       NA
## NA.5   NA     <NA>       NA

Select

Ahora sí podemos realizar los filtros. Pero es primordial conocer su sintaxis.

  • select("data.frame", "starts_with o ends_with o contains": Donde select es el comando para filtrar, en data.frame irá el nombre del data frame en cuestión, y se podrán usar tres opciones starts_with(), ends_with() o contains() para indicar si empieza, si finaliza o contiene las características deseadas, respectivamente.

Si nos interesa solo las variables que empiezan con “e”. Usaríamos la siguiente sintaxis.

head(select(datos, starts_with("e"))) # Para extraer variables que empiecen con la letra e.
##   edad
## 1   11
## 2   20
## 3   24
## 4   20
## 5   18
## 6   30

Ahora veamos si deseamos filtrar las variables que terminan en “O”.

head(select(datos, ends_with("O")))   # Para extraer variables que terminan con la letra O.
##        sexo
## 1  Femenino
## 2 Masculino
## 3  Femenino
## 4  Femenino
## 5 Masculino
## 6 Masculino

Calcular nuevas variables

R base

Si deseamos incluir una columna nueva al data frame, usaremos el comando cbind().

Veamos un ejemplo:

# Se crea el vector casa de elementos "si" y "no". 
set.seed(6)
casa <- sample(c("si","no"), size = 100, replace = TRUE)

Una vez creado lo agregamos al data frame datos

datos <- cbind(datos, casa)  # Agregando la columna o variable casa.

Ahora generemos una nueva columna egresos:

egresos <- sample(1000:5000, size = 100, replace = TRUE)
datos <- cbind(datos,egresos) 
datos[1:5, ]
##   edad      sexo ingresos casa egresos
## 1   11  Femenino     2568   si    3681
## 2   20 Masculino     1396   no    3402
## 3   24  Femenino     3936   si    4461
## 4   20  Femenino     1184   no    1658
## 5   18 Masculino     2380   no    2660

Y veamos si sus ingresos son mayores que sus egresos

datos$salud_fin <- datos$ingresos - datos$egresos
datos[1:5, ]
##   edad      sexo ingresos casa egresos salud_fin
## 1   11  Femenino     2568   si    3681     -1113
## 2   20 Masculino     1396   no    3402     -2006
## 3   24  Femenino     3936   si    4461      -525
## 4   20  Femenino     1184   no    1658      -474
## 5   18 Masculino     2380   no    2660      -280

Agregar filas.

Si se desea agregar filas, tendremos que usar el comando rbind. Pero primero se tendrá que crear un data.frame con las filas que se desea agregar.

Primero creamos un data frame con las filas que deseamos agregar.

z <- data.frame(edad=c(20, 24),
                sexo=c("Femenino", "Femenino"),
                ingresos=c(3000, 5000),
                casa=c("si", "si"),
                egresos = c(26564, 46),
                salud_fin = c(-554, 6648))    # Creando un DF con las nuevas oservaciones.

Como se puede observar hemos tenido que crear el data frame z en donde se indica que tiene 2 filas. Una vez creado lo agregamos a nuestra base de datos con el comando rbind().

datos<-rbind(datos, z)   # Uniendo los nuevos dataframe.
tail(datos)
##     edad      sexo ingresos casa egresos salud_fin
## 97    28  Femenino     4141   si    3227       914
## 98    30 Masculino     1072   si    4172     -3100
## 99    18 Masculino     4903   no    4745       158
## 100   13 Masculino     1879   si    3451     -1572
## 101   20  Femenino     3000   si   26564      -554
## 102   24  Femenino     5000   si      46      6648

mutate()

Con la función mutate() podemos computar tranformaciones de variables en un data frame. A menudo, tendremos la necesidad de crear nuevas variables que se calculan a partir de variables existentes, mutate() nos proporciona una interfaz clara para realizar este tipo de operaciones.

Así, por ejemplo pensemos que queremos calcular el precio de las casa en pesos mexicanos. Consideremos el tipo de cambio del día de hoy 19.95

A continuación podemos crear una nueva variable precio_pesos con SalePrice y el tipo de cambio:

mutate(df, precio_pesos = SalePrice * 19.95)[1:5, c(81, 82)]

así, lo que hicimos antes fue crear una columna nueva y rellenar la información de dicha columna a partir de información que ya teníamos en nuestro dataframe

La función mutate() nos permite encadenar varias expresiones en una misma sentencia, para esto consideremos otra conversión, ahora veamos como pasar de pies a metros.

df_2 <- mutate(df, precio_pesos = SalePrice * 19.95, metros = LotArea * 0.3048)

df_2[1:5, c(82, 83)]
##   precio_pesos metros
## 1      4159575   2576
## 2      3620925   2926
## 3      4458825   3429
## 4      2793000   2911
## 5      4987500   4346

donde agregamos ahora dos columnas de manera simultánea.

Evaluar funciones para ciertos grupos. R (eg aggregate) vs group_by y summarise.

Calcular ciertas métricas u obtener valores sumarizados para ciertos grupos es uno de procedimientos más comunes, para esto procedemos usando la función:

  • Data frame aggregate(x, # Objeto de R

        by,              # Lista de variables (elementos que forman los grupos)
    
        FUN,             # Función a ser aplicada para crear el resumen estadístico
    
        ...,             # Argumentos adicionales a ser pasados a FUN
    
        simplify = TRUE, # Simplificar el resultado lo máximo posible (TRUE) o no (FALSE)
    
        drop = TRUE)     # Deshechar las combinaciones no usadas de grupos (TRUE) o no
        (FALSE).
  • Formula aggregate(formula, # Fórmula de entrada

        data,                # Lista o data frame donde se encuentran las variables
    
        FUN,                 # Función a ser aplicada para crear el resumen estadístico
    
        ...,                 # Argumentos adicionales a ser pasados a FUN
    
        subset,              # Observaciones a ser usadas (opcional)
    
        na.action = na.omit) # Cómo tratar valores NA
  • Serie de tiempo aggregate(x, # Serie temporal nfrequency = 1, # Observaciones por unidad de tiempo (submúltiplo de x)

        FUN = sum,           # Función a ser aplicada para crear el resumen estadístico
    
        ndeltat = 1,         # Fracción entre dos observaciones consecutivas
    
        ts.eps = getOption("ts.eps"), # Tolerancia para determinar si 'nfrequency' es un submúltiplo de la frecuencia de x
        ...)                 # Argumentos adicionales a ser pasados a FUN

R base

Supongamos que queremos calcular el precio medio de las casas según su condición. Para esto tengamos en cuenta que para usar la función aggregate para calcular la media por grupos en R, deberemos especificar la variable numérica en el primer argumento, la categórica (como una lista) en el segundo y la función que se aplicará (en este caso mean) en el tercero. Una alternativa es especificar una fórmula de la forma: numérica ~ categórica.

#                   variable numerica | variable categorica  
group_mean <- aggregate(df$SalePrice, list(df$SaleCondition), mean)

# Equivalente
group_mean <- aggregate(SalePrice ~ SaleCondition, data = df, mean) 

group_mean
##   SaleCondition SalePrice
## 1       Abnorml    146527
## 2       AdjLand    104125
## 3        Alloca    167377
## 4        Family    149600
## 5        Normal    175202
## 6       Partial    272292

donde calculamos el precio promedio de las casas por cada tipo.

tydiverse

Ocupando tydiverse, podemos hacer una mezcla de condiciones más interesante, por ejemplo

df %>% filter(SalePrice <= 40000) %>% group_by(SaleCondition) %>% summarise(media = mean(SalePrice))
## # A tibble: 2 x 2
##   SaleCondition media
##   <chr>         <dbl>
## 1 Abnorml       36037
## 2 Normal        39650

donde primero realizaremos un filtro para aquellos precios de las casas que son menores a 40000, después agruparemos a partir de las categorías de la columna SaleCondition y finalmente creamos una columna nueva denominada media para calcular el promedio de los precios de las casas, ya filtrados, de acuerdo a cada categoría agrupada.

Joins

Diferentes tipos de uniones

Antes de saltar a los códigos R, echemos un vistazo a los diferentes tipos de uniones que usaremos en este documento. Tendremos principalmente 4 tipos de uniones: inner, left, right, and full joins.

Estos cuatro tipos diferentes de uniones se pueden resumir de la siguiente manera:

  1. Unión interna: conserve solo los ID que están contenidos en ambos conjuntos de datos.

  2. Unión izquierda: conserva solo los ID que están contenidos en el primer conjunto de datos.

  3. Unión derecha: mantenga solo los ID que están contenidos en el segundo conjunto de datos.

  4. Unión completa: mantenga todas las identificaciones.

Ejemplo

# Creamos un dataframe
data_A <- data.frame(ID = paste0("ID_", 1:6),                   
                     x1 = 1:6,
                     x2 = letters[1:6])
data_A
##     ID x1 x2
## 1 ID_1  1  a
## 2 ID_2  2  b
## 3 ID_3  3  c
## 4 ID_4  4  d
## 5 ID_5  5  e
## 6 ID_6  6  f
# Creamos otro dataframe
data_B <- data.frame(ID = paste0("ID_", 4:9),                   
                     y1 = 104:109,
                     y2 = LETTERS[4:9])
data_B
##     ID  y1 y2
## 1 ID_4 104  D
## 2 ID_5 105  E
## 3 ID_6 106  F
## 4 ID_7 107  G
## 5 ID_8 108  H
## 6 ID_9 109  I

Fusión de datos con R base

La siguiente sintaxis explica cómo unir dos tablas de datos utilizando la funcion básica de R.

# Inner join
data_base_inner <- merge(data_A, data_B, by = "ID")             
data_base_inner
##     ID x1 x2  y1 y2
## 1 ID_4  4  d 104  D
## 2 ID_5  5  e 105  E
## 3 ID_6  6  f 106  F
# Left join
data_base_left <- merge(data_A, data_B, by = "ID", all.x = TRUE)  
data_base_left
##     ID x1 x2  y1   y2
## 1 ID_1  1  a  NA <NA>
## 2 ID_2  2  b  NA <NA>
## 3 ID_3  3  c  NA <NA>
## 4 ID_4  4  d 104    D
## 5 ID_5  5  e 105    E
## 6 ID_6  6  f 106    F
# Right join
data_base_right <- merge(data_A, data_B, by = "ID", all.y = TRUE) 
data_base_right
##     ID x1   x2  y1 y2
## 1 ID_4  4    d 104  D
## 2 ID_5  5    e 105  E
## 3 ID_6  6    f 106  F
## 4 ID_7 NA <NA> 107  G
## 5 ID_8 NA <NA> 108  H
## 6 ID_9 NA <NA> 109  I
# Full join
data_base_full <- merge(data_A, data_B, by = "ID", all = TRUE)  
data_base_full
##     ID x1   x2  y1   y2
## 1 ID_1  1    a  NA <NA>
## 2 ID_2  2    b  NA <NA>
## 3 ID_3  3    c  NA <NA>
## 4 ID_4  4    d 104    D
## 5 ID_5  5    e 105    E
## 6 ID_6  6    f 106    F
## 7 ID_7 NA <NA> 107    G
## 8 ID_8 NA <NA> 108    H
## 9 ID_9 NA <NA> 109    I

Fusión de datos con dplyr

# Inner join
data_dplyr_inner <- inner_join(data_A, data_B, by = "ID")         

# Left join
data_dplyr_left <- left_join(data_A, data_B, by = "ID")            
# Right join
data_dplyr_right <- right_join(data_A, data_B, by = "ID")        

# Full join
data_dplyr_full <- full_join(data_A, data_B, by = "ID")