Al momento de realizar algún proyecto vas a necesitar transformar los
datos para obtener la forma que deseas para trabajar. dplyr (que es de
tidyverse) es uno de los paquetes que está a la altura de todo. Algunos
de sus comandos son reconocidos como lo son mutate ,
summarize, select, entre otros. Muchas veces
nos va a tener que tocar crear nuevas variables. Por ejemplo, yo como
investigador me tocó en esta investigación utilizar datos del Banco
Mundial sobre desigualdad del ingreso, indicadores institucionales
ingresos del turismo para testear una hipótesis acerca de que la mejora
conjunta de los mecanismos de participación y de inclusión política de
los países de latinoamérica y de los ingresos del turismo tenía un
efecto negativo en la desigualdad. (Mella Gómez,
2022). Algunas de las variables tenían una distribución de colas
gordas y decidí aplicar el logaritmo natural, creando un modelo de
regresión con una forma log-log1, aunque este paper todos los análisis que
hice fueron en Stata, la lógica es la misma: uno requiere transformar y
crear nuevas variables y tidyverse o más concretamente
dplyr es la herramienta ideal. Ahora veremos cómo funciona
y qué elementos nos permite hacer tidyverse.
La filosofía detrás de dplyr está contenida en la librería tidyverse, la cual contiene los siguientes paquetes: ggplot2, tidyr, dplyr, readr, purr, tibble, stringr y forcats. La forma de instalarla es la siguiente:
install.package("tidyverse")
La librería se carga así:
library(tidyverse)
Es un operador creado por Stephan Mill en el paquete magister. La librería tidyverse puede utilizarse con este operador tubería o pipes con el fin de concadenar mejor el código. Ejemplo:
data(iris)
library(tidyverse)
iris %>%
filter(Species=="versicolor")%>%
select(Species,Sepal.Length) %>%
head()
## Species Sepal.Length
## 1 versicolor 7.0
## 2 versicolor 6.4
## 3 versicolor 6.9
## 4 versicolor 5.5
## 5 versicolor 6.5
## 6 versicolor 5.7
Dentro de las funciones más utilizadas en la librería podemos mencionar:
select(): permite seleccionar columnas.
filter(): filtra las observaciones.
mutate() : Crea nuevas variables.
group_by() : Agrupa por columnas.
summarise() : Operaciones por columnas.
arrage(): Ordena las observaciones.
Para ello hay que cargar la librería:
library(dplyr)
El comando select nos permite seleccionar o aislar un conjunto de vectores o variables de un data frame que a nosotros nos interesa para el análisis. Esto es útil cuando tienes bases de datos de muestras complejas que poseen cientos y hasta miles de variables. Un ejemplo práctico:
library(dplyr)
data("iris")
select(iris, Species, Sepal.Width) %>%
head(1)
## Species Sepal.Width
## 1 setosa 3.5
select(iris, -Species) %>%
head(1)
## Sepal.Length Sepal.Width Petal.Length Petal.Width
## 1 5.1 3.5 1.4 0.2
data("storms")
storms %>%
select(-lat, -long)%>%
tail()
## # A tibble: 6 × 11
## name year month day hour status category wind pressure
## <chr> <dbl> <dbl> <int> <dbl> <fct> <dbl> <int> <int>
## 1 Wanda 2021 11 6 18 tropical storm NA 35 1002
## 2 Wanda 2021 11 7 0 tropical storm NA 35 1003
## 3 Wanda 2021 11 7 6 tropical storm NA 35 1004
## 4 Wanda 2021 11 7 12 other low NA 35 1006
## 5 Wanda 2021 11 7 18 other low NA 40 1006
## 6 Wanda 2021 11 8 0 other low NA 40 1006
## # ℹ 2 more variables: tropicalstorm_force_diameter <int>,
## # hurricane_force_diameter <int>
Es posible también usar la función everything() para
ordenar columnas, por ejemplo, ordenar en primer y segundo lugar las
variables latitud (lat) y longitud (long):
storms%>%
select(lat, long, everything())%>%
tail()
## # A tibble: 6 × 13
## lat long name year month day hour status category wind pressure
## <dbl> <dbl> <chr> <dbl> <dbl> <int> <dbl> <fct> <dbl> <int> <int>
## 1 37.1 -38 Wanda 2021 11 6 18 tropical st… NA 35 1002
## 2 37.4 -37.4 Wanda 2021 11 7 0 tropical st… NA 35 1003
## 3 38.1 -36.4 Wanda 2021 11 7 6 tropical st… NA 35 1004
## 4 39.2 -34.9 Wanda 2021 11 7 12 other low NA 35 1006
## 5 40.9 -32.8 Wanda 2021 11 7 18 other low NA 40 1006
## 6 43.2 -29.7 Wanda 2021 11 8 0 other low NA 40 1006
## # ℹ 2 more variables: tropicalstorm_force_diameter <int>,
## # hurricane_force_diameter <int>
El paquete dplyr permite la recolección de datos partiendo de algún
criterio lógico pre-establecido. Las funciones más comunes para este
tipo de tareas es starts_with() y ends_with(),
la cual permite selecionar variables o columnas de un data frame que
comiencen o terminen con alguna característica respectivamente:
#Selecccionando una columna que comience con algún criterio:
storms %>%
select(starts_with("l")) %>%
head()
## # A tibble: 6 × 2
## lat long
## <dbl> <dbl>
## 1 27.5 -79
## 2 28.5 -79
## 3 29.5 -79
## 4 30.5 -79
## 5 31.5 -78.8
## 6 32.4 -78.7
También podemos seleccionar si lsa columnas terminan con:
#Seleccionando variables que terminan con X criterio:
storms %>%
select(ends_with("er")) %>%
tail()
## # A tibble: 6 × 2
## tropicalstorm_force_diameter hurricane_force_diameter
## <int> <int>
## 1 100 0
## 2 60 0
## 3 60 0
## 4 90 0
## 5 90 0
## 6 70 0
O si las columnas del df contienen un elemento X usando la función
contains():
storms %>%
select(contains("on")) %>%
tail()
## # A tibble: 6 × 2
## month long
## <dbl> <dbl>
## 1 11 -38
## 2 11 -37.4
## 3 11 -36.4
## 4 11 -34.9
## 5 11 -32.8
## 6 11 -29.7
O seleccionar por una condición:
storms %>%
select_if(is.numeric) %>%
glimpse()
## Rows: 19,066
## Columns: 11
## $ year <dbl> 1975, 1975, 1975, 1975, 1975, 1975, 1975,…
## $ month <dbl> 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,…
## $ day <int> 27, 27, 27, 27, 28, 28, 28, 28, 29, 29, 2…
## $ hour <dbl> 0, 6, 12, 18, 0, 6, 12, 18, 0, 6, 12, 18,…
## $ lat <dbl> 27.5, 28.5, 29.5, 30.5, 31.5, 32.4, 33.3,…
## $ long <dbl> -79.0, -79.0, -79.0, -79.0, -78.8, -78.7,…
## $ category <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ wind <int> 25, 25, 25, 25, 25, 25, 25, 30, 35, 40, 4…
## $ pressure <int> 1013, 1013, 1013, 1013, 1012, 1012, 1011,…
## $ tropicalstorm_force_diameter <int> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ hurricane_force_diameter <int> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
#O si la variable es factor:
storms %>%
select_if(is.factor) %>%
glimpse()
## Rows: 19,066
## Columns: 1
## $ status <fct> tropical depression, tropical depression, tropical depression, …
El conjunto de datos mencionado anteriormente es de 100,000 observaciones que incluye una serie de variables:
movield
titule
geners
userId
rating
timestamp
Intentemos leer estos datos:
library(readr)
movies<-read.csv("https://www.maximacampus.es/contenido/miscelanea/movies.csv", as.is = TRUE)
Ahora convertimos los datos en formato tibble:
Para seleccionar un data frame con las variables MovieID y Rating debemos de hacer:
id_rank<-movies %>%
select(movieId, rating)
head(id_rank)
## movieId rating
## 1 1 4.0
## 2 1 4.0
## 3 1 3.5
## 4 1 4.0
## 5 1 4.0
## 6 1 4.0
El comando filter() nos permite seleccionar
observaciones con un criterio previamente establecido. Los argumentos en
la función son:
Para seleccionar hacemos lo siguiente:
iris %>%
filter(Species== "setosa", Sepal.Length >=4) %>%
head(5)
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1 5.1 3.5 1.4 0.2 setosa
## 2 4.9 3.0 1.4 0.2 setosa
## 3 4.7 3.2 1.3 0.2 setosa
## 4 4.6 3.1 1.5 0.2 setosa
## 5 5.0 3.6 1.4 0.2 setosa
Los operadores lógicos son importantes para generar el filtrado. Los que se pueden usar con la función filter son:
< (Menor que)
> (Mayor que)
== (Equivale a.
<= Menor o igual.
>= Mayor o igual.
!= No es igual a.
Otros más a destacar pero no necesariamente relacionado a lo numérico:
%in% (Membresía de grupo).
is.na (Es valor perdido).
!is.na (no es valor perdido).
También están los operadores booleanos como
&,|, !, xor, any, all.
Tip importante: Es importante asegurarse en algunos casos si los datos están o no agrupados.
Seleccionar una variable categórica:
storms %>%
select(name, category, status, wind) %>%
filter(name== "Caroline") %>%
head()
## # A tibble: 6 × 4
## name category status wind
## <chr> <dbl> <fct> <int>
## 1 Caroline NA tropical depression 25
## 2 Caroline NA tropical depression 25
## 3 Caroline NA tropical depression 25
## 4 Caroline NA tropical depression 25
## 5 Caroline NA tropical depression 25
## 6 Caroline NA tropical depression 25
Otra selección con dos nombres:
storms %>%
select(name, category, status, wind) %>%
filter(name %in% c("Caroline", "Amy")) %>%
str()
## tibble [64 × 4] (S3: tbl_df/tbl/data.frame)
## $ name : chr [1:64] "Amy" "Amy" "Amy" "Amy" ...
## $ category: num [1:64] NA NA NA NA NA NA NA NA NA NA ...
## $ status : Factor w/ 9 levels "disturbance",..: 7 7 7 7 7 7 7 7 8 8 ...
## $ wind : int [1:64] 25 25 25 25 25 25 25 30 35 40 ...
También podemos seleccionar por una variable numérica:
storms %>%
select(category, status, wind, name) %>%
filter(wind>70) %>%
head()
## # A tibble: 6 × 4
## category status wind name
## <dbl> <fct> <int> <chr>
## 1 1 hurricane 75 Blanche
## 2 1 hurricane 75 Blanche
## 3 3 hurricane 100 Caroline
## 4 3 hurricane 100 Caroline
## 5 2 hurricane 90 Caroline
## 6 1 hurricane 75 Doris
Es posible seleccionar datos cerca de un valor usando la función
near() el argumento es el siguiente:
storms %>%
select(category, name, status, wind) %>%
filter(near(wind, 70, tol= 10)) %>%
head()
## # A tibble: 6 × 4
## category name status wind
## <dbl> <chr> <fct> <int>
## 1 1 Blanche hurricane 65
## 2 1 Blanche hurricane 70
## 3 1 Blanche hurricane 75
## 4 1 Blanche hurricane 75
## 5 1 Blanche hurricane 70
## 6 1 Caroline hurricane 65
También podemos filtrar por medio de la desviación típica:
storms %>%
select(category, name, status, wind) %>%
filter(near(wind,70, tol= sd(wind))) %>%
head()
## # A tibble: 6 × 4
## category name status wind
## <dbl> <chr> <fct> <int>
## 1 NA Amy tropical storm 45
## 2 NA Amy tropical storm 50
## 3 NA Amy tropical storm 50
## 4 NA Amy tropical storm 55
## 5 NA Amy tropical storm 60
## 6 NA Amy tropical storm 60
El parámetro between() nos permite seleccionar entre dos
valores:
storms %>%
select(wind, status, category, name) %>%
filter(between(wind, 50, 70)) %>%
head()
## # A tibble: 6 × 4
## wind status category name
## <int> <fct> <dbl> <chr>
## 1 50 tropical storm NA Amy
## 2 50 tropical storm NA Amy
## 3 55 tropical storm NA Amy
## 4 60 tropical storm NA Amy
## 5 60 tropical storm NA Amy
## 6 60 tropical storm NA Amy
Funciones como arrange() permite ordenar las
observaciones de forma ascendente o descendente, dependiendo de lo que
te interese como investigador.
Un ejemplo del argumento del comando es:
iris%>% arange(Petal.Width)%>%head()
storms %>%
select(category, name, status, lat) %>%
arrange(lat) %>%
head()
## # A tibble: 6 × 4
## category name status lat
## <dbl> <chr> <fct> <dbl>
## 1 NA Victor other low 7
## 2 NA Isidore tropical depression 7.2
## 3 NA Isidore tropical depression 7.4
## 4 NA Victor other low 7.4
## 5 NA Bret disturbance 7.5
## 6 NA Kirk tropical depression 7.7
Ahora de manera descendente:
storms %>%
select(category, name, status, lat) %>%
arrange(desc(lat)) %>%
head()
## # A tibble: 6 × 4
## category name status lat
## <dbl> <chr> <fct> <dbl>
## 1 NA Alberto extratropical 70.7
## 2 NA Alberto extratropical 69
## 3 NA Cristobal extratropical 69
## 4 NA Ophelia extratropical 68.8
## 5 NA Alberto extratropical 68
## 6 NA Cristobal extratropical 68
Esta nos permite:
Crear nuevas variables.
Modificar variables creadas.
Los argumentos son:
Ejemplo:
iris %>%
mutate(PetalW= Petal.Width/100) %>%
glimpse()
## Rows: 150
## Columns: 6
## $ Sepal.Length <dbl> 5.1, 4.9, 4.7, 4.6, 5.0, 5.4, 4.6, 5.0, 4.4, 4.9, 5.4, 4.…
## $ Sepal.Width <dbl> 3.5, 3.0, 3.2, 3.1, 3.6, 3.9, 3.4, 3.4, 2.9, 3.1, 3.7, 3.…
## $ Petal.Length <dbl> 1.4, 1.4, 1.3, 1.5, 1.4, 1.7, 1.4, 1.5, 1.4, 1.5, 1.5, 1.…
## $ Petal.Width <dbl> 0.2, 0.2, 0.2, 0.2, 0.2, 0.4, 0.3, 0.2, 0.2, 0.1, 0.2, 0.…
## $ Species <fct> setosa, setosa, setosa, setosa, setosa, setosa, setosa, s…
## $ PetalW <dbl> 0.002, 0.002, 0.002, 0.002, 0.002, 0.004, 0.003, 0.002, 0…
Con el conjunto de datos storms
#crear nuevas variables:
data("storms")
storms %>%
select(name, wind) %>%
mutate(wind_km= wind*1.852) %>%
head()
## # A tibble: 6 × 3
## name wind wind_km
## <chr> <int> <dbl>
## 1 Amy 25 46.3
## 2 Amy 25 46.3
## 3 Amy 25 46.3
## 4 Amy 25 46.3
## 5 Amy 25 46.3
## 6 Amy 25 46.3
#Aquí modificamos una variable ya creada:
storms %>%
select(name, wind) %>%
mutate(wind= wind*1.852) %>%
head()
## # A tibble: 6 × 2
## name wind
## <chr> <dbl>
## 1 Amy 46.3
## 2 Amy 46.3
## 3 Amy 46.3
## 4 Amy 46.3
## 5 Amy 46.3
## 6 Amy 46.3
storms %>%
mutate(status_ts= ifelse(status== "tropical storm", 1, 0)) %>%
glimpse()
## Rows: 19,066
## Columns: 14
## $ name <chr> "Amy", "Amy", "Amy", "Amy", "Amy", "Amy",…
## $ year <dbl> 1975, 1975, 1975, 1975, 1975, 1975, 1975,…
## $ month <dbl> 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,…
## $ day <int> 27, 27, 27, 27, 28, 28, 28, 28, 29, 29, 2…
## $ hour <dbl> 0, 6, 12, 18, 0, 6, 12, 18, 0, 6, 12, 18,…
## $ lat <dbl> 27.5, 28.5, 29.5, 30.5, 31.5, 32.4, 33.3,…
## $ long <dbl> -79.0, -79.0, -79.0, -79.0, -78.8, -78.7,…
## $ status <fct> tropical depression, tropical depression,…
## $ category <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ wind <int> 25, 25, 25, 25, 25, 25, 25, 30, 35, 40, 4…
## $ pressure <int> 1013, 1013, 1013, 1013, 1012, 1012, 1011,…
## $ tropicalstorm_force_diameter <int> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ hurricane_force_diameter <int> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ status_ts <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,…
#categorizar una variable, ejemplo, el viento:
storms_new<- storms %>%
mutate(wind_ca= case_when(wind<=40 ~"Bajo",
wind >60 & wind <=65 ~ "Medio",
wind >65 ~ "Fuerte"))
storms_new$wind_ca <-as.factor(storms_new$wind_ca)
glimpse(storms_new)
## Rows: 19,066
## Columns: 14
## $ name <chr> "Amy", "Amy", "Amy", "Amy", "Amy", "Amy",…
## $ year <dbl> 1975, 1975, 1975, 1975, 1975, 1975, 1975,…
## $ month <dbl> 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,…
## $ day <int> 27, 27, 27, 27, 28, 28, 28, 28, 29, 29, 2…
## $ hour <dbl> 0, 6, 12, 18, 0, 6, 12, 18, 0, 6, 12, 18,…
## $ lat <dbl> 27.5, 28.5, 29.5, 30.5, 31.5, 32.4, 33.3,…
## $ long <dbl> -79.0, -79.0, -79.0, -79.0, -78.8, -78.7,…
## $ status <fct> tropical depression, tropical depression,…
## $ category <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ wind <int> 25, 25, 25, 25, 25, 25, 25, 30, 35, 40, 4…
## $ pressure <int> 1013, 1013, 1013, 1013, 1012, 1012, 1011,…
## $ tropicalstorm_force_diameter <int> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ hurricane_force_diameter <int> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ wind_ca <fct> Bajo, Bajo, Bajo, Bajo, Bajo, Bajo, Bajo,…
summary(storms_new$wind_ca)
## Bajo Fuerte Medio NA's
## 9288 3825 987 4966
Estos dos comandos son útiles para hacer resumenes de estadísticos descriptivos. Los argumentos utilizados son:
El conjunto de datos a aplicar el análisis.
La variable factor por la cual agrupar.
Ejemplo:
En el ejemplo aquí con la base de datos iris calculamos
la anchura media y la desviación estándar de los sépalos por
especie.
iris %>%
group_by(Species) %>%
summarise(mean(Sepal.Width), sd(Sepal.Width))
## # A tibble: 3 × 3
## Species `mean(Sepal.Width)` `sd(Sepal.Width)`
## <fct> <dbl> <dbl>
## 1 setosa 3.43 0.379
## 2 versicolor 2.77 0.314
## 3 virginica 2.97 0.322
Al momento de estimar con datos faltantes es necesario dar cuenta a
los usuarios, al momento de realizar reportes o para fines de
replicación, que hacen falta datos. Lo que puedes hacer es si fuesemos a
calcular la media, en el ejemplo anterior, ignorando los datos faltantes
sería escribiendo mean(Sepal.Width, na.rm= TRUE) , por lo
que la media condicional se calcula solo con las observaciones
existentes y no tomando en cuenta los valores faltantes. En el caso
contrario sería usaro na.rm.=FALSE.
Ahora vamos a realizar algunos ejemplos varios con la base de datos storms: Intentemos resumir de manera adecuada los estadísticos descriptivos
storms %>%
summarise(N=n(), Max= max(wind), Prom= mean(wind), Min= min(wind), D.E= sd(wind))
## # A tibble: 1 × 5
## N Max Prom Min D.E
## <int> <int> <dbl> <int> <dbl>
## 1 19066 165 50.0 10 25.5
Con la base de datos storms vamos a resumir los vientos y lo haremos por tipo de tormenta y mes.
storms %>%
select(status,wind) %>%
group_by(status) %>%
summarise(Max= max(wind), Media= mean(wind), DE= sd(wind), Min= min(wind))
## # A tibble: 9 × 5
## status Max Media DE Min
## <fct> <int> <dbl> <dbl> <int>
## 1 disturbance 50 29.3 6.70 20
## 2 extratropical 105 41.4 13.4 10
## 3 hurricane 165 86.6 20.7 65
## 4 other low 80 25.4 6.79 10
## 5 subtropical depression 30 26.7 4.79 10
## 6 subtropical storm 60 44.5 7.95 35
## 7 tropical depression 32 27.5 3.72 10
## 8 tropical storm 70 45.7 8.29 35
## 9 tropical wave 40 28.6 4.59 20
Es también posible realizar otro tipo de agrupamientos con más de dos
variables, por ejemplo, en la base de datos Storms mediante
las variables status, wind y month
storms %>%
select(status, wind, month) %>%
group_by(status, month) %>%
summarise(N= n(), Max=max(wind), Mín=min(wind), Prom= mean(wind), DE= sd(wind))
## `summarise()` has grouped output by 'status'. You can override using the
## `.groups` argument.
## # A tibble: 75 × 7
## # Groups: status [9]
## status month N Max Mín Prom DE
## <fct> <dbl> <int> <int> <int> <dbl> <dbl>
## 1 disturbance 6 13 40 25 34.2 4.00
## 2 disturbance 7 45 45 25 30.1 5.98
## 3 disturbance 8 25 40 25 31 5
## 4 disturbance 9 41 45 20 26.1 6.85
## 5 disturbance 10 14 50 20 31.1 9.03
## 6 disturbance 11 8 30 20 24.4 4.17
## 7 extratropical 1 29 70 40 54.0 6.86
## 8 extratropical 4 40 55 30 37.6 7.07
## 9 extratropical 5 18 55 20 42.2 10.2
## 10 extratropical 6 130 55 20 35.7 8.36
## # ℹ 65 more rows
Este tipo de regresión se interpreta como un aumento porcentual de la variable X resulta en un efecto porcentual enla variable Y, es decir, se interpreta como una elasticidad. Como el cambio porcentual de la variable X resulta en un cambio porcentual en la variable Y.↩︎