title: Filter a dataframe column based on values in a second column being within a tolerance value of any rows in a second dataframe
body: <p>I am dealing with experimental measurements of time-correlated gamma-ray emissions with a pair of detectors. I have a long-form dataframe which lists every gamma-ray detected and displays its energy, the timestamp of the event, and the detector channel. Here is the sample structure of this dataframe:</p>
  
  <pre><code>df
      Energy  Timestamp       Channel
  0   639     753437128196030 1
  1   798     753437128196010 2
  2   314     753437131148580 1
  3   593     753437131148510 2
  4   2341    753437133607800 1
  </code></pre>
  
  <p>I must filter these data and according to the following conditions:
  Return the energies of all events detected in Channel 1 which occur within one user-selectable <code>timing_window</code> of events detected in Channel 2.
  Furthermore, only the events in Channel 2 that are within the energy range <code>[E_lo, E_hi]</code> should be considered when evaluating the timing window conditions.</p>
  
  <p>So far, I have tried the following:</p>
  
  <p>Separate the energy data of each detector into individual dataframes:</p>
  
  <pre><code>d1_all = df[(df["Channel"] == 1)]
  d2_all = df[(df["Channel"] == 2)]
  </code></pre>
  
  <p>Reset the indices of <code>d1_all</code>:</p>
  
  <pre><code>d1_all = d1_all.reset_index()
  d1_all = d1_all.drop(['index'], axis=1)
  d1_all.head()
  </code></pre>
  
  <p>Retain only the events in <code>d2_all</code> which occur in the range <code>[E_lo=300, E_hi=600]</code></p>
  
  <pre><code>d2_gate = d2_all[(d2_all["Energy"] &gt;= 300) &amp; (d2_all["Energy"] &lt;=600)]
  </code></pre>
  
  <p>Reset the indices of <code>d2_all</code>:</p>
  
  <pre><code>d2_gate = d2_gate.reset_index()
  d2_gate = d2_gate.drop(['index'], axis=1)
  d2_gate.head()
  </code></pre>
  
  <p><em>Everything up to this point works fine.</em> <strong>Here is the biggest problem.</strong> The following code evaluates each event in detector 1 to determine if its timestamp is within one <code>timing_window</code> of the timestamp corresponding to ANY event within the energy range E_lo to E_hi in detector 2. The problem is that this dataframe can have on the order of 10's to 100's of thousands of entries for each detector, and the current code takes essentially forever to run. This code uses nested <code>for</code> loops.</p>
  
  <pre><code>for i in range(0, d1_all.shape[0]):
      coincidence = False
      for j in range(0, d2_gate.shape[0]):
          if ((d1_all.iloc[i]["Timestamp"]) &gt;= 
              (d2_gate.iloc[j]["Timestamp"] - coin_window)) and ((d1_all.iloc[i] 
              ["Timestamp"]) &lt;= (d2_gate.iloc[j]["Timestamp"] + coin_window)):
              coincidence = True
              break
          else:
              pass
      if coincidence == True:
          pass
      elif coincidence == False:
          d1_all = d1_all.drop([i])
  </code></pre>
  
  <p>Any help identifying a faster implementation of evaluating for coincidences would be greatly appreciated! Thank you!</p>