2016-08-30 6 views
6

Mam dataframe pandy, która wygląda tak:Pandy: Usuń wiersze na podstawie innych wierszy

qseqid sseqid qstart qend 
2   1  125  345 
4   1  150  320 
3   2  150  450 
6   2  25  300 
8   2  50  500 

Chciałbym usunąć wiersze na podstawie innych wierszy wartości z tych criterias: wiersz (R1) musi być usunięty, jeśli istnieje inny wiersz (r2) z tymi samymi sseqid i r1[qstart] > r2[qstart] i .

Czy to możliwe w przypadku pand?

Odpowiedz

7
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'] > merged['qstart_y']) 
      & (merged['qend_x'] < 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) 

daje

qend qseqid qstart sseqid 
0 345  2  125  1 
3 300  6  25  2 
4 500  8  50  2 

Idea jest użycie pd.merge celu utworzenia DataFrame z każdym parowania rzędów z samym sseqid:

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 

każdy rząd połączonego zawiera dane z dwóch rzędów df. Następnie można porównać co dwa rzędy za pomocą

mask = ((merged['qstart_x'] > merged['qstart_y']) 
     & (merged['qend_x'] < merged['qend_y'])) 

i znaleźć etykiety w df.index które nie pasują do tego warunku:

df_mask = ~df.index.isin(merged.loc[mask, 'index'].values) 

i wybierz te wiersze:

result = df.loc[df_mask] 

pamiętać, że ta zakłada, że ​​df ma unikalny indeks.

+0

@unutbu - jest to doskonała myśl o połączeniu 'df.reset_index()' i 'df' :-) – Anzel

+0

To jest niesamowite! Wielkie dzięki :) – jsgounot