Pandas : Delete rows based on other rows
<p>I have a pandas dataframe which looks like that :</p>

<pre><code>qseqid  sseqid  qstart    qend
2         1     125       345
4         1     150       320
3         2     150       450
6         2     25        300
8         2     50        500
</code></pre>

<p>I would like to remove rows based on other rows values with these criterias : A row (r1) must be removed if another row (r2) exist with the same <code>sseqid</code> and <code>r1[qstart] &gt; r2[qstart]</code> and <code>r1[qend] &lt; r2[qend]</code>.</p>

<p>Is this possible with pandas ? </p>

<pre><code>df  = pd.DataFrame({'qend': [345, 320, 450, 300, 500],
 'qseqid': [2, 4, 3, 6, 8],
 'qstart': [125, 150, 150, 25, 50],
 'sseqid': [1, 1, 2, 2, 2]})

def remove_rows(df):
    merged = pd.merge(df.reset_index(), df, on='sseqid')
    mask = ((merged['qstart_x'] &gt; merged['qstart_y']) 
            &amp; (merged['qend_x'] &lt; merged['qend_y']))
    df_mask = ~df.index.isin(merged.loc[mask, 'index'].values)
    result = df.loc[df_mask]
    return result

result = remove_rows(df)
print(result)
</code></pre>

<p>yields</p>

<pre><code>   qend  qseqid  qstart  sseqid
0   345       2     125       1
3   300       6      25       2
4   500       8      50       2
</code></pre>

<hr>

<p>The idea is to use <code>pd.merge</code> to form a DataFrame with every pairing of rows
with the same <code>sseqid</code>:</p>

<pre><code>In [78]: pd.merge(df.reset_index(), df, on='sseqid')
Out[78]: 
    index  qend_x  qseqid_x  qstart_x  sseqid  qend_y  qseqid_y  qstart_y
0       0     345         2       125       1     345         2       125
1       0     345         2       125       1     320         4       150
2       1     320         4       150       1     345         2       125
3       1     320         4       150       1     320         4       150
4       2     450         3       150       2     450         3       150
5       2     450         3       150       2     300         6        25
6       2     450         3       150       2     500         8        50
7       3     300         6        25       2     450         3       150
8       3     300         6        25       2     300         6        25
9       3     300         6        25       2     500         8        50
10      4     500         8        50       2     450         3       150
11      4     500         8        50       2     300         6        25
12      4     500         8        50       2     500         8        50
</code></pre>

<p>Each row of merged contains data from two rows of df. You can then compare every two rows using</p>

<pre><code>mask = ((merged['qstart_x'] &gt; merged['qstart_y']) 
        &amp; (merged['qend_x'] &lt; merged['qend_y']))
</code></pre>

<p>and find the labels in <code>df.index</code> that do not match this condition:</p>

<pre><code>df_mask = ~df.index.isin(merged.loc[mask, 'index'].values)
</code></pre>

<p>and select those rows:</p>

<pre><code>result = df.loc[df_mask]
</code></pre>

<p>Note that this assumes <code>df</code> has a unique index. </p>

python pandas dataframe