-2

Let's assume that I want to do something within groups, for example extract first row from each group. With tidyverse and iris dataset it's rather easy:

iris %>% 
  group_by(Species) %>% 
  nest() %>% 
  mutate(first_within_group = map(data, ~head(.x, 1))) %>% 
  select(-data) %>% 
  unnest()

However, with bigger datasets I strike on performance issues. Is there an alternative for group_by() + nest() that would be more efficient in terms of speed? Is the performance dependent on number of factors inside group_by()?

jakes
  • 1,964
  • 3
  • 18
  • 50

2 Answers2

1

the data.tableway

library( data.table )
dt <- as.data.table( iris )
dt[ dt[, .I[1], Species ]$V1]

benchmark

   microbenchmark::microbenchmark( data.table = dt[ dt[, .I[1], Species ]$V1],
                                slice = iris %>% group_by(Species) %>% slice(1),
                                nest = {iris %>% 
                                    group_by(Species) %>% 
                                    nest() %>% 
                                    mutate(first_within_group = map(data, ~head(.x, 1))) %>% 
                                    select(-data) %>% 
                                    unnest()})

# Unit: microseconds
#       expr      min        lq      mean    median        uq       max neval
# data.table  622.111  680.7065  758.0381  737.7965  814.4675  1102.024   100
#      slice 1004.717 1049.1530 1110.7793 1080.7855 1161.8255  1365.028   100
#       nest 8455.281 8786.2190 9335.8634 8976.4675 9454.4230 28383.302   100
Wimpel
  • 26,031
  • 1
  • 20
  • 37
0

Using slice

iris %>% group_by(Species) %>% slice(1)

Using data.table

library(data.table)
irisDT = as.data.table(iris)
irisDT[ ,.SD[1], by = Species]

Benchmark

 expr        min        lq      mean    median       uq       max neval
  map   8024.127 8274.1645 9048.5633 8625.7005 9254.004 12900.339   100
  slice  943.808  986.0910 1274.0415 1082.6330 1428.091  4274.758   100
  dt[]   657.492  701.5495  847.3838  757.3865  780.738  4405.899   100
JRR
  • 3,024
  • 2
  • 13
  • 37