En posts anteriores hemos hablado de Tidyverse, la colección de paquetes por excelencia para análisis de datos en R. Dplyr es un paquete orientado a la manipulación de conjuntos de datos que forma parte de Tidyverse. Las transformaciones que se realizan con este paquete se pueden hacer también con R base sin necesidad de ningún complemento, pero la gramática de Dplyr es más eficiente y fácil de aprender y recordar. Sus funciones se resumen en una serie de verbos clave:
- filter para filtrar observaciones.
- arrange para ordenar observaciones.
- select para seleccionar variables.
- mutate para crear nuevas variables.
- summarise para calcular estadísticos de variables.
- group_by para agrupar por una variable y después operar, visualizar, etc.
Filter
Ya lo hemos utilizado Filter previamente. Como hemos comentado, sirve para filtrar casos u observaciones. En el caso de la encuesta del CIS, cada caso es un entrevistado. Habría que utilizar esta función si, por ejemplo, quisiéramos quedarnos solo con los que valoran a Pedro Sánchez con un 5 o menos.
sanchezaprobado <- dataset %>%
filter(P3406<=5)
## # A tibble: 3,102 x 309
De esta forma hemos creado un nuevo dataset llamado sanchezaprobado, que contiene solo a los 3102 encuestados que en la P3406 han valorado a Sánchez con un 5 o menos. El total de encuestados era de 5943, por lo que podemos ver cómo el tamaño se ha reducido en más de 2800 personas, que son las que no cumplen el criterio establecido. En este chunk se utiliza el símbolo %>%. Se trata de una pipe, que es un operador que sirve para concatenar operaciones. En el código se observa que hemos puesto el dataset en la primera línea de código, de modo que a partir de ahí R interpreta que todas las operaciones siguientes se hacen sobre ese dataset.
Los operadores lógicos de filter son:
- Mayor que (>).
- Menor que (<).
- Mayor o igual que (>=).
- Menor o igual que (<=).
- Igual que (==).
- Distinto de (!=).
Con el uso de | (o) o & (y) se pueden concatenar varias condiciones en la función filter, como se muestra en el siguiente fragmento de código. En este ejemplo seleccionaríamos a aquellos que valoran con un 5 o menos a Pablo Iglesias o a Pedro Sánchez. Por tanto, aquellos que valoren bien a Sánchez y mal a Iglesias o viceversa quedarían incluidos en el conjunto de casos seleccionados. Este conjunto contiene 4259 encuestados.
dataset %>%
filter(P3406 <=5 | P3404 <= 5)
## # A tibble: 4,259 x 309Arrange
Para ordenar filas utilizaremos el comando arrange. En este caso queremos ordenar de menor a mayor por satisfacción con el funcionamiento de la democracia.
dataset %>%
arrange(P3)
## # A tibble: 5,943 x 3
## ESTU CUES P3
## <dbl> <dbl> <dbl>
## 1 3248 549 0
## 2 3248 568 0
## 3 3248 595 0
## 4 3248 599 0
## 5 3248 609 0
## 6 3248 612 0
## 7 3248 1893 0
## 8 3248 2614 0
## 9 3248 2625 0
## 10 3248 2626 0
## # ... with 5,933 more rowsPor el contrario, para ordenar de mayor a menor satisfacción con el funcionamiento de la democracia hay que usar el comando desc().
dataset %>%
arrange(desc(P3))
## # A tibble: 5,943 x 3
## ESTU CUES P3
## <dbl> <dbl> <dbl>
## 1 3248 2781 99
## 2 3248 2794 99
## 3 3248 2158 99
## 4 3248 5939 99
## 5 3248 2420 99
## 6 3248 2768 99
## 7 3248 3897 99
## 8 3248 32 99
## 9 3248 4348 99
## 10 3248 4199 99
## # ... with 5,933 more rowsSi ordenamos de forma descendente, primero nos saldrán los 98 de «n.s.» («no sabe»). Este problema se puede solventar gracias a las pipes, que permiten combinar funciones de Tidyverse como filter y arrange. De esta manera, primero cribaremos los «no sabe» para después ordenar la variable.
dataset %>%
filter(P3 != 98, P3 != 99) %>%
arrange(desc(P3))
## # A tibble: 5,764 x 3
## ESTU CUES P3
## <dbl> <dbl> <dbl>
## 1 3248 560 10
## 2 3248 575 10
## 3 3248 607 10
## 4 3248 1862 10
## 5 3248 1882 10
## 6 3248 1887 10
## 7 3248 1906 10
## 8 3248 2696 10
## 9 3248 4927 10
## 10 3248 2552 10
## # ... with 5,754 more rowsTambién se pueden encadenar varios arrange. En el siguiente caso ordenaremos primero de menor a mayor la P3 (satisfacción con la democracia) y después de mayor a menor por P4 (opinión sobre la democracia). En caso de que la P3 sea igual, las filas se ordenarán de mayor a menor por la P4.
dataset %>%
filter(P3 != 98, P3 != 99, P4 != 8, P4 != 9) %>%
arrange(P3, desc(P4))
## # A tibble: 5,561 x 4
## ESTU CUES P3 P4
## <dbl> <dbl> <dbl> <dbl>
## 1 3248 1893 0 3
## 2 3248 2697 0 3
## 3 3248 4214 0 3
## 4 3248 4218 0 3
## 5 3248 4225 0 3
## 6 3248 5709 0 3
## 7 3248 4990 0 3
## 8 3248 5034 0 3
## 9 3248 5082 0 3
## 10 3248 5083 0 3
## # ... with 5,551 more rowsSelect
Hasta ahora hemos trabajado con las 309 variables del dataset completo y tarda más en computar, por lo que la programación es menos eficiente. La función select nos va a permitir quedarnos solo con las variables de nuestro interés. Por ejemplo, si sólo quisiéramos obtener la variable «CUES», que es el identificador del cuestionario, tendríamos que ejecutar lo siguiente:
dataset %>%
select(CUES) %>%
head()
## # A tibble: 6 x 1
## CUES
## <dbl>
## 1 519
## 2 520
## 3 521
## 4 522
## 5 523
## 6 524Si quisiéramos quedarnos sólo con las variables relativas al desarrollo de la entrevista, que vienen ordenadas al final, no es necesario escribirlas todas en el paréntesis del comando select. Bastaría con poner la primera y la última con dos puntos entre ellas.
dataset %>%
select(P6001:P6102) %>%
head()
## # A tibble: 6 x 7
## P6001 P6002 P6003 P6004 P6005 P6101 P6102
## <dbl> <dbl> <dbl> <dbl> <dbl> <chr> <chr>
## 1 1 NA NA NA NA - -
## 2 NA NA NA NA 1 - -
## 3 NA NA NA NA NA - -
## 4 NA NA NA 1 NA - -
## 5 NA NA NA NA 1 51 53
## 6 NA NA NA 1 NA - -Y para elegir todas las variables, menos las relativas al desarrollo de la entrevista, bastaría con poner un símbolo negativo (-).
dataset %>%
select(-(P6001:P6102)) %>%
head()
## # A tibble: 6 x 302
## ESTU CUES CCAA PROV MUN TAMUNI CAPITAL DISTR SECCION ENTREV P0
## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 3248 519 11 6 15 5 2 0 0 0 1
## 2 3248 520 11 6 15 5 2 0 0 0 1
## 3 3248 521 11 6 15 5 2 0 0 0 1
## 4 3248 522 11 6 15 5 2 0 0 0 1
## 5 3248 523 11 6 15 5 2 0 0 0 1
## 6 3248 524 11 6 15 5 2 0 0 0 1
## # ... with 291 more variablesOtra posibilidad es quedarnos sólo con las variables que empiezan por P. Para seleccionar las que acaban bajo el criterio que establezcamos, el comando a usar sería ends_with. A los comandos ya mencionados se les suman otros como contains, matches o num_range.
dataset %>%
select(starts_with("P")) %>%
head()
## # A tibble: 6 x 272
## PROV P0 P1 P2 P3 P4 P5 P6 P7 P8 P901 P902
## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 6 1 1 1 1 1 4 4 3 1 2 1
## 2 6 1 2 2 5 1 3 3 3 1 2 2
## 3 6 1 1 1 5 1 4 4 4 2 2 2
## 4 6 1 2 2 8 1 2 3 2 1 2 1
## 5 6 1 3 2 5 1 3 3 4 1 2 2
## 6 6 1 1 2 1 1 4 4 5 2 2 2
## # ... with 260 more variablesUna función muy similar a select es rename. Como su propio nombre indica, permite cambiar el nombre de las variables para hacerlas más manejables.
dataset %>%
dplyr::rename(interespolitica = P1, interescampaña = P2, satisfacciondemocracia = P3)
Los dos últimos comandos se pueden combinar, de modo que se puede seleccionar y renombrar a la vez.
dataset %>%
select(interespolitica = P1, interescampaña = P2, satisfacciondemocracia = P3)
## # A tibble: 5,943 x 3
## interespolitica interescampaña satisfacciondemocracia
## <dbl> <dbl> <dbl>
## 1 1 1 1
## 2 2 2 5
## 3 1 1 5
## 4 2 2 8
## 5 3 2 5
## 6 1 2 1
## 7 4 3 5
## 8 3 4 2
## 9 3 3 4
## 10 2 2 9
## # ... with 5,933 more rowsMutate
El comando mutate sirve para calcular nuevas variables. Este comando resultaría útil si quisiéramos, por ejemplo, calcular la distancia percibida entre PP y PSOE por los encuestados. Antes de operar con mutate hemos enviado a perdidos todos los 98 y 99 de las variables implicadas en los próximos ejemplos («no sabe/no contesta»). También incorporamos select con esas variables implicadas para agilizar la computación y facilitar la visualización de los resultados de usar mutate.
dataset$P3301[dataset$P3301 == 98] <- NA
dataset$P3301[dataset$P3301 == 99] <- NA
dataset$P3302[dataset$P3302 == 98] <- NA
dataset$P3302[dataset$P3302 == 99] <- NA
dataset$P3302[dataset$P3303 == 98] <- NA
dataset$P3302[dataset$P3303 == 99] <- NA
dataset %>%
select(P3301, P3302) %>%
mutate(distpppsoe = P3302 - P3301)
## # A tibble: 5,943 x 3
## P3301 P3302 distpppsoe
## <dbl> <dbl> <dbl>
## 1 5 7 2
## 2 3 8 5
## 3 4 6 2
## 4 2 9 7
## 5 3 8 5
## 6 2 9 7
## 7 3 8 5
## 8 4 8 4
## 9 4 7 3
## 10 2 8 6
## # ... with 5,933 more rowsEsto da como resultado una nueva columna donde se calcula la distancia que considera cada entrevistado entre el PP y el PSOE. Por ejemplo, el entrevistado 1 considera que hay una distancia de 2, puesto que sitúa al PP en el 7 y al PSOE en el 5.
También se puede añadir a lo anterior el cálculo de una segunda y una tercera variable, como la distancia percibida entre PSOE y Ciudadanos y entre PP y Ciudadanos. Con estas variables se puede operar dentro de la misma secuencia de código que las crea, sin necesidad de empezar una nueva.
dataset %>%
select(P3301, P3302, P3303) %>%
mutate(distpppsoe = P3302 - P3301, distpsoecs = P3301 - P3303, distppcs = P3302 - P3303)
## # A tibble: 5,943 x 6
## P3301 P3302 P3303 distpppsoe distpsoecs distppcs
## <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 5 7 7 2 -2 0
## 2 3 8 7 5 -4 1
## 3 4 6 5 2 -1 1
## 4 2 9 7 7 -5 2
## 5 3 8 7 5 -4 1
## 6 2 9 7 7 -5 2
## 7 3 8 6 5 -3 2
## 8 4 8 6 4 -2 2
## 9 4 7 6 3 -2 1
## 10 2 8 6 6 -4 2
## # ... with 5,933 more rowsEl entrevistado 1, que percibía una distancia entre PP y PSOE de 2, considera que el PSOE está otros 2 puntos a la izquierda respecto a Ciudadanos y que tanto Ciudadanos como el PP están en la posición 7 de la escala, por lo que la diferencia es 0.
Para estas nuevas variables también se pueden calcular estadísticos como la media. Para ello es importante excluir antes los valores perdidos (NA o not available), ya que en caso de no hacerlo, mediante el comando na.rm, la media no podrá ser calculada. Si en un cálculo hay un NA, el resultado será NA independientemente de la media de los demás valores. En el siguiente fragmento de código calculamos la distancia entre la ubicación ideológica del PSOE percibida por el entrevistado y la autoubicación media del PSOE percibida por la muestra.
dataset %>%
select(P3301) %>%
mutate(distpsoemedia = P3301 - mean(P3301, na.rm = TRUE))
## # A tibble: 5,943 x 2
## P3301 distpsoemedia
## <dbl> <dbl>
## 1 5 1.00
## 2 3 -0.997
## 3 4 0.00341
## 4 2 -2.00
## 5 3 -0.997
## 6 2 -2.00
## 7 3 -0.997
## 8 4 0.00341
## 9 4 0.00341
## 10 2 -2.00
## # ... with 5,933 more rowsMutate añade las variables calculadas al conjunto de datos existente conservando todas las variables. Sin embargo, existe una variación de este comando, llamada transmute, que crea un conjunto de datos que solo contiene las variables de nueva creación.
dataset %>%
transmute(distpppsoe = P3302 - P3301, distpsoecs = P3301 - P3303, distppcs = P3302 - P3303)
## # A tibble: 5,943 x 3
## distpppsoe distpsoecs distppcs
## <dbl> <dbl> <dbl>
## 1 2 -2 0
## 2 5 -4 1
## 3 2 -1 1
## 4 7 -5 2
## 5 5 -4 1
## 6 7 -5 2
## 7 5 -3 2
## 8 4 -2 2
## 9 3 -2 1
## 10 6 -4 2
## # ... with 5,933 more rowsSummarise
El último comando de dplyr que vamos a ver es summarise, que resume variables del dataframe en un solo estadístico. Permite, por ejemplo, calcular la media de autoubicación ideológica de los encuestados.
dataset %>%
summarise(mean(P32))
## mean(P32)
## 1 18.4279Sin embargo, el dato que hemos obtenido con el código anterior está falseado por los 98 y 99 correspondientes al «no sabe» y al «no contesta» (es evidente que si la escala de autoubicación ideológica va del 1 al 10, no se puede obtener una media de 18.42). Para paliar este defecto hay que recodificar los «no sabe» y «no contesta» con na_if de mutate. Este comando es especialmente útil cuando tratamos datos de encuesta, donde es frecuente tener valores perdidos. Con el siguiente código enviamos a perdidos los 98 y 99 y repetimos el cálculo anterior para obtener la media real de la muestra excluyendo los perdidos. En esta ocasión la media es 4.52, cifra mucho más verosímil.
dataset %>%
select(P32) %>%
mutate(P32 = na_if(P32, 98)) %>%
mutate(P32 = na_if(P32, 99)) %>%
summarise(mediaubicacion = mean(P32, na.rm = TRUE))
## mediaubicacion
## 1 4.522615Por último, con group_by podemos crear categorías en función de una variable, por ejemplo la religión, y tener en cuenta esos grupos para calcular estadísticos, como por ejemplo la autoubicación ideológica media de cada grupo religioso. Este comando permite segmentar la muestra y acceder a estadísticos desagregados. Previamente hemos definido las etiquetas de cada código con levels.
dataset$P48 <- as_factor(dataset$P48)
levels(dataset$P48) <- c("Católico practicante", "Católico no practicante", "Creyente de otra religión", "Agnóstico", "Indiferente, no creyente", "Ateo", "N.C.")
dataset %>%
select(P32, P48) %>%
mutate(P32 = na_if(P32, 98)) %>%
mutate(P32 = na_if(P32, 99)) %>%
mutate(P48 = na_if(P48, 9)) %>%
group_by(P48) %>%
dplyr::summarise(mediaubicacion = mean(P32, na.rm = TRUE))
## # A tibble: 7 x 2
## P48 mediaubicacion
## <fct> <dbl>
## 1 Católico practicante 5.77
## 2 Católico no practicante 4.62
## 3 Creyente de otra religión 4.56
## 4 Agnóstico 3.49
## 5 Indiferente, no creyente 3.84
## 6 Ateo 3.06
## 7 N.C. 3.62Los resultados obtenidos indican que el grupo religioso situado más a la derecha en la escala son los católicos practicantes (con una ubicación ideológica media de 5.77), mientras que los ateos son los que están más a la izquierda (3.06). Con estos seis comandos de dplyr ya nos hacemos una idea bastante clara de la utilidad del paquete y de las tareas para las que se puede emplear. Además, su uso en conjunto con otros paquetes del Tidyverse potencia las posibilidades de los mismos. Por ejemplo, podemos hacer gráficos de ggplot2 habiendo filtrado antes los casos perdidos filter y calculado nuevas variables con mutate.
