Введение в dplyr*

При обработке данных вы должны:

  1. Представить что вы хотите получить.
  2. Детально описать желаемое в виде компьютерной программы.
  3. Выполнить код.

Пакет dplyr делает каждый из этих шагов на столько простым и быстрым на сколько это возможно следующим образом:

Цель этого документа – дать представление о базовых инструментах предоставляемых dplyr, и продемонстрировать их применение к структурам данных типа data.frame.

Также существуют отдельные руководства по следующим темам:

Набор данных ‘hflights’

Для исследования основных операций манипулирования данными в dplyr мы будем использовать встроенный набор данных hflights. Он содержит данные всех 227496 рейсов из Хьюстона за 2011 год, и предоставлен, как написано в ?hflights, бюро по перемещениям США.

    library(hflights)
    dim(hflights)
## [1] 227496     21
    head(hflights)
##      Year Month DayofMonth DayOfWeek DepTime ArrTime UniqueCarrier
## 5424 2011     1          1         6    1400    1500            AA
## 5425 2011     1          2         7    1401    1501            AA
## 5426 2011     1          3         1    1352    1502            AA
## 5427 2011     1          4         2    1403    1513            AA
## 5428 2011     1          5         3    1405    1507            AA
## 5429 2011     1          6         4    1359    1503            AA
##      FlightNum TailNum ActualElapsedTime AirTime ArrDelay DepDelay Origin
## 5424       428  N576AA                60      40      -10        0    IAH
## 5425       428  N557AA                60      45       -9        1    IAH
## 5426       428  N541AA                70      48       -8       -8    IAH
## 5427       428  N403AA                70      39        3        3    IAH
## 5428       428  N492AA                62      44       -3        5    IAH
## 5429       428  N262AA                64      45       -7       -1    IAH
##      Dest Distance TaxiIn TaxiOut Cancelled CancellationCode Diverted
## 5424  DFW      224      7      13         0                         0
## 5425  DFW      224      6       9         0                         0
## 5426  DFW      224      5      17         0                         0
## 5427  DFW      224      9      22         0                         0
## 5428  DFW      224      9       9         0                         0
## 5429  DFW      224      6      13         0                         0

dplyr может работать с data.frame непосредственно, но при работе с большими объёмами данных стоит конвертировать их в tbl_df, обёртку вокруг data.frame которая не станет по случайности выводить кучу данных на экран (это может очень медленным процессом).

    hflights_df <- tbl_df(hflights)
    hflights_df
## Source: local data frame [227,496 x 21]
## 
##    Year Month DayofMonth DayOfWeek DepTime ArrTime UniqueCarrier FlightNum
## 1  2011     1          1         6    1400    1500            AA       428
## 2  2011     1          2         7    1401    1501            AA       428
## 3  2011     1          3         1    1352    1502            AA       428
## 4  2011     1          4         2    1403    1513            AA       428
## 5  2011     1          5         3    1405    1507            AA       428
## 6  2011     1          6         4    1359    1503            AA       428
## 7  2011     1          7         5    1359    1509            AA       428
## 8  2011     1          8         6    1355    1454            AA       428
## 9  2011     1          9         7    1443    1554            AA       428
## 10 2011     1         10         1    1443    1553            AA       428
## ..  ...   ...        ...       ...     ...     ...           ...       ...
## Variables not shown: TailNum (chr), ActualElapsedTime (int), AirTime
##   (int), ArrDelay (int), DepDelay (int), Origin (chr), Dest (chr),
##   Distance (int), TaxiIn (int), TaxiOut (int), Cancelled (int),
##   CancellationCode (chr), Diverted (int)

Основные операции

dplyr предлагает пять основных операций для манипуляции данными применимые к отдельной таблице: filter(), arrange(), select(), mutate() and summarise(). Для тех кто пользовался до этого plyr многие из них будут знакомы.

Фильтрация строк при помощи filter()

filter() позволяет вам выбрать подмножество строк из data.frame. Первый аргумент – имя набора данных, второй и последующие – условия фильтра в контексте этого набора данных.

Например мы можем выбрать все вылет 1-го января следующим образом:

    filter(hflights_df, Month == 1, DayofMonth == 1)
## Source: local data frame [552 x 21]
## 
##    Year Month DayofMonth DayOfWeek DepTime ArrTime UniqueCarrier FlightNum
## 1  2011     1          1         6    1400    1500            AA       428
## 2  2011     1          1         6     728     840            AA       460
## 3  2011     1          1         6    1631    1736            AA      1121
## 4  2011     1          1         6    1756    2112            AA      1294
## 5  2011     1          1         6    1012    1347            AA      1700
## 6  2011     1          1         6    1211    1325            AA      1820
## 7  2011     1          1         6     557     906            AA      1994
## 8  2011     1          1         6    1824    2106            AS       731
## 9  2011     1          1         6     654    1124            B6       620
## 10 2011     1          1         6    1639    2110            B6       622
## ..  ...   ...        ...       ...     ...     ...           ...       ...
## Variables not shown: TailNum (chr), ActualElapsedTime (int), AirTime
##   (int), ArrDelay (int), DepDelay (int), Origin (chr), Dest (chr),
##   Distance (int), TaxiIn (int), TaxiOut (int), Cancelled (int),
##   CancellationCode (chr), Diverted (int)

Что будет эквивалентно более многословному (длиннее на целых 10 символов!) варианту:

    hflights[hflights$Month == 1 & hflights$DayofMonth == 1, ]

filter() работает аналогично subset() за тем исключением, что вы можете ему передать любое количество условий для фильтра, которые будут объединены вместе через & (логическое И, но не && с которым можно случайно перепутать). Вы можете также использовать любы другие логически связки:

    filter(hflights_df, Month == 1 | Month == 2)

Упорядочивание строк при помощи arrange()

arrange(), в свою очередь, работает аналогично subset() за исключением того, что вместо выбора строк она переупорядочивает их. Функция получает на вход имя набора данных и список имён колонок (или более сложное выражение) для упорядочивания по ним. Если будет указано больше одной колонки, то каждая следующая колонка будет упорядочиваться в пределах каждого отдельного набора значений предыдущих:

    arrange(hflights_df, DayofMonth, Month, Year)
## Source: local data frame [227,496 x 21]
## 
##    Year Month DayofMonth DayOfWeek DepTime ArrTime UniqueCarrier FlightNum
## 1  2011     1          1         6    1400    1500            AA       428
## 2  2011     1          1         6     728     840            AA       460
## 3  2011     1          1         6    1631    1736            AA      1121
## 4  2011     1          1         6    1756    2112            AA      1294
## 5  2011     1          1         6    1012    1347            AA      1700
## 6  2011     1          1         6    1211    1325            AA      1820
## 7  2011     1          1         6     557     906            AA      1994
## 8  2011     1          1         6    1824    2106            AS       731
## 9  2011     1          1         6     654    1124            B6       620
## 10 2011     1          1         6    1639    2110            B6       622
## ..  ...   ...        ...       ...     ...     ...           ...       ...
## Variables not shown: TailNum (chr), ActualElapsedTime (int), AirTime
##   (int), ArrDelay (int), DepDelay (int), Origin (chr), Dest (chr),
##   Distance (int), TaxiIn (int), TaxiOut (int), Cancelled (int),
##   CancellationCode (chr), Diverted (int)

Необходимо использовать desc() чтобы задать обратный порядок:

    arrange(hflights_df, desc(ArrDelay))
## Source: local data frame [227,496 x 21]
## 
##    Year Month DayofMonth DayOfWeek DepTime ArrTime UniqueCarrier FlightNum
## 1  2011    12         12         1     650     808            AA      1740
## 2  2011     8          1         1     156     452            CO         1
## 3  2011    11          8         2     721     948            MQ      3786
## 4  2011     6         21         2    2334     124            UA       855
## 5  2011     5         20         5     858    1027            MQ      3328
## 6  2011     6          9         4    2029    2243            MQ      3859
## 7  2011     1         20         4     635     807            CO        59
## 8  2011     6         22         3     908    1040            CO       595
## 9  2011    12         13         2     706     824            MQ      3328
## 10 2011    10         25         2    2310     149            DL      1215
## ..  ...   ...        ...       ...     ...     ...           ...       ...
## Variables not shown: TailNum (chr), ActualElapsedTime (int), AirTime
##   (int), ArrDelay (int), DepDelay (int), Origin (chr), Dest (chr),
##   Distance (int), TaxiIn (int), TaxiOut (int), Cancelled (int),
##   CancellationCode (chr), Diverted (int)

dplyr::arrange() работает так же как и plyr::arrange(). Это простая обёртка над order(), только позволяющая меньше набирать на клавиатуре. Предыдущий пример эквивалентен такому выражению:

    hflights[order(hflights$DayofMonth, hflights$Month, hflights$Year), ]
    hflights[order(desc(hflights$ArrDelay)), ]

Выбор колонок при помощи select()

Часто случается что при работе с большим набором данных вам на самом деле интересны только некоторые колонки. select() позволяет вам быстро сфокусироваться на интересующей части колонок, используя при этом символические имена на манер номеров колонок:

    # Выбор колонки по имени
    select(hflights_df, Year, Month, DayOfWeek)
## Source: local data frame [227,496 x 3]
## 
##    Year Month DayOfWeek
## 1  2011     1         6
## 2  2011     1         7
## 3  2011     1         1
## 4  2011     1         2
## 5  2011     1         3
## 6  2011     1         4
## 7  2011     1         5
## 8  2011     1         6
## 9  2011     1         7
## 10 2011     1         1
## ..  ...   ...       ...
    # Выбор всех колонок между Year и DayOfWeek (включительно)
    select(hflights_df, Year:DayOfWeek)
## Source: local data frame [227,496 x 4]
## 
##    Year Month DayofMonth DayOfWeek
## 1  2011     1          1         6
## 2  2011     1          2         7
## 3  2011     1          3         1
## 4  2011     1          4         2
## 5  2011     1          5         3
## 6  2011     1          6         4
## 7  2011     1          7         5
## 8  2011     1          8         6
## 9  2011     1          9         7
## 10 2011     1         10         1
## ..  ...   ...        ...       ...
    # Выбор всех колонок за исключением тех что между Year и DayOfWeek (включительно)
    select(hflights_df, -(Year:DayOfWeek))
## Source: local data frame [227,496 x 17]
## 
##    DepTime ArrTime UniqueCarrier FlightNum TailNum ActualElapsedTime
## 1     1400    1500            AA       428  N576AA                60
## 2     1401    1501            AA       428  N557AA                60
## 3     1352    1502            AA       428  N541AA                70
## 4     1403    1513            AA       428  N403AA                70
## 5     1405    1507            AA       428  N492AA                62
## 6     1359    1503            AA       428  N262AA                64
## 7     1359    1509            AA       428  N493AA                70
## 8     1355    1454            AA       428  N477AA                59
## 9     1443    1554            AA       428  N476AA                71
## 10    1443    1553            AA       428  N504AA                70
## ..     ...     ...           ...       ...     ...               ...
## Variables not shown: AirTime (int), ArrDelay (int), DepDelay (int), Origin
##   (chr), Dest (chr), Distance (int), TaxiIn (int), TaxiOut (int),
##   Cancelled (int), CancellationCode (chr), Diverted (int)

Эта функция работает подобно base::subset(). Отдельная функция добавлена для поддержания стройности идеологии dplyr, заключающейся в наличии функций каждая из которых делает только одну конкретную операцию и наиболее подходящим образом.

Создание новых колонок при помощи mutate()

Бывает полезно не только выбрать интересующие колонки, но и вычислить на их основании значения некоторой другой колонки. Для этих целей предназначена mutate():

mutate(hflights_df,
  gain = ArrDelay - DepDelay,
  speed = Distance / AirTime * 60)
## Source: local data frame [227,496 x 23]
## 
##    Year Month DayofMonth DayOfWeek DepTime ArrTime UniqueCarrier FlightNum
## 1  2011     1          1         6    1400    1500            AA       428
## 2  2011     1          2         7    1401    1501            AA       428
## 3  2011     1          3         1    1352    1502            AA       428
## 4  2011     1          4         2    1403    1513            AA       428
## 5  2011     1          5         3    1405    1507            AA       428
## 6  2011     1          6         4    1359    1503            AA       428
## 7  2011     1          7         5    1359    1509            AA       428
## 8  2011     1          8         6    1355    1454            AA       428
## 9  2011     1          9         7    1443    1554            AA       428
## 10 2011     1         10         1    1443    1553            AA       428
## ..  ...   ...        ...       ...     ...     ...           ...       ...
## Variables not shown: TailNum (chr), ActualElapsedTime (int), AirTime
##   (int), ArrDelay (int), DepDelay (int), Origin (chr), Dest (chr),
##   Distance (int), TaxiIn (int), TaxiOut (int), Cancelled (int),
##   CancellationCode (chr), Diverted (int), gain (int), speed (dbl)

dplyr::mutate() работает аналогично plyr::mutate() и аналогично base::transform(). Главное отличие между mutate() and transform() в том что первая может ссылаться в вычислениях на колонку которая создаётся в рамках того же вызова функции:

mutate(hflights_df,
  gain = ArrDelay - DepDelay,
  gain_per_hour = gain / (AirTime / 60)
)
## Source: local data frame [227,496 x 23]
## 
##    Year Month DayofMonth DayOfWeek DepTime ArrTime UniqueCarrier FlightNum
## 1  2011     1          1         6    1400    1500            AA       428
## 2  2011     1          2         7    1401    1501            AA       428
## 3  2011     1          3         1    1352    1502            AA       428
## 4  2011     1          4         2    1403    1513            AA       428
## 5  2011     1          5         3    1405    1507            AA       428
## 6  2011     1          6         4    1359    1503            AA       428
## 7  2011     1          7         5    1359    1509            AA       428
## 8  2011     1          8         6    1355    1454            AA       428
## 9  2011     1          9         7    1443    1554            AA       428
## 10 2011     1         10         1    1443    1553            AA       428
## ..  ...   ...        ...       ...     ...     ...           ...       ...
## Variables not shown: TailNum (chr), ActualElapsedTime (int), AirTime
##   (int), ArrDelay (int), DepDelay (int), Origin (chr), Dest (chr),
##   Distance (int), TaxiIn (int), TaxiOut (int), Cancelled (int),
##   CancellationCode (chr), Diverted (int), gain (int), gain_per_hour (dbl)
transform(hflights,
  gain = ArrDelay - DepDelay,
  gain_per_hour = gain / (AirTime / 60)
)
#> Error: object 'gain' not found

Вычисление итогов при помощи summarise()

Последняя рассматриваемая операция – summarise(), она просто сворачивает данные набора в одну колонку. Пока это не слишком полезно:

summarise(hflights_df,
  delay = mean(DepDelay, na.rm = TRUE))
## Source: local data frame [1 x 1]
## 
##   delay
## 1 9.445

Такое поведение в точности эквивалентно поведению plyr::summarise().

Итог

У вас может возникнуть впечатление что все перечисленные функции имеют что-то общее:

  • Первый аргумент – data.frame.
  • Последующие аргументы описываю то что вы хотите проделать с первым, и вы можете обращаться к атрибутам первого аргумента по именам, не используя для доступа $.
  • Возвращаемый результат – новый data.frame.

Все эти свойства вместе позволяют легко комбинировать множество вызовов в одну цепочку для вычисления сложного результата.

Эти пять функций создают основу для языка манипулирования данными. На самом простом уровне вы можете только изменить что-либо в наборе данных пятью способами: изменить порядок строк (arrange()), выбрать наблюдения или атрибуты (filter() и select()), добавить вычисляемые атрибуты (mutate()) или свернуть набор в итог (summarise()). Оставшаяся часть этого языка образуется из применения перечисленных функций к различным типам данных, например группированным данным, как описано ниже.

Операции группировки

Вышеописанные функции полезны сами по себе, но особую мощь они приобретают в комбинации с концепцией (нет, не коллективной безопасности (: ) группировки, повторения вычислений для каждой группы наблюдений в отдельности. В dplyr используется функция group_by() для разбиения набора данных на части по строкам. Вы можете использовать вывод функции group_by() непосредственно как первый аргумент перечисленных выше пяти основных функций, они сами обработают правильно разбитый на группы набор данных.

Из функций в предыдущем разделе select() не реагирует на то что его первый аргумент сгруппирован, arrange() просто ведёт себя так, как будто его вторым аргументом указанны атрибуты по которым сгруппирован первый аргумент. Погруппные mutate() и filter() наиболее полезны в совокупности с функциями агрегирования по окну*, но это описано в отдельном руководстве (vignette()). summarise() в данном случае весьма полезна и проста в применении как будет более детально показано далее.

В следующем примере мы разделим набор данных по самолётам и рассчитаем количество вылетов (count = n()) и средние дальность полета (dist = mean(Distance, na.rm = TRUE)) и задержку вылета (delay = mean(ArrDelay, na.rm = TRUE)). Затем построим график при помощи ggplot2.

planes <- group_by(hflights_df, TailNum)
delay <- summarise(planes,
  count = n(),
  dist = mean(Distance, na.rm = TRUE),
  delay = mean(ArrDelay, na.rm = TRUE))
delay <- filter(delay, count > 20, dist < 2000)

# Интересно, на сколько зависит 
# задержка от дальности полёта 
ggplot(delay, aes(dist, delay)) +
  geom_point(aes(size = count), alpha = 1/2) +
  geom_smooth() +
  scale_size_area()

plot of chunk pic14

Вы использовали summarise() с функциями агрегирования, получающими вектор значений и возвращающими скалярное значение. Множество таких функций есть в базовой среде R, например min(), max(), mean(), sum(), sd(), median() и IQR(). dplyr предлагает ещё несколько полезных:

Например, мы можем использовать их чтобы найти номера самолётов и количество вылетов во все возможные пункты назначения:

    destinations <- group_by(hflights_df, Dest)
    summarise(destinations,
      planes = n_distinct(TailNum),
      flights = n()
    )
## Source: local data frame [116 x 3]
## 
##    Dest planes flights
## 1   ABQ    716    2812
## 2   AEX    215     724
## 3   AGS      1       1
## 4   AMA    158    1297
## 5   ANC     38     125
## 6   ASE     60     125
## 7   ATL    983    7886
## 8   AUS   1015    5022
## 9   AVL    142     350
## 10  BFL     70     504
## ..  ...    ...     ...

Также вы можете применить собственную функцию. Для повышения производительности многие функции dplyr написаны на C++. Если вы хотите использовать собственную функцию на C++ обратите внимание на соответствующее руководство* для уточнения деталей.

При группировке по нескольким переменным вы можете также получить “послойные” итоги для каждого уровня в отдельности и по очереди. Этот приём позволяет кумулятивно получать свёртку набора данных:

    daily <- group_by(hflights_df, Year, Month, DayofMonth)
    (per_day   <- summarise(daily, flights = n()))
## Source: local data frame [365 x 4]
## Groups: Year, Month
## 
##    Year Month DayofMonth flights
## 1  2011     1          1     552
## 2  2011     1          2     678
## 3  2011     1          3     702
## 4  2011     1          4     583
## 5  2011     1          5     590
## 6  2011     1          6     660
## 7  2011     1          7     661
## 8  2011     1          8     500
## 9  2011     1          9     602
## 10 2011     1         10     659
## ..  ...   ...        ...     ...
    (per_month <- summarise(per_day, flights = sum(flights)))
## Source: local data frame [12 x 3]
## Groups: Year
## 
##    Year Month flights
## 1  2011     1   18910
## 2  2011     2   17128
## 3  2011     3   19470
## 4  2011     4   18593
## 5  2011     5   19172
## 6  2011     6   19600
## 7  2011     7   20548
## 8  2011     8   20176
## 9  2011     9   18065
## 10 2011    10   18696
## 11 2011    11   18021
## 12 2011    12   19117
    (per_year  <- summarise(per_month, flights = sum(flights)))
## Source: local data frame [1 x 2]
## 
##   Year flights
## 1 2011  227496

Однако необходимо проявлять осторожность при таком методе получения итогов: он подойдёт для сумм и количеств, но нужно задуматься при использовании средних и дисперсий, и уж точно не применять с медианой.

Последовательные манипуляции

API (тот самый мощный ЭПиАй) dplyr функционален, в том смысле, что вызовы функций не имеют побочных эффектов, и вы должны сами сохранять результаты. Это обстоятельство не способствует написанию элегантного кода если вам нужно выполнить множество операций подряд. Вы, конечно, можете выполнять их шаг за шагом:

    a1 <- group_by(hflights, Year, Month, DayofMonth)
    a2 <- select(a1, Year:DayofMonth, ArrDelay, DepDelay)
    a3 <- summarise(a2,
      arr = mean(ArrDelay, na.rm = TRUE),
      dep = mean(DepDelay, na.rm = TRUE))
    a4 <- filter(a3, arr > 30 | dep > 30)

Или, если вы не желаете сохранять промежуточные результаты, можно передавать вызовы функций как аргументы, вкладывая один в другой:

    filter(
      summarise(
        select(
          group_by(hflights, Year, Month, DayofMonth),
          Year:DayofMonth, ArrDelay, DepDelay
        ),
        arr = mean(ArrDelay, na.rm = TRUE),
        dep = mean(DepDelay, na.rm = TRUE)
      ),
      arr > 30 | dep > 30
    )
## Source: local data frame [14 x 5]
## Groups: Year, Month
## 
##    Year Month DayofMonth   arr   dep
## 1  2011     2          4 44.08 47.17
## 2  2011     3          3 35.13 38.20
## 3  2011     3         14 46.64 36.14
## 4  2011     4          4 38.72 27.95
## 5  2011     4         25 37.80 22.26
## 6  2011     5         12 69.52 64.52
## 7  2011     5         20 37.03 26.55
## 8  2011     6         22 65.52 62.31
## 9  2011     7         29 29.56 31.87
## 10 2011     9         29 39.20 32.50
## 11 2011    10          9 61.90 59.53
## 12 2011    11         15 43.68 39.23
## 13 2011    12         29 26.30 30.79
## 14 2011    12         31 46.48 54.17

Что создаёт сложности с чтением, так как порядок выполнения начинается из середины выражения и аргументы отдаляются от текста вызова функции. Чтобы обойти это проблему dplyr использует оператор %>%. x %>% f(y) преобразуется в f(x, y), что можно использовать для преобразования кода вызовов в удобный для чтения слева направо, сверху вниз:

    hflights %>%
      group_by(Year, Month, DayofMonth) %>%
      select(Year:DayofMonth, ArrDelay, DepDelay) %>%
      summarise(
        arr = mean(ArrDelay, na.rm = TRUE),
        dep = mean(DepDelay, na.rm = TRUE)
      ) %>%
      filter(arr > 30 | dep > 30)
## Source: local data frame [14 x 5]
## Groups: Year, Month
## 
##    Year Month DayofMonth   arr   dep
## 1  2011     2          4 44.08 47.17
## 2  2011     3          3 35.13 38.20
## 3  2011     3         14 46.64 36.14
## 4  2011     4          4 38.72 27.95
## 5  2011     4         25 37.80 22.26
## 6  2011     5         12 69.52 64.52
## 7  2011     5         20 37.03 26.55
## 8  2011     6         22 65.52 62.31
## 9  2011     7         29 29.56 31.87
## 10 2011     9         29 39.20 32.50
## 11 2011    10          9 61.90 59.53
## 12 2011    11         15 43.68 39.23
## 13 2011    12         29 26.30 30.79
## 14 2011    12         31 46.48 54.17

Другие источники данных

Также как с data.frame, dplyr может работать с данными представленными другими способами, такими как data tables, базы данных и многомерные массивы.

Data tables

dplyr также предлагает все перечисленные методы манипулирования данным и для объектов типа data.tables, вы просто должны заменить набор данных на data.table.

data.table может оказаться быстрее во многих случаях, потому что возможно выполнение нескольких операций одновременно. Например, вы можете выполнить mutate и select за один вызов, и data.table сообразит что нет нужды рассчитывать новую переменную в строках которые должны быть отфильтрованы.

Преимущества при использовании data.tables следующие:

  • В большинстве случаев data.tables изолирует вас от данных непосредственно, и защищает их таким образом от непреднамеренного изменения.
  • Вместо изощрённого использования встроенного оператора [, предлагается множество относительно простых методов.

Базы данных

dplyr позволяет использовать удалённые базы данных так же как data.frame. Избавляя таким образом от необходимости постоянно переключать мышление между языками. Для уточнения деталей необходимо обратиться к соответствующему руководству*.

В сравнении с другим вариантами использования баз данных:

  • скрывается, на сколько это возможно, факт использования удалённой базы данных
  • исчезает необходимость изучать какой-либо диалект sql (хотя это может быть полезно!)
  • предоставляется прослойка между множеством различных реализаций интерфейсов баз данных.

Многомерные массивы/кубы

tbl_cube() предлагает экспериментальный интерфейс к многомерным массивам или кубам (как OLAP-кубы) . Если вы используете подобное представление в R, пожалуйста, свяжитесь с автором чтобы он лучше понял ваши потребности.

Сравнение с другими подходами

В сравнение со всеми существующими альтернативами, dplyr:

В сравнении с функциями из основной поставки:

В сравнении с plyr:

В сравнении с использованием виртуальных data.frame: