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