Res
El objetivo de este post es exponer las principales funciones del paquete {dplyr} diseñadas para la manipulación de dataframes/tibbles. Utilizamos el dataframe ‘babynames’ del paquete babynames()
.
¿Qué es dplyr?
dplyr es un paquete compuesto por un conjunto de funciones diseñado por Hadley Wickham para la manipulación de data frames, y forma parte del conjunto de paquetes conocido como The tidyverse. En particular, como veremos a continuación, dplyr constituye en un conjunto de herramientas que facilita en gran medida la manipulación de data frames.
Las funciones del paquete {dplyr} son las siguientes:
select()
filter()
group_by()
mutate()
summarise()
arrange()
En primer lugar debemos instalar y cargar el paquete {dplyr}
library(dplyr)
Por lo general, el primer argumento de estas funciones es el dataframe utilizado, al que sigue los parámetros requeridos para realizar las operaciones. No obstante, una forma sencilla de utilizar las funciones del paquete {dplyr} es utilizando pipes (%>%), encadenando de esta forma distintas funciones en un mismo código. Para ello, se establece en primer lugar el data frame a utilizar, seguido del operador %>%
y, a continuación, la función y los parámetros necesarios. Los ejemplos utilizados en este post utilizarán pipes.
babynames
En este post utilizaremos el dataframe (tibble) babynames, incluido en el paquete llamado también {babynames}. Dicho dataframe contiene información por nombre de las personas recién nacidas en Estados Unidos para cada año desde 1880 hasta 2017 (aunque descarta los nombres de menos de seis observaciones), proporcionado por la Agencia de Seguridad Social norteamericana. El data frame se compone de 1.924.655 mill de filas y 5 columnas: year
, sex
, name
, n
y prop
, donde prop
es la proporción de personas de dicho género con el nombre indicado en el año correspondiente.
library(babynames)
library(fansi)
Por consiguiente, la estructura del data frame es:
str(babynames)
## tibble [1,924,665 x 5] (S3: tbl_df/tbl/data.frame)
## $ year: num [1:1924665] 1880 1880 1880 1880 1880 1880 1880 1880 1880 1880 ...
## $ sex : chr [1:1924665] "F" "F" "F" "F" ...
## $ name: chr [1:1924665] "Mary" "Anna" "Emma" "Elizabeth" ...
## $ n : int [1:1924665] 7065 2604 2003 1939 1746 1578 1472 1414 1320 1288 ...
## $ prop: num [1:1924665] 0.0724 0.0267 0.0205 0.0199 0.0179 ...
Donde las primeras diez observaciones de babynames
son los nombres más comunes en el primer año del periodo, es decir, 1880.
head(babynames, n=10)
## # A tibble: 10 x 5
## year sex name n prop
## <dbl> <chr> <chr> <int> <dbl>
## 1 1880 F Mary 7065 0.0724
## 2 1880 F Anna 2604 0.0267
## 3 1880 F Emma 2003 0.0205
## 4 1880 F Elizabeth 1939 0.0199
## 5 1880 F Minnie 1746 0.0179
## 6 1880 F Margaret 1578 0.0162
## 7 1880 F Ida 1472 0.0151
## 8 1880 F Alice 1414 0.0145
## 9 1880 F Bertha 1320 0.0135
## 10 1880 F Sarah 1288 0.0132
# Mary lidera el ranking en dicho año, seguido por Anna, Emma y Elizabeth. En los primeros diez puestos no encontramos nombres masculinos.
select()
Supongamos que no queremos conservar todas las columnas del data frame original. En nuestro caso particular supongamos que únicamente queremos trabajar con las columnas year
, sex
y name
. En ese caso podemos seleccionar dichas columnas de la siguiente forma:
# Seleccionando las columnas year, sex y name:
babynames %>%
select(year, sex, name)
## # A tibble: 1,924,665 x 3
## year sex name
## <dbl> <chr> <chr>
## 1 1880 F Mary
## 2 1880 F Anna
## 3 1880 F Emma
## 4 1880 F Elizabeth
## 5 1880 F Minnie
## 6 1880 F Margaret
## 7 1880 F Ida
## 8 1880 F Alice
## 9 1880 F Bertha
## 10 1880 F Sarah
## # ... with 1,924,655 more rows
Otras formas alternativas para obtener el mismo resultado sería utilizando el operador :
, que nos permite seleccionar las variables que se encuentran entre las dos columnas seleccionadas o, también, eliminando las dos últimas columnas mediante el uso de un signo negativo.
# seleccionando las columnas que se encuentran entre las columnas year y name:
babynames %>%
select(year:name)
## # A tibble: 1,924,665 x 3
## year sex name
## <dbl> <chr> <chr>
## 1 1880 F Mary
## 2 1880 F Anna
## 3 1880 F Emma
## 4 1880 F Elizabeth
## 5 1880 F Minnie
## 6 1880 F Margaret
## 7 1880 F Ida
## 8 1880 F Alice
## 9 1880 F Bertha
## 10 1880 F Sarah
## # ... with 1,924,655 more rows
# eliminando las columnas que se encuentran entre n y prop:
babynames %>%
select(-(n:prop))
## # A tibble: 1,924,665 x 3
## year sex name
## <dbl> <chr> <chr>
## 1 1880 F Mary
## 2 1880 F Anna
## 3 1880 F Emma
## 4 1880 F Elizabeth
## 5 1880 F Minnie
## 6 1880 F Margaret
## 7 1880 F Ida
## 8 1880 F Alice
## 9 1880 F Bertha
## 10 1880 F Sarah
## # ... with 1,924,655 more rows
En el caso de que fuese requerido cambiar el nombre de todas o alguna de las columnas seleccionadas se puede hacer de forma sencilla como se observa en la siguiente orden:
babynames %>%
select(year, sexo= sex, nombre = name, num = n)
## # A tibble: 1,924,665 x 4
## year sexo nombre num
## <dbl> <chr> <chr> <int>
## 1 1880 F Mary 7065
## 2 1880 F Anna 2604
## 3 1880 F Emma 2003
## 4 1880 F Elizabeth 1939
## 5 1880 F Minnie 1746
## 6 1880 F Margaret 1578
## 7 1880 F Ida 1472
## 8 1880 F Alice 1414
## 9 1880 F Bertha 1320
## 10 1880 F Sarah 1288
## # ... with 1,924,655 more rows
# Para renombrar las columnas sin necesidad de seleccionarlas podemos hacer uso de la función rename()
filter()
La función filter()
permite seleccionar un conjunto de observaciones según un parámetro determinado. Por ejemplo, supongamos que nos interesa seleccionar únicamente las observaciones correspondientes al año 2017. En dicho caso podemos escribir el siguiente código:
babynames %>%
filter(year== 2017)
## # A tibble: 32,469 x 5
## year sex name n prop
## <dbl> <chr> <chr> <int> <dbl>
## 1 2017 F Emma 19738 0.0105
## 2 2017 F Olivia 18632 0.00994
## 3 2017 F Ava 15902 0.00848
## 4 2017 F Isabella 15100 0.00805
## 5 2017 F Sophia 14831 0.00791
## 6 2017 F Mia 13437 0.00717
## 7 2017 F Charlotte 12893 0.00688
## 8 2017 F Amelia 11800 0.00629
## 9 2017 F Evelyn 10675 0.00569
## 10 2017 F Abigail 10551 0.00563
## # ... with 32,459 more rows
# En 2017 Emma sigue siendo uno de los nombres más recurrentes, ocupando el primer puesto del ranking. Por el contrario, nuevos nombres como Olivia, Ava, Sophia, etc., aparecen en el nuevo ranking. Al igual que sucedía en 1880 seguimos sin encontrar nombres masculinos en el top 10.
# Podemos seleccionar varios años con el comando %in%
babynames %>%
filter(year %in% c(1880, 1900, 1920, 1940, 1960, 1980, 2000))
## # A tibble: 86,581 x 5
## year sex name n prop
## <dbl> <chr> <chr> <int> <dbl>
## 1 1880 F Mary 7065 0.0724
## 2 1880 F Anna 2604 0.0267
## 3 1880 F Emma 2003 0.0205
## 4 1880 F Elizabeth 1939 0.0199
## 5 1880 F Minnie 1746 0.0179
## 6 1880 F Margaret 1578 0.0162
## 7 1880 F Ida 1472 0.0151
## 8 1880 F Alice 1414 0.0145
## 9 1880 F Bertha 1320 0.0135
## 10 1880 F Sarah 1288 0.0132
## # ... with 86,571 more rows
Pongamos que nos interesa seleccionar solo los nombres de sexo masculino (M), para ello indicaríamos el siguiente comando:
babynames %>%
filter(sex== "M")
## # A tibble: 786,372 x 5
## year sex name n prop
## <dbl> <chr> <chr> <int> <dbl>
## 1 1880 M John 9655 0.0815
## 2 1880 M William 9532 0.0805
## 3 1880 M James 5927 0.0501
## 4 1880 M Charles 5348 0.0452
## 5 1880 M George 5126 0.0433
## 6 1880 M Frank 3242 0.0274
## 7 1880 M Joseph 2632 0.0222
## 8 1880 M Thomas 2534 0.0214
## 9 1880 M Henry 2444 0.0206
## 10 1880 M Robert 2415 0.0204
## # ... with 786,362 more rows
# Nombres clásicos aparecen en el ranking masculino. John, William, James, Charles o George se sitúan como los nombres más populares en 1880.
En el caso de que quisiéramos seleccionar los nombres de sexo masculino para un año determinado anotaríamos el siguiente código:
babynames %>%
filter(year == 2017 & sex == "M")
## # A tibble: 14,160 x 5
## year sex name n prop
## <dbl> <chr> <chr> <int> <dbl>
## 1 2017 M Liam 18728 0.00954
## 2 2017 M Noah 18326 0.00933
## 3 2017 M William 14904 0.00759
## 4 2017 M James 14232 0.00725
## 5 2017 M Logan 13974 0.00712
## 6 2017 M Benjamin 13733 0.00699
## 7 2017 M Mason 13502 0.00688
## 8 2017 M Elijah 13268 0.00676
## 9 2017 M Oliver 13141 0.00669
## 10 2017 M Jacob 13106 0.00668
## # ... with 14,150 more rows
# Se observa un cambio significativo en las preferencias de los nombres de los recién nacidos. Liam, Noah, Logan aparecen en el ranking, aunque algunos nombres más tradicionales, como William o James, conservan todavía su atractivo.
O supongamos que nos interesa seleccionar los nombres de cualquier sexo que hayan superado los 9000 registros y determinar el año en el que esto sucedió
babynames %>%
filter(n > 9000)
## # A tibble: 6,653 x 5
## year sex name n prop
## <dbl> <chr> <chr> <int> <dbl>
## 1 1880 M John 9655 0.0815
## 2 1880 M William 9532 0.0805
## 3 1882 M John 9557 0.0783
## 4 1882 M William 9298 0.0762
## 5 1884 F Mary 9217 0.0670
## 6 1884 M John 9388 0.0765
## 7 1885 F Mary 9128 0.0643
## 8 1886 F Mary 9889 0.0643
## 9 1886 M John 9026 0.0758
## 10 1887 F Mary 9888 0.0636
## # ... with 6,643 more rows
Otra posibilidad sería, por ejemplo, filtrar el conjunto de observaciones con el objetivo de identificar el número de niños de sexo masculino que recibieron un nombre determinado para cada uno de los años del periodo. Pongamos, por ejemplo, que queremos determinar cuántos recién nacidos recibieron el nombre de Ruben (sin tilde) para cada uno de los años entre 1880 y 2017.
# Guardamos el nuevo data frame con el nombre Ruben
Ruben <- babynames %>%
filter(sex == "M" & name == "Ruben")
# el paquete knitr permite hacer tablas utilizando la función kable()
library(knitr)
knitr::kable(Ruben)
year | sex | name | n | prop |
---|---|---|---|---|
1880 | M | Ruben | 30 | 0.0002534 |
1881 | M | Ruben | 21 | 0.0001939 |
1882 | M | Ruben | 34 | 0.0002786 |
1883 | M | Ruben | 30 | 0.0002667 |
1884 | M | Ruben | 28 | 0.0002281 |
1885 | M | Ruben | 28 | 0.0002415 |
1886 | M | Ruben | 40 | 0.0003360 |
1887 | M | Ruben | 34 | 0.0003110 |
1888 | M | Ruben | 21 | 0.0001617 |
1889 | M | Ruben | 33 | 0.0002772 |
1890 | M | Ruben | 25 | 0.0002088 |
1891 | M | Ruben | 25 | 0.0002288 |
1892 | M | Ruben | 44 | 0.0003347 |
1893 | M | Ruben | 41 | 0.0003387 |
1894 | M | Ruben | 33 | 0.0002642 |
1895 | M | Ruben | 37 | 0.0002922 |
1896 | M | Ruben | 49 | 0.0003796 |
1897 | M | Ruben | 42 | 0.0003444 |
1898 | M | Ruben | 45 | 0.0003406 |
1899 | M | Ruben | 32 | 0.0002778 |
1900 | M | Ruben | 50 | 0.0003084 |
1901 | M | Ruben | 35 | 0.0003028 |
1902 | M | Ruben | 45 | 0.0003390 |
1903 | M | Ruben | 50 | 0.0003866 |
1904 | M | Ruben | 38 | 0.0002743 |
1905 | M | Ruben | 41 | 0.0002862 |
1906 | M | Ruben | 52 | 0.0003609 |
1907 | M | Ruben | 62 | 0.0003910 |
1908 | M | Ruben | 60 | 0.0003606 |
1909 | M | Ruben | 71 | 0.0004014 |
1910 | M | Ruben | 83 | 0.0003980 |
1911 | M | Ruben | 59 | 0.0002444 |
1912 | M | Ruben | 134 | 0.0002968 |
1913 | M | Ruben | 154 | 0.0002872 |
1914 | M | Ruben | 199 | 0.0002912 |
1915 | M | Ruben | 256 | 0.0002906 |
1916 | M | Ruben | 237 | 0.0002567 |
1917 | M | Ruben | 289 | 0.0003012 |
1918 | M | Ruben | 286 | 0.0002727 |
1919 | M | Ruben | 292 | 0.0002876 |
1920 | M | Ruben | 336 | 0.0003052 |
1921 | M | Ruben | 357 | 0.0003137 |
1922 | M | Ruben | 361 | 0.0003208 |
1923 | M | Ruben | 368 | 0.0003250 |
1924 | M | Ruben | 398 | 0.0003404 |
1925 | M | Ruben | 427 | 0.0003708 |
1926 | M | Ruben | 440 | 0.0003841 |
1927 | M | Ruben | 478 | 0.0004114 |
1928 | M | Ruben | 493 | 0.0004320 |
1929 | M | Ruben | 484 | 0.0004370 |
1930 | M | Ruben | 516 | 0.0004569 |
1931 | M | Ruben | 465 | 0.0004348 |
1932 | M | Ruben | 469 | 0.0004366 |
1933 | M | Ruben | 398 | 0.0003902 |
1934 | M | Ruben | 443 | 0.0004172 |
1935 | M | Ruben | 488 | 0.0004563 |
1936 | M | Ruben | 482 | 0.0004529 |
1937 | M | Ruben | 489 | 0.0004472 |
1938 | M | Ruben | 445 | 0.0003916 |
1939 | M | Ruben | 450 | 0.0003971 |
1940 | M | Ruben | 443 | 0.0003735 |
1941 | M | Ruben | 462 | 0.0003682 |
1942 | M | Ruben | 512 | 0.0003636 |
1943 | M | Ruben | 544 | 0.0003741 |
1944 | M | Ruben | 506 | 0.0003643 |
1945 | M | Ruben | 560 | 0.0004084 |
1946 | M | Ruben | 648 | 0.0003927 |
1947 | M | Ruben | 737 | 0.0003968 |
1948 | M | Ruben | 909 | 0.0005099 |
1949 | M | Ruben | 997 | 0.0005533 |
1950 | M | Ruben | 1025 | 0.0005635 |
1951 | M | Ruben | 1040 | 0.0005440 |
1952 | M | Ruben | 1098 | 0.0005562 |
1953 | M | Ruben | 1202 | 0.0006006 |
1954 | M | Ruben | 1259 | 0.0006087 |
1955 | M | Ruben | 1290 | 0.0006173 |
1956 | M | Ruben | 1366 | 0.0006370 |
1957 | M | Ruben | 1382 | 0.0006318 |
1958 | M | Ruben | 1375 | 0.0006386 |
1959 | M | Ruben | 1358 | 0.0006269 |
1960 | M | Ruben | 1359 | 0.0006275 |
1961 | M | Ruben | 1382 | 0.0006410 |
1962 | M | Ruben | 1380 | 0.0006565 |
1963 | M | Ruben | 1259 | 0.0006096 |
1964 | M | Ruben | 1345 | 0.0006634 |
1965 | M | Ruben | 1150 | 0.0006068 |
1966 | M | Ruben | 1198 | 0.0006590 |
1967 | M | Ruben | 1175 | 0.0006602 |
1968 | M | Ruben | 1139 | 0.0006413 |
1969 | M | Ruben | 1237 | 0.0006760 |
1970 | M | Ruben | 1326 | 0.0006958 |
1971 | M | Ruben | 1322 | 0.0007270 |
1972 | M | Ruben | 1323 | 0.0007900 |
1973 | M | Ruben | 1310 | 0.0008115 |
1974 | M | Ruben | 1383 | 0.0008481 |
1975 | M | Ruben | 1376 | 0.0008478 |
1976 | M | Ruben | 1365 | 0.0008358 |
1977 | M | Ruben | 1365 | 0.0007983 |
1978 | M | Ruben | 1379 | 0.0008069 |
1979 | M | Ruben | 1398 | 0.0007802 |
1980 | M | Ruben | 1488 | 0.0008022 |
1981 | M | Ruben | 1473 | 0.0007909 |
1982 | M | Ruben | 1470 | 0.0007790 |
1983 | M | Ruben | 1494 | 0.0008018 |
1984 | M | Ruben | 1374 | 0.0007323 |
1985 | M | Ruben | 1453 | 0.0007553 |
1986 | M | Ruben | 1381 | 0.0007189 |
1987 | M | Ruben | 1527 | 0.0007833 |
1988 | M | Ruben | 1592 | 0.0007955 |
1989 | M | Ruben | 1595 | 0.0007612 |
1990 | M | Ruben | 1744 | 0.0008107 |
1991 | M | Ruben | 1732 | 0.0008173 |
1992 | M | Ruben | 1805 | 0.0008601 |
1993 | M | Ruben | 1749 | 0.0008470 |
1994 | M | Ruben | 1724 | 0.0008460 |
1995 | M | Ruben | 1697 | 0.0008439 |
1996 | M | Ruben | 1662 | 0.0008296 |
1997 | M | Ruben | 1595 | 0.0007986 |
1998 | M | Ruben | 1582 | 0.0007804 |
1999 | M | Ruben | 1637 | 0.0008031 |
2000 | M | Ruben | 1716 | 0.0008221 |
2001 | M | Ruben | 1735 | 0.0008392 |
2002 | M | Ruben | 1571 | 0.0007606 |
2003 | M | Ruben | 1655 | 0.0007881 |
2004 | M | Ruben | 1601 | 0.0007580 |
2005 | M | Ruben | 1464 | 0.0006886 |
2006 | M | Ruben | 1593 | 0.0007271 |
2007 | M | Ruben | 1477 | 0.0006673 |
2008 | M | Ruben | 1354 | 0.0006215 |
2009 | M | Ruben | 1197 | 0.0005649 |
2010 | M | Ruben | 1102 | 0.0005370 |
2011 | M | Ruben | 975 | 0.0004806 |
2012 | M | Ruben | 957 | 0.0004724 |
2013 | M | Ruben | 887 | 0.0004398 |
2014 | M | Ruben | 892 | 0.0004363 |
2015 | M | Ruben | 862 | 0.0004229 |
2016 | M | Ruben | 797 | 0.0003950 |
2017 | M | Ruben | 745 | 0.0003795 |
# Vemos que el nombre de Ruben fue incrementando su popularidad en Estados Unidos a lo largo de los años, especialmente hasta 1992, y después, poco a poco, ha ido progresivamente perdiendo su atractivo. No obstante, no parece que Ruben haya sido un nombre muy recurrido en el país a lo largo de estos años.
Como se ha indicado previamente, las pipes %>%
sirven especialmente para encadenar funciones, pudiendo reducir el tamaño del código y facilitando su interpretación. Por ejemplo, en el caso de que nos interesara seleccionar únicamente el año y el nombre de los recién nacidos de sexo masculino en el año 2017 indicaríamos:
babynames %>%
select(year, sex, name) %>%
filter(year == 2017 & sex== "M")
## # A tibble: 14,160 x 3
## year sex name
## <dbl> <chr> <chr>
## 1 2017 M Liam
## 2 2017 M Noah
## 3 2017 M William
## 4 2017 M James
## 5 2017 M Logan
## 6 2017 M Benjamin
## 7 2017 M Mason
## 8 2017 M Elijah
## 9 2017 M Oliver
## 10 2017 M Jacob
## # ... with 14,150 more rows
group_by()
La función group_by()
convierte el data frame original en una tabla agrupada según los parámetros de la función. La función group_by()
, como veremos, funciona muy bien cuando se usa conjuntamente con otras funciones como summarise()
o mutate()
. Por tanto usaremos esta función conjuntamente con otras funciones en los apartados posteriores pero, a modo de ejemplo, veamos cómo se podría agrupar nuestro data frame según el sexo de los recién nacidos:
# La tabla_1 sería el resultado de agrupar las filas por sexo utilizando group_by()
tabla_1 <- babynames %>%
group_by(sex)
# Una vez agrupada la tabla por sexo, con la función summarise() que veremos después, podemos identificar el número de observaciones según el sexo masculino o femenino del recién nacido.
tabla_1 %>%
summarise(n = n())
## # A tibble: 2 x 2
## sex n
## <chr> <int>
## 1 F 1138293
## 2 M 786372
# Debemos recordar desagrupar las observaciones una vez realizado el análisis necesario utilizando la función ungroup()
tabla_1 <- tabla_1 %>%
ungroup()
# Vemos que una vez hemos desagrupado las observaciones, si aplicamos de nuevo la función summarise() el resultado obtenido es para el conjunto de observaciones y no para las observaciones agrupadas.
tabla_1 %>%
summarise(n = n())
## # A tibble: 1 x 1
## n
## <int>
## 1 1924665
mutate()
La función mutate()
nos permite añadir columnas nuevas partiendo de las columnas del data frame original. A modo de ejemplo podemos crear una nueva columna, que denominaremos prop_2
, como resultado de multiplicar la columna prop
por 100. La función mutate()
requiere, una vez indicado el data frame sobre el que se va a operar, que indiquemos el nombre de la nueva columna y la operación que determina el valor de la misma:
babynames %>%
mutate( prop_2 = prop * 100)
## # A tibble: 1,924,665 x 6
## year sex name n prop prop_2
## <dbl> <chr> <chr> <int> <dbl> <dbl>
## 1 1880 F Mary 7065 0.0724 7.24
## 2 1880 F Anna 2604 0.0267 2.67
## 3 1880 F Emma 2003 0.0205 2.05
## 4 1880 F Elizabeth 1939 0.0199 1.99
## 5 1880 F Minnie 1746 0.0179 1.79
## 6 1880 F Margaret 1578 0.0162 1.62
## 7 1880 F Ida 1472 0.0151 1.51
## 8 1880 F Alice 1414 0.0145 1.45
## 9 1880 F Bertha 1320 0.0135 1.35
## 10 1880 F Sarah 1288 0.0132 1.32
## # ... with 1,924,655 more rows
# De esta forma comprobamos de una forma más adecuada que Mary, el nombre femenino más utilizado en 1880, representa el 7,24 del total de nombres de recién nacidos en dicho año.
Supongamos que nos interesa que en una nueva columna se indique el total de las observaciones del conjunto del data frame. En nuestro caso cabe la posibilidad que nos interese crear una nueva columna donde se indique la suma del total de los babynames , es decir, de n
, bien sea la suma de todos los años del periodo (1880-2017), bien sea el total según el año. En dicho caso podemos utilizar la función mutate()
de la siguiente forma:
# En el primero de los casos la columna sería igual para el total de observaciones, en tanto en cuanto indica el total de n (348120517).
babynames %>%
mutate( suma_total = sum(n))
## # A tibble: 1,924,665 x 6
## year sex name n prop suma_total
## <dbl> <chr> <chr> <int> <dbl> <int>
## 1 1880 F Mary 7065 0.0724 348120517
## 2 1880 F Anna 2604 0.0267 348120517
## 3 1880 F Emma 2003 0.0205 348120517
## 4 1880 F Elizabeth 1939 0.0199 348120517
## 5 1880 F Minnie 1746 0.0179 348120517
## 6 1880 F Margaret 1578 0.0162 348120517
## 7 1880 F Ida 1472 0.0151 348120517
## 8 1880 F Alice 1414 0.0145 348120517
## 9 1880 F Bertha 1320 0.0135 348120517
## 10 1880 F Sarah 1288 0.0132 348120517
## # ... with 1,924,655 more rows
# En el segundo de los casos, agrupando por año, el valor de la columna sería distinta según el año. Así, por ejemplo, para 1880 la suma de n sería 201484.
babynames %>%
group_by(year) %>%
mutate( suma_by_year = sum(n))
## # A tibble: 1,924,665 x 6
## # Groups: year [138]
## year sex name n prop suma_by_year
## <dbl> <chr> <chr> <int> <dbl> <int>
## 1 1880 F Mary 7065 0.0724 201484
## 2 1880 F Anna 2604 0.0267 201484
## 3 1880 F Emma 2003 0.0205 201484
## 4 1880 F Elizabeth 1939 0.0199 201484
## 5 1880 F Minnie 1746 0.0179 201484
## 6 1880 F Margaret 1578 0.0162 201484
## 7 1880 F Ida 1472 0.0151 201484
## 8 1880 F Alice 1414 0.0145 201484
## 9 1880 F Bertha 1320 0.0135 201484
## 10 1880 F Sarah 1288 0.0132 201484
## # ... with 1,924,655 more rows
# Al realizar este tipo de operaciones debemos siempre ser conscientes de los valores que estamos sumando (o con los que estamos operando) para evitar equívocos. Por ello, resulta de gran utilidad utilizar la función summarise() que vemos a continuación.
summarise()
La función summarise()
provee un valor determinado en función de un conjunto de valores. Así, por ejemplo, para determinar el número de observaciones (filas) del data frame, o para determinar el número total de nacimientos (n
) podemos utilizar esta función de la siguiente forma:
babynames %>%
summarise(num_observaciones = n(),
total_babynames = sum(n))
## # A tibble: 1 x 2
## num_observaciones total_babynames
## <int> <int>
## 1 1924665 348120517
# Esta operación nos permite comprobar el total de observaciones y el total de babynames del conjunto del dataframe.
No obstante, la función summarise()
tiene una especial utilidad cuando se utiliza conjuntamente con la función group_by()
. Así, por ejemplo, podemos estimar fácilmente el número de nacimientos por cada año (o mejor dicho el número de solicitudes de la tarjeta de la SS por nacimiento en Estados Unidos cada año):
babynames %>%
group_by (year) %>%
summarise(suma = sum(n))
## # A tibble: 138 x 2
## year suma
## <dbl> <int>
## 1 1880 201484
## 2 1881 192696
## 3 1882 221533
## 4 1883 216946
## 5 1884 243462
## 6 1885 240854
## 7 1886 255317
## 8 1887 247394
## 9 1888 299473
## 10 1889 288946
## # ... with 128 more rows
# El total del primer deberá coincidir con el valor de la nueva columna creada previamente (suma_by_year) en cada uno de los años del periodo analizado.
De forma similar podemos identificar el número de nacimientos por año y por sexo de los recién nacidos:
babynames %>%
group_by (year, sex) %>%
summarise(suma = sum(n))
## # A tibble: 276 x 3
## # Groups: year [138]
## year sex suma
## <dbl> <chr> <int>
## 1 1880 F 90993
## 2 1880 M 110491
## 3 1881 F 91953
## 4 1881 M 100743
## 5 1882 F 107847
## 6 1882 M 113686
## 7 1883 F 112319
## 8 1883 M 104627
## 9 1884 F 129020
## 10 1884 M 114442
## # ... with 266 more rows
# En los primeros años el registro es mayor en los niños que en las niñas.
También podemos estimar en una sola orden el valor de diversos indicadores. A modo de ejemplo, estimamos para cada año y según el sexo del recién nacido, el total de nacimientos, el valor máximo y el valor mínimo (que previsiblemente será 5 debido a que la base de datos proporciona información de los nombres que superen dicho valor)
babynames %>%
group_by (year, sex) %>%
summarise(suma = sum(n), max = max(n), min = min(n))
## # A tibble: 276 x 5
## # Groups: year [138]
## year sex suma max min
## <dbl> <chr> <int> <int> <int>
## 1 1880 F 90993 7065 5
## 2 1880 M 110491 9655 5
## 3 1881 F 91953 6919 5
## 4 1881 M 100743 8769 5
## 5 1882 F 107847 8148 5
## 6 1882 M 113686 9557 5
## 7 1883 F 112319 8012 5
## 8 1883 M 104627 8894 5
## 9 1884 F 129020 9217 5
## 10 1884 M 114442 9388 5
## # ... with 266 more rows
En el data frame anterior podemos observar las observaciones con mayor valor n
en cada año y por sexo, entre otros aspectos. No obstante, puede que nos interese determinar qué nombres lideran el ranking cada año. Para ello podemos establecer el siguiente código:
# Para establecer los nombres (F y M) que lideran el ranking entre 1880 y 1889:
babynames %>%
group_by (year, sex, name) %>%
summarise(max = max(n)) %>%
top_n(1) %>%
head(n=20)
## Selecting by max
## # A tibble: 20 x 4
## # Groups: year, sex [20]
## year sex name max
## <dbl> <chr> <chr> <int>
## 1 1880 F Mary 7065
## 2 1880 M John 9655
## 3 1881 F Mary 6919
## 4 1881 M John 8769
## 5 1882 F Mary 8148
## 6 1882 M John 9557
## 7 1883 F Mary 8012
## 8 1883 M John 8894
## 9 1884 F Mary 9217
## 10 1884 M John 9388
## 11 1885 F Mary 9128
## 12 1885 M John 8756
## 13 1886 F Mary 9889
## 14 1886 M John 9026
## 15 1887 F Mary 9888
## 16 1887 M John 8110
## 17 1888 F Mary 11754
## 18 1888 M John 9247
## 19 1889 F Mary 11648
## 20 1889 M John 8548
# Para establecer los nombres (F y M) que lideran el ranking entre 2008 y 2017:
babynames %>%
group_by (year, sex, name) %>%
summarise(max = max(n)) %>%
top_n(1) %>%
tail(n=20)
## Selecting by max
## # A tibble: 20 x 4
## # Groups: year, sex [20]
## year sex name max
## <dbl> <chr> <chr> <int>
## 1 2008 F Emma 18809
## 2 2008 M Jacob 22591
## 3 2009 F Isabella 22298
## 4 2009 M Jacob 21169
## 5 2010 F Isabella 22905
## 6 2010 M Jacob 22117
## 7 2011 F Sophia 21837
## 8 2011 M Jacob 20365
## 9 2012 F Sophia 22304
## 10 2012 M Jacob 19069
## 11 2013 F Sophia 21213
## 12 2013 M Noah 18241
## 13 2014 F Emma 20924
## 14 2014 M Noah 19286
## 15 2015 F Emma 20435
## 16 2015 M Noah 19613
## 17 2016 F Emma 19471
## 18 2016 M Noah 19082
## 19 2017 F Emma 19738
## 20 2017 M Liam 18728
# Mary y John son, definitivamente, los nombres más recurrentes al inicio del periodo. Por el contrario, en la última década existe una mayor variabilidad en el nombre más escogido tanto para niño como para niña. No obstante, es fácil identificar un grupo de nombres de gran atractivo para la población en estos años, bien sea Emma, Isabella o Sophia para niña o Jacob y Noah para niño.
Una forma alternativa es indicando expresamente que queremos detectar la primera observación del rango deseado, la última o podemos establecer la posición de la observación deseada:
# La primera observación coincidirá con el resultado anterior, siendo Mary y John los nombres más comunes de los primeros años del periodo considerado.
babynames %>%
group_by (year, sex) %>%
summarise(nombre = first(name), max = max(n))
## # A tibble: 276 x 4
## # Groups: year [138]
## year sex nombre max
## <dbl> <chr> <chr> <int>
## 1 1880 F Mary 7065
## 2 1880 M John 9655
## 3 1881 F Mary 6919
## 4 1881 M John 8769
## 5 1882 F Mary 8148
## 6 1882 M John 9557
## 7 1883 F Mary 8012
## 8 1883 M John 8894
## 9 1884 F Mary 9217
## 10 1884 M John 9388
## # ... with 266 more rows
# En este caso particular detectar la observación más baja carece de significado, en tanto en cuanto las observaciones más bajas serán de 5 (mínimo valor de la base de datos), pero puede resultar muy útil en otros análisis
babynames %>%
group_by (year, sex) %>%
summarise(nombre = last(name), min = min(n))
## # A tibble: 276 x 4
## # Groups: year [138]
## year sex nombre min
## <dbl> <chr> <chr> <int>
## 1 1880 F Wilma 5
## 2 1880 M Zachariah 5
## 3 1881 F Viney 5
## 4 1881 M Wright 5
## 5 1882 F Zilla 5
## 6 1882 M Zed 5
## 7 1883 F Zoa 5
## 8 1883 M Winthrop 5
## 9 1884 F Yetta 5
## 10 1884 M Zachariah 5
## # ... with 266 more rows
# Podemos indicar qué valor queremos, pongamos que en lugar de la observación de mayor valor queremos el segundo nombre más utilizado por año y sexo:
babynames %>%
group_by (year, sex) %>%
summarise(nombre = nth(name, 2))
## # A tibble: 276 x 3
## # Groups: year [138]
## year sex nombre
## <dbl> <chr> <chr>
## 1 1880 F Anna
## 2 1880 M William
## 3 1881 F Anna
## 4 1881 M William
## 5 1882 F Anna
## 6 1882 M William
## 7 1883 F Anna
## 8 1883 M William
## 9 1884 F Anna
## 10 1884 M William
## # ... with 266 more rows
# Vemos que tras Mary y John los nombres que lideran el ranking, al menos en los primeros años del periodo, son Anna y William.
También es posible seleccionar las columnas indicando el número de filas. Así, por ejemplo, para seleccionar los dos primeros valores de cada año y sexo podemos indicar la siguiente orden:
babynames %>%
group_by(year, sex) %>%
filter(row_number() <=2)
## # A tibble: 552 x 5
## # Groups: year, sex [276]
## year sex name n prop
## <dbl> <chr> <chr> <int> <dbl>
## 1 1880 F Mary 7065 0.0724
## 2 1880 F Anna 2604 0.0267
## 3 1880 M John 9655 0.0815
## 4 1880 M William 9532 0.0805
## 5 1881 F Mary 6919 0.0700
## 6 1881 F Anna 2698 0.0273
## 7 1881 M John 8769 0.0810
## 8 1881 M William 8524 0.0787
## 9 1882 F Mary 8148 0.0704
## 10 1882 F Anna 3143 0.0272
## # ... with 542 more rows
# Evidentemente, los nombres detectados son los mismos que los obtenidos en los ejercicios previos
arrange()
La función arrange()
nos permite ordenar los datos por filas según algún criterio establecido. Pongamos en este caso que queremos ordenar las observaciones por nombre, según un criterio alfabético.
# Para ordenar las filas de la A a la Z:
babynames %>%
arrange(name)
## # A tibble: 1,924,665 x 5
## year sex name n prop
## <dbl> <chr> <chr> <int> <dbl>
## 1 2007 M Aaban 5 0.00000226
## 2 2009 M Aaban 6 0.00000283
## 3 2010 M Aaban 9 0.00000439
## 4 2011 M Aaban 11 0.00000542
## 5 2012 M Aaban 11 0.00000543
## 6 2013 M Aaban 14 0.00000694
## 7 2014 M Aaban 16 0.00000783
## 8 2015 M Aaban 15 0.00000736
## 9 2016 M Aaban 9 0.00000446
## 10 2017 M Aaban 11 0.0000056
## # ... with 1,924,655 more rows
# Para ordenarlas de la Z a la A:
babynames %>%
arrange(desc(name))
## # A tibble: 1,924,665 x 5
## year sex name n prop
## <dbl> <chr> <chr> <int> <dbl>
## 1 2010 M Zzyzx 5 0.00000244
## 2 2014 M Zyyon 6 0.00000293
## 3 2010 F Zyyanna 6 0.00000306
## 4 2015 M Zyvon 7 0.00000343
## 5 2009 M Zyvion 5 0.00000236
## 6 2016 F Zyva 8 0.00000415
## 7 2017 F Zyva 9 0.0000048
## 8 2015 M Zyus 5 0.00000245
## 9 2002 M Zytavious 6 0.0000029
## 10 2004 M Zytavious 6 0.00000284
## # ... with 1,924,655 more rows
# Resulta que Zzyzx, antes llamado Soda Springs, es una comunidad en el Condado de San Bernardino, en el desierto de Mojave en California. Según Wikipedia un tal Curtis Howe Springer se inventó el término y lo dio a dicho espacio, orgulloso de que dicho vocablo fuese la última palabra en el idioma inglés. Parece ser que la revista Reader´s Digest ha declarado a Zzyzx el lugar de California más difícil de pronunciar y que una encuesta de eBabyNames.com dice que Zzyzx (que se pronunciaría algo así como Zay-Zix) sería, según sus encuestados, el nombre más raro que habría existido jamás.
Podemos también organizar las observaciones según otros criterios. Si por ejemplo queremos detectar qué nombres, en qué año y a qué sexo corresponde las observaciones con mayor número de registros. Para ello podemos anotar la siguiente orden:
babynames %>%
arrange(desc(n))
## # A tibble: 1,924,665 x 5
## year sex name n prop
## <dbl> <chr> <chr> <int> <dbl>
## 1 1947 F Linda 99686 0.0548
## 2 1948 F Linda 96209 0.0552
## 3 1947 M James 94756 0.0510
## 4 1957 M Michael 92695 0.0424
## 5 1947 M Robert 91642 0.0493
## 6 1949 F Linda 91016 0.0518
## 7 1956 M Michael 90620 0.0423
## 8 1958 M Michael 90520 0.0420
## 9 1948 M James 88588 0.0497
## 10 1954 M Michael 88514 0.0428
## # ... with 1,924,655 more rows
# En este caso vemos que Linda resultó ser la opción más popular para las niñas en 1947 y 1948, siendo estos años donde más gente coincidió en su decisión.
dplyr y ggplot2
Dado que una imagen vale más que mil palabras conviene tener en cuenta que las funciones del paquete dplyr
, utilizando pipes (%
) para encadenar funciones, pueden utilizarse conjuntamente con los gráficos de ggplot como se observa en los siguientes ejemplos.
Supongamos que queremos observar la evolución del número total de registros de solicitud de la tarjeta de la Seguridad Social por año, para lo que utilizaremos las funciones group_by()
y summarise()
seguido de las instrucciones de ggplot2.
# Cargamos la librería ggplot2
library(ggplot2)
babynames %>%
group_by(year) %>%
summarise(suma = sum(n)) %>%
ggplot(aes(x= year, y = suma, fill = "orange")) +
geom_col() +
scale_y_continuous(labels = scales::comma) +
theme_minimal() +
guides(fill=F) +
labs( x= "year",
y= " ",
title = "Número de personas recién nacidas en Estados Unidos desde 1880 a 2017",
subtitle = "Estimado en base al número de solicitudes de la tarjeta de la Seguridad Social",
caption = "US Social Security Administration")
En el caso de que quisiéramos graficar los nombres más populares por sexo en 1880 y 2017 podríamos establecer un código similar al siguiente:
# Creamos un nuevo data frame, con información específica de 1880 y 2017 seleccionando los registros que lideran el ranking.
babynames_2 <- babynames %>%
select(year, sex, name, n) %>%
filter( year == 1880 | year == 2017) %>%
group_by(year, sex, name, n) %>%
arrange (year, sex, n) %>%
group_by( year, sex) %>%
top_n(20, n)
Para realizar los siguientes gráficos vamos a utilizar un theme diseñado por Tradfford Data Lab llamado theme_lab()
que particularmente encuentro muy agradable visualmente.
# La descarga de este theme se encuentra en el siguiente link:
source("https://github.com/traffordDataLab/assets/raw/master/theme/ggplot2/theme_lab.R")
Utilizando el data frame creado (babynames_2), identificamos y graficamos para el año 1880 los 40 nombres, 20 de sexo masculino y 20 de sexo femenino, mediante el siguiente código:
babynames_2 %>%
filter( year == 1880) %>%
arrange(desc(n)) %>%
ggplot(aes(reorder(name, n), n)) +
geom_col(fill = "#fc6721",
alpha = 0.8)+
coord_flip() +
facet_wrap(~sex, scales= "free_y", ncol=2)+
theme_lab() +
theme(panel.grid.major.x = element_blank())+
scale_y_continuous(labels = scales::comma) +
geom_text(aes(label=n, y=n + 1),
hjust=1.1,
color="white",
size= 3.2)+
labs(title = "Los 20 nombres más populares por sexo en 1880",
subtitle = "Estimado en base al número de solicitudes de la tarjeta de la Seguridad Social",
caption = "Source: US Social Security Administration",
x = "", y = "",
fill = NULL)
# Como se comprobó previamente Mary y John lideran el ranking en 1880 aunque William, James, Charles o George también fueron nombres de notable popularidad.
De forma similar, modificando un par de líneas del comando anterior podemos realizar el mismo ejercicio para el año 2017, observando de esta forma la evolución de los nombres, y la mayor variedad
babynames_2 %>%
filter( year == 2017) %>%
arrange(desc(n)) %>%
ggplot(aes(reorder(name, n), n)) +
geom_col(fill = "#fc6721",
alpha = 0.8)+
coord_flip() +
facet_wrap(~sex, scales= "free_y", ncol=2)+
theme_lab() +
theme(panel.grid.major.x = element_blank())+
scale_y_continuous(labels = scales::comma) +
geom_text(aes(label=n, y=n + 1),
hjust=1.1,
color="white",
size= 3.2)+
labs(title = "Los 20 nombres más populares por sexo en 2017",
subtitle = "Estimado en base al número de solicitudes de la tarjeta de la Seguridad Social",
caption = "Source: US Social Security Administration",
x = "", y = "",
fill = NULL)