Похоже, что это перекрестное соединение с условиями фильтрации. Если вы в data.table
, посмотрите на неэквивалентные объединения.
Это не на 100% идентично, идентификаторы, которые не имеют соответствующих критериев, не переносятся Это легко исправить с помощью anti_join и bind_rows.
Ваш метод занял ~ 20 секунд на моем компьютере. Этот метод занимает около 1 секунды.
df%>%
inner_join(df, by = 'area')%>%
filter(date.y < date.x
, date.y >= date.x - 100)%>%
group_by(id.x, broker.x, date.x, area)%>%
summarize(n_area_date = n()
, sum_broker = sum(broker.y)
, p_broker = sum_broker / n_area_date)
Редактировать: Вот решение data.table. Это делается за 140 миллисекунд - почти в 150 раз быстрее, чем оригинал, и примерно в 6 раз быстрее, чем соединение dplyr без равенства.
dt[, .(area, date, broker)
][dt[, .(area, date, l_date = date - 100, id, broker)]
,on = .(area = area
, date < date
, date >= l_date)
, .(id, i.broker, i.date, i.area, x.broker)
, allow.cartesian = T
][, .(n_area_date = .N
, sum_broker = sum(x.broker)
, p_broker = sum(x.broker) / .N)
, by = .(id, i.broker, i.date, i.area)]
Производительность:
Unit: milliseconds
expr min lq mean median uq max neval
dplyr_non_equi_join 781.3828 802.5404 837.2033 810.3655 847.3634 1032.001 10
dt_non_equi 121.0912 125.1777 137.7371 138.7682 141.9835 175.763 10
original 19986.1950 20047.2880 20356.4174 20160.2137 20900.4362 21097.170 10