Q:

efficiency in a row-wise for loop and implementation with purrr

I'm filtering a data frame by a different sub-set for each row, based on relation to observation i. specifically, taking observations that it's dates are certain amount of days before the data of observation i. 
Solved it with a for-loop,  but didn't find implementation with purrr. It seems that row-wise solutions posts handle simpler problems.   
1.is there any solution with purrr?
2.can the code be more efficient?   
i've sloved the problem with a for-loop and with parallel computation using package foreach.
the data is as follows:
each row is a loan with rich information (240k observations). some of the borrowers get the aid of a broker. 
i'm counting in each statistical geographic zone, the proportion of brokered loans in the 100 days prior to each observation. 
(this proportion is going to be an instrument for selection bias problem of choosing a broker) 
# define a toy data ----
n <- 10000
df <- data.frame(id = 1:n,
                 broker = rbinom(n,1,0.4) ,
                 date = Sys.Date() + sample(n/100, n, replace = T) ,
                 area = sample(n/200, n, replace = T))
# going parallel ====
# load packages ----
library(tidyverse)
library(parallel)
library(doSNOW) # working on windows platform
library(foreach)
library(progress)
# define cluster ----
n_cores <- detectCores()
cl <- makeCluster(n_cores - 1)
registerDoSNOW(cl)
# define progress bar ----
pb <- txtProgressBar(min=1, max=n/100, style=3)
progress <- function(n) setTxtProgressBar(pb, n)
opts <- list(progress=progress)
# calculate IV variable - count how many times brokered loan appear in borower's statistical zone in the previous 100 days ----
t_par <- Sys.time() # record start time
# to make things more efficient, split the data to small chunks by statistic area 
a <- df %>% split(df$area) 
# nested forloop - the outer loop is parallel, the inner is serial. 
d <- foreach(j = seq_along(a),.packages = "tidyverse",.options.snow=opts) %dopar% {
   setTxtProgressBar(pb, j)
# empty temporary data frame   
   y <- data.frame(n_area_date = numeric(length(nrow(a[[j]]))), 
                   sum_broker = numeric(length(nrow(a[[j]]))),
                   p_broker = numeric(length(nrow(a[[j]]))))
# the inner loop   
   for(i in 1:nrow(a[[j]])){
      y[i,] <-  a[[j]] %>% filter( date < a[[j]][i, "date"],
                                   date >=  a[[j]][i, "date"] -100 ) %>%
         summarise( n_area_date = n(),
                    sum_broker = sum(broker),
                    p_broker = sum_broker / n_area_date)
   }
   cbind(a[[j]], y)
}
# turn result back into a data.frame
e <- map_df(d, rbind) 
(t_par <- Sys.time() - t_par)
# closing ----
stopCluster(cl)

the result on a strong computer is time-wise satisfactory.
yet, the code is not as readable as i would like. many a times, purrr did allow me to write more elegant and efficient code. is this a case to keep with for-loop?

A:

This appears to be a cross join with filtering conditions. If you're into data.table, look into non-equi joins. 
This isn't 100% identical, ids which did not have matching criteria are not carried forward. That is easily remedied with an anti_join and bind_rows.
Your method took ~20 seconds on my computer. This method takes around 1 second.
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)

Edit: Here's the data.table solution. It's done in 140 milliseconds - almost 150x faster than the original and around 6x faster than dplyr non-equi join.
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)]

Performance:
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

