TodЛs somos políticЛs. TodЛs hacemos política.

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 309

Arrange

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 rows

Por 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 rows

Si 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 rows

Tambié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 rows

Select

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   524

Si 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 variables

Otra 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 variables

Una 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 rows

Mutate

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 rows

Esto 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 rows

El 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 rows

Mutate 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 rows

Summarise

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.4279

Sin 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.522615

Por ú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.62

Los 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.