El paquete dplyr es una herramienta rápida y consistente para trabajar con data frames como si fueran un objeto, además es muy sencillo y eficiente.
Las funciones que utiliza dplyr son muy similares entre si, de tal forma que una vez aprendas a usar una es fácil entender el resto.
Tiene una función para cada manipulación que queramos hacer, entre las más importantes estan:
-filter() (y slice())
-arrange()
-select() (y rename())
-distinct()
-mutate() (y transmute())
-summarise()
-sample_n() y sample_frac()
Iremos estudiando cada una de estas funciones individualmente, para los ejemplos utilizaremos la base de datos de R llamada Seatbelts que contiene una serie temporal mensual de las personas que han muerto o han tenido lesiones graves en accidentes automovilísticos en Gran Bretaña entre Enero de 1969 y Diciembre de 1984.
library(dplyr)
##
## Attaching package: 'dplyr'
##
## The following object is masked from 'package:stats':
##
## filter
##
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
datos <- tbl_df(data.frame(Year=rep(1969:1984,each=12), Month=rep(month.abb,16),Seatbelts))
filter()
La función filter() nos permite seleccionar un subconjunto de filas del data frame, el primer argumento es el nombre del data frame y los siguientes son expresiones para filtrar nuestro data frame.
Por ejemplo, podemos seleccionar los accidentes de Febrero de 1974 con:
filter(datos, Month == 'Feb', Year == 1974)
## Source: local data frame [1 x 10]
##
## Year Month DriversKilled drivers front rear kms PetrolPrice VanKilled
## 1 1974 Feb 100 1503 665 299 10808 0.1081615 6
## Variables not shown: law (dbl)
Esto sería equivalente en R a:
datos[datos$Month == 'Feb' & datos$Year == 1974, ]
filter() funciona de manera similar a subset() con excepción de que puedes introducir cualquier número de condiciones.
Otro ejemplo:
filter(datos, drivers>100 , front > 1000, Month == 'Nov')
## Source: local data frame [4 x 10]
##
## Year Month DriversKilled drivers front rear kms PetrolPrice VanKilled
## 1 1969 Nov 147 2152 1109 434 9834 0.10273011 13
## 2 1970 Nov 169 2242 1171 456 10643 0.09573896 16
## 3 1971 Nov 187 2233 1045 402 11467 0.09170669 14
## 4 1972 Nov 168 2397 1089 462 12220 0.08742885 17
## Variables not shown: law (dbl)
Para seleccionar filas por su posición se utiliza la función slice():
slice(datos,15:20)
## Source: local data frame [6 x 10]
##
## Year Month DriversKilled drivers front rear kms PetrolPrice VanKilled
## 1 1970 Mar 110 1717 1006 351 11000 0.10013961 8
## 2 1970 Apr 102 1558 892 362 10733 0.09862110 11
## 3 1970 May 103 1575 990 486 12912 0.09834929 7
## 4 1970 Jun 111 1520 866 429 12926 0.09808018 13
## 5 1970 Jul 120 1805 1095 551 13990 0.09727921 13
## 6 1970 Aug 129 1800 1204 646 14926 0.09741062 11
## Variables not shown: law (dbl)
arrange()
arrange() funciona de manera similar a filter(), con la diferencia de que reordena las filas en lugar de filtrar y seleccionarlas. Solamente necesitas introducir el data frame y el nombre de la columna que deseas ordenar, si proporcionas más de un nombre de columnna esta se utilizará para desempatar los valores de las columnas anteriores. Por ejemplo:
arrange(datos, DriversKilled, drivers)
## Source: local data frame [192 x 10]
##
## Year Month DriversKilled drivers front rear kms PetrolPrice VanKilled
## 1 1983 Jul 60 1174 587 477 20997 0.12005924 6
## 2 1984 Jul 79 1222 601 472 21486 0.11493598 7
## 3 1977 Feb 79 1401 567 224 12028 0.10040232 9
## 4 1984 Mar 81 1282 513 349 18539 0.11573525 4
## 5 1983 May 82 1236 559 398 19205 0.11796940 3
## 6 1977 Mar 82 1411 616 266 14033 0.09886203 7
## 7 1984 Apr 84 1110 548 375 19759 0.11535626 3
## 8 1983 Aug 84 1139 615 422 20705 0.11943775 8
## 9 1981 Apr 84 1404 714 358 16854 0.11516148 6
## 10 1984 Feb 86 1165 434 319 16670 0.11479699 3
## .. ... ... ... ... ... ... ... ... ...
## Variables not shown: law (dbl)
Usaremos desc() para ordenar la columna en orden descendente:
arrange(datos, desc(DriversKilled), drivers)
## Source: local data frame [192 x 10]
##
## Year Month DriversKilled drivers front rear kms PetrolPrice VanKilled
## 1 1972 Dec 198 2654 1208 497 12025 0.08703543 14
## 2 1970 Dec 190 2478 1299 468 10742 0.09510631 14
## 3 1971 Nov 187 2233 1045 402 11467 0.09170669 14
## 4 1970 Oct 183 2008 1147 475 12034 0.09638063 14
## 5 1977 Dec 183 2215 1046 431 13842 0.08933071 7
## 6 1969 Dec 180 2148 1113 437 9267 0.10199719 14
## 7 1978 Dec 178 2262 1010 390 13726 0.08477030 7
## 8 1979 Dec 171 2207 1077 466 15161 0.10760157 10
## 9 1972 Oct 170 1976 1074 452 13532 0.08772661 5
## 10 1970 Nov 169 2242 1171 456 10643 0.09573896 16
## .. ... ... ... ... ... ... ... ... ...
## Variables not shown: law (dbl)
select()
Muchas veces tenemos un data frame con muchas columnas pero realmente solo nos interesa trabajar con unas pocas, la función select() es la que nos permite quedarnos rápidamente con las columnas de nuestro interés.
#Selección de columnas por nombre
select(datos, Year, Month, drivers, front, rear)
## Source: local data frame [192 x 5]
##
## Year Month drivers front rear
## 1 1969 Jan 1687 867 269
## 2 1969 Feb 1508 825 265
## 3 1969 Mar 1507 806 319
## 4 1969 Apr 1385 814 407
## 5 1969 May 1632 991 454
## 6 1969 Jun 1511 945 427
## 7 1969 Jul 1559 1004 522
## 8 1969 Aug 1630 1091 536
## 9 1969 Sep 1579 958 405
## 10 1969 Oct 1653 850 437
## .. ... ... ... ... ...
#Selección de columnas entre DriversKilled y rear
select(datos, DriversKilled:rear)
## Source: local data frame [192 x 4]
##
## DriversKilled drivers front rear
## 1 107 1687 867 269
## 2 97 1508 825 265
## 3 102 1507 806 319
## 4 87 1385 814 407
## 5 119 1632 991 454
## 6 106 1511 945 427
## 7 110 1559 1004 522
## 8 106 1630 1091 536
## 9 107 1579 958 405
## 10 134 1653 850 437
## .. ... ... ... ...
#Selección de columnas exceptuando las que están entre kms y law
select(datos, -(kms:law))
## Source: local data frame [192 x 6]
##
## Year Month DriversKilled drivers front rear
## 1 1969 Jan 107 1687 867 269
## 2 1969 Feb 97 1508 825 265
## 3 1969 Mar 102 1507 806 319
## 4 1969 Apr 87 1385 814 407
## 5 1969 May 119 1632 991 454
## 6 1969 Jun 106 1511 945 427
## 7 1969 Jul 110 1559 1004 522
## 8 1969 Aug 106 1630 1091 536
## 9 1969 Sep 107 1579 958 405
## 10 1969 Oct 134 1653 850 437
## .. ... ... ... ... ... ...
Hay muchas funciones que sirven de ayuda para usarse dentro de select(), como starts_with(), ends_with(), matches() y contains(), de esta manera puedes seleccionar más rápido grandes bloques de columnas que cumplen algún criterio que te interese, por ejemplo:
select(datos, contains('k'))
## Source: local data frame [192 x 3]
##
## DriversKilled kms VanKilled
## 1 107 9059 12
## 2 97 7685 6
## 3 102 9963 12
## 4 87 10955 8
## 5 119 11823 10
## 6 106 12391 13
## 7 110 13460 11
## 8 106 14055 6
## 9 107 12106 10
## 10 134 11372 16
## .. ... ... ...
select(datos, starts_with('driv'))
## Source: local data frame [192 x 2]
##
## DriversKilled drivers
## 1 107 1687
## 2 97 1508
## 3 102 1507
## 4 87 1385
## 5 119 1632
## 6 106 1511
## 7 110 1559
## 8 106 1630
## 9 107 1579
## 10 134 1653
## .. ... ...
Se puede utilizar select() para renombrar las columnas:
select(datos, CondMuertos=DriversKilled)
## Source: local data frame [192 x 1]
##
## CondMuertos
## 1 107
## 2 97
## 3 102
## 4 87
## 5 119
## 6 106
## 7 110
## 8 106
## 9 107
## 10 134
## .. ...
El problema de esto es que solamente muestra la columna que hemos cambiado y no es muy útil.
En lugar de select() usaremos rename() para renombrar las columnas:
rename(datos, CondMuertos=DriversKilled, Conductores=drivers)
## Source: local data frame [192 x 10]
##
## Year Month CondMuertos Conductores front rear kms PetrolPrice
## 1 1969 Jan 107 1687 867 269 9059 0.1029718
## 2 1969 Feb 97 1508 825 265 7685 0.1023630
## 3 1969 Mar 102 1507 806 319 9963 0.1020625
## 4 1969 Apr 87 1385 814 407 10955 0.1008733
## 5 1969 May 119 1632 991 454 11823 0.1010197
## 6 1969 Jun 106 1511 945 427 12391 0.1005812
## 7 1969 Jul 110 1559 1004 522 13460 0.1037740
## 8 1969 Aug 106 1630 1091 536 14055 0.1040764
## 9 1969 Sep 107 1579 958 405 12106 0.1037740
## 10 1969 Oct 134 1653 850 437 11372 0.1030264
## .. ... ... ... ... ... ... ... ...
## Variables not shown: VanKilled (dbl), law (dbl)
distinct()
La función distinct() nos devuelve los valores únicos en una tabla, se suele usar en conjunto con select():
#Muestra en pantalla los valores que toman los años:
distinct(select(datos, Year))
## Source: local data frame [16 x 1]
##
## Year
## 1 1969
## 2 1970
## 3 1971
## 4 1972
## 5 1973
## 6 1974
## 7 1975
## 8 1976
## 9 1977
## 10 1978
## 11 1979
## 12 1980
## 13 1981
## 14 1982
## 15 1983
## 16 1984
#Muestra en pantalla los valores distintos que toma DriversKilled:
distinct(select(datos, DriversKilled))
## Source: local data frame [82 x 1]
##
## DriversKilled
## 1 107
## 2 97
## 3 102
## 4 87
## 5 119
## 6 106
## 7 110
## 8 134
## 9 147
## 10 180
## .. ...
#Podemos usar el arrange antes visto para ordenar los valores:
arrange(distinct(select(datos, DriversKilled)), DriversKilled)
## Source: local data frame [82 x 1]
##
## DriversKilled
## 1 60
## 2 79
## 3 81
## 4 82
## 5 84
## 6 86
## 7 87
## 8 89
## 9 90
## 10 92
## .. ...
mutate()
Así como seleccionar las columnas de un data frame, a menudo también es importante crear nuevas columnas en función de las que ya tenemos. Este es el trabajo de mutate()
mutate(datos, total=front+rear, Costo=kms*PetrolPrice)
## Source: local data frame [192 x 12]
##
## Year Month DriversKilled drivers front rear kms PetrolPrice VanKilled
## 1 1969 Jan 107 1687 867 269 9059 0.1029718 12
## 2 1969 Feb 97 1508 825 265 7685 0.1023630 6
## 3 1969 Mar 102 1507 806 319 9963 0.1020625 12
## 4 1969 Apr 87 1385 814 407 10955 0.1008733 8
## 5 1969 May 119 1632 991 454 11823 0.1010197 10
## 6 1969 Jun 106 1511 945 427 12391 0.1005812 13
## 7 1969 Jul 110 1559 1004 522 13460 0.1037740 11
## 8 1969 Aug 106 1630 1091 536 14055 0.1040764 6
## 9 1969 Sep 107 1579 958 405 12106 0.1037740 10
## 10 1969 Oct 134 1653 850 437 11372 0.1030264 16
## .. ... ... ... ... ... ... ... ... ...
## Variables not shown: law (dbl), total (dbl), Costo (dbl)
mutate() funciona de manera similar a transform(), la diferencia esta en que mutate() permite hacer referencia a las columnas que acabas de crear:
mutate(datos, total=front+rear, PorcentFront=front/total, PorcentRear=rear/total)
## Source: local data frame [192 x 13]
##
## Year Month DriversKilled drivers front rear kms PetrolPrice VanKilled
## 1 1969 Jan 107 1687 867 269 9059 0.1029718 12
## 2 1969 Feb 97 1508 825 265 7685 0.1023630 6
## 3 1969 Mar 102 1507 806 319 9963 0.1020625 12
## 4 1969 Apr 87 1385 814 407 10955 0.1008733 8
## 5 1969 May 119 1632 991 454 11823 0.1010197 10
## 6 1969 Jun 106 1511 945 427 12391 0.1005812 13
## 7 1969 Jul 110 1559 1004 522 13460 0.1037740 11
## 8 1969 Aug 106 1630 1091 536 14055 0.1040764 6
## 9 1969 Sep 107 1579 958 405 12106 0.1037740 10
## 10 1969 Oct 134 1653 850 437 11372 0.1030264 16
## .. ... ... ... ... ... ... ... ... ...
## Variables not shown: law (dbl), total (dbl), PorcentFront (dbl),
## PorcentRear (dbl)
Si solamente queremos quedarnos con las nuevas variables entonces usaremos transmute():
transmute(datos, total=front+rear, PorcentFront=front/total, PorcentRear=rear/total)
## Source: local data frame [192 x 3]
##
## total PorcentFront PorcentRear
## 1 1136 0.7632042 0.2367958
## 2 1090 0.7568807 0.2431193
## 3 1125 0.7164444 0.2835556
## 4 1221 0.6666667 0.3333333
## 5 1445 0.6858131 0.3141869
## 6 1372 0.6887755 0.3112245
## 7 1526 0.6579292 0.3420708
## 8 1627 0.6705593 0.3294407
## 9 1363 0.7028613 0.2971387
## 10 1287 0.6604507 0.3395493
## .. ... ... ...
summarise()
Colapsa un data frame en una sola fila, no es muy útil de momento:
summarise(datos, kms_mean = mean(kms, na.rm=TRUE), SD_Petrol=sd(PetrolPrice))
## Source: local data frame [1 x 2]
##
## kms_mean SD_Petrol
## 1 14993.6 0.01217583
sample_n y sample_frac()
Se utilizan para obtener muestras aleatorias de filas, puede ser un número exacto con sample_n() o una fracción con sample_frac():
#Muestra de 8 filas:
sample_n(datos, 8)
## Source: local data frame [8 x 10]
##
## Year Month DriversKilled drivers front rear kms PetrolPrice VanKilled
## 1 1976 Apr 101 1395 643 373 14417 0.1096425 10
## 2 1981 Apr 84 1404 714 358 16854 0.1151615 6
## 3 1974 Feb 100 1503 665 299 10808 0.1081615 6
## 4 1976 Jan 102 1473 704 266 12177 0.1137935 14
## 5 1980 Aug 104 1552 885 466 19361 0.1081939 10
## 6 1978 Jun 106 1622 865 440 16882 0.0844319 11
## 7 1982 May 103 1487 755 410 18581 0.1113040 4
## 8 1975 Feb 92 1356 607 302 11096 0.1308452 16
## Variables not shown: law (dbl)
#Muestra del 3% de las filas:
sample_frac(datos, 0.03)
## Source: local data frame [6 x 10]
##
## Year Month DriversKilled drivers front rear kms PetrolPrice VanKilled
## 1 1984 Jul 79 1222 601 472 21486 0.11493598 7
## 2 1976 Sep 108 1627 767 346 15406 0.10616402 10
## 3 1971 Oct 140 1992 1077 446 12729 0.09226965 13
## 4 1980 Apr 100 1360 646 310 16585 0.11169537 4
## 5 1979 Mar 128 1762 794 342 14723 0.08755921 9
## 6 1981 Feb 106 1458 691 316 14932 0.10400254 6
## Variables not shown: law (dbl)
Operaciones Agrupadas
Las funciones vistas hasta ahora se pueden encadenar facilmente para obtener resultados más complejos, son bastante utiles pero son mucho más poderosas si agrupamos los datos con group_by(), de esta manera repetiremos las operaciones individualmente en grupos de observaciones de nuestra base de datos.
#Creamos un nuevo data frame agrupado por law, (law toma el valor 0 o 1 según estaba en vigor la ley del uso obligatorio de cinturones de seguridad)
por_law <- group_by(datos, law)
#Calculamos la media de los valores de drivers, front y rear una vez agrupados por law
summarise(por_law, media_drivers = mean(drivers, na.rm = TRUE),
media_front = mean(front, na.rm = TRUE),
media_rear = mean(rear, na.rm = TRUE))
## Source: local data frame [2 x 4]
##
## law media_drivers media_front media_rear
## 1 0 1717.751 873.4556 400.3195
## 2 1 1321.696 570.9565 407.7391
#La ley solo obligaba a los conductores y los pasajeros de adelante a usar el cinturón, de ahi que podamos apreciar una disminución drástica de los lesionados y muertos en esos asientos, mientras que en la parte trasera del coche ha habido un ligero aumento.
Otras Operaciones
Las funciones que se verán a continuación son de menor relevancia pero pueden resultar utiles en algunos casos:
tbl_df() Sirve para mostrar en pantalla solamente una parte de las columnas y filas que caben en pantalla, el resto las describe textualmente.
add_rownames() Sirve para convertir los nombres de las filas en una variable
tbl_df(add_rownames(datos, var = "NuevaVar"))
## Source: local data frame [192 x 11]
##
## NuevaVar Year Month DriversKilled drivers front rear kms PetrolPrice
## 1 1 1969 Jan 107 1687 867 269 9059 0.1029718
## 2 2 1969 Feb 97 1508 825 265 7685 0.1023630
## 3 3 1969 Mar 102 1507 806 319 9963 0.1020625
## 4 4 1969 Apr 87 1385 814 407 10955 0.1008733
## 5 5 1969 May 119 1632 991 454 11823 0.1010197
## 6 6 1969 Jun 106 1511 945 427 12391 0.1005812
## 7 7 1969 Jul 110 1559 1004 522 13460 0.1037740
## 8 8 1969 Aug 106 1630 1091 536 14055 0.1040764
## 9 9 1969 Sep 107 1579 958 405 12106 0.1037740
## 10 10 1969 Oct 134 1653 850 437 11372 0.1030264
## .. ... ... ... ... ... ... ... ... ...
## Variables not shown: VanKilled (dbl), law (dbl)
as_data_frame() Convierte una lista en un data frame, para que funcione cada elemento de la lista tiene que tener la misma longitud.
Dplyr cuenta con estas funciones acumulativas: cumall(), cumany() y cummean().
groups() Nos muestra una lista de las agrupaciones que tiene el data frame.
ungroup() Deshace las agrupaciones existentes en el data frame.
group_size() Calcula el tamaño de los grupos.
Referencias:
http://cran.r-project.org/web/packages/dplyr/dplyr.pdf
http://cran.rstudio.com/web/packages/dplyr/vignettes/introduction.html