title: Extracting rows around patterns in R
body: <p>I have a data.frame <code>test</code> where I would like to identify what comes before and after a <code>bar</code> - <code>foo</code> pattern for each <code>id</code>.  The pattern must be consecutive by <code>timestamp</code></p>
  
  <p>For example, in the following sample there are <strong>three</strong> patterns of <code>bar</code> - <code>foo</code> that occur. </p>
  
  <pre><code>&gt; test
               timestamp id message   result
  1  2019-01-01 00:00:21  1     bar negative
  2  2019-01-01 00:00:58  1     bar positive
  3  2019-01-01 00:01:35  1     foo positive
  4  2019-01-01 00:03:02  1     bar negative
  5  2019-01-01 00:06:42  1     baz positive
  6  2019-01-01 00:07:16  1     baz positive
  7  2019-01-01 00:07:39  1     bar positive
  8  2019-01-01 00:09:14  2     bar negative
  9  2019-01-01 00:09:56  2     foo negative
  10 2019-01-01 00:10:56  2     foo positive
  11 2019-01-01 00:11:13  2     foo negative
  12 2019-01-01 00:11:32  2     foo positive
  13 2019-01-01 00:11:49  2     bar negative
  14 2019-01-01 00:12:18  2     foo positive
  15 2019-01-01 00:15:28  2     bar positive
  </code></pre>
  
  <p>As a result, the ideal output would look like this:</p>
  
  <pre><code>&gt; output
      before    after id
  1 negative negative  1
  2     &lt;NA&gt; positive  2
  3 positive positive  2
  </code></pre>
  
  <p>The code I've applied below <em>works</em> but seems convoluted and inefficient</p>
  
  <pre><code>test %&gt;%
              group_by(id) %&gt;%
              mutate(next.message = lead(message, order_by=timestamp),
                     previous.result = lag(result, order_by=timestamp),
                     next.result = lead(result, n = 2, order_by=timestamp)) %&gt;%
              filter(message == 'bar', next.message == 'foo')  %&gt;%
              filter_all(any_vars(!is.na(.))) %&gt;% 
              select (-c(timestamp, message, result, next.message)) %&gt;%
              rename(before = previous.result , after = next.result) 
  </code></pre>
  
  <p>What would be a better way to approach this problem using either <code>dplyr</code> or <code>data.table</code> functions? </p>
  
  <p>sample data: </p>
  
  <pre><code>dput(test)
  structure(list(timestamp = structure(c(1546318821, 1546318858, 
  1546318895, 1546318982, 1546319202, 1546319236, 1546319259, 1546319354, 
  1546319396, 1546319456, 1546319473, 1546319492, 1546319509, 1546319538, 
  1546319728), class = c("POSIXct", "POSIXt")), id = c(1, 1, 1, 
  1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2), message = c("bar", "bar", 
  "foo", "bar", "baz", "baz", "bar", "bar", "foo", "foo", "foo", 
  "foo", "bar", "foo", "bar"), result = c("negative", "positive", 
  "positive", "negative", "positive", "positive", "positive", "negative", 
  "negative", "positive", "negative", "positive", "negative", "positive", 
  "positive")), row.names = c(NA, -15L), class = "data.frame")
  </code></pre>