2014-04-25 17 views
6

L'operazione che voglio fare è simile alla fusione. Ad esempio, con la fusione inner otteniamo un frame di dati che contiene le righe presenti nel primo e secondo frame di dati. Con la fusione outer otteniamo un frame di dati che è presente EITHER nel primo OR nel secondo frame di dati.Come sottrarre le righe di un frame dati di un panda da un altro?

Quello che mi serve è un frame di dati che contenga righe presenti nel primo frame di dati E NON presenti nel secondo? C'è un modo veloce ed elegante per farlo?

+0

how = 'left'? sicuramente questo non è quello che vuoi (dato il tuo punteggio SO deve essere più complesso di quello) –

+0

L'unione sinistra o destra mi dà un frame di dati che contiene le righe che sono presenti in uno dei frame di dati. Ma ho bisogno di un frame di dati che contenga righe presenti in un frame di dati E NON presenti in un altro. – Roman

+0

Se si tratta di una sola chiave di fusione, è possibile farlo con 'isin' e' ~ ' –

risposta

6

Che ne dici di qualcosa come il seguente?

print df1 

    Team Year foo 
0 Hawks 2001 5 
1 Hawks 2004 4 
2 Nets 1987 3 
3 Nets 1988 6 
4 Nets 2001 8 
5 Nets 2000 10 
6 Heat 2004 6 
7 Pacers 2003 12 

print df2 

    Team Year foo 
0 Pacers 2003 12 
1 Heat 2004 6 
2 Nets 1988 6 

Finché v'è un non-chiave comunemente denominata colonna, è possibile lasciare che il aggiunto sufffexes fare il lavoro (se non ci sono colonne comuni non chiave allora si potrebbe creare uno da utilizzare temporaneamente .. . df1['common'] = 1 e df2['common'] = 1):

new = df1.merge(df2,on=['Team','Year'],how='left') 
print new[new.foo_y.isnull()] 

    Team Year foo_x foo_y 
0 Hawks 2001  5 NaN 
1 Hawks 2004  4 NaN 
2 Nets 1987  3 NaN 
4 Nets 2001  8 NaN 
5 Nets 2000  10 NaN 

Oppure si può utilizzare isin ma si dovrà creare un unico tasto:

df1['key'] = df1['Team'] + df1['Year'].astype(str) 
df2['key'] = df1['Team'] + df2['Year'].astype(str) 
print df1[~df1.key.isin(df2.key)] 

    Team Year foo   key 
0 Hawks 2001 5 Hawks2001 
2 Nets 1987 3 Nets1987 
4 Nets 2001 8 Nets2001 
5 Nets 2000 10 Nets2000 
6 Heat 2004 6 Heat2004 
7 Pacers 2003 12 Pacers2003 
4

si potrebbe incorrere in e rrors se la colonna non indicizzata contiene celle con NaN.

print df1 

    Team Year foo 
0 Hawks 2001 5 
1 Hawks 2004 4 
2 Nets 1987 3 
3 Nets 1988 6 
4 Nets 2001 8 
5 Nets 2000 10 
6 Heat 2004 6 
7 Pacers 2003 12 
8 Problem 2112 NaN 


print df2 

    Team Year foo 
0 Pacers 2003 12 
1 Heat 2004 6 
2 Nets 1988 6 
3 Problem 2112 NaN 

new = df1.merge(df2,on=['Team','Year'],how='left') 
print new[new.foo_y.isnull()] 

    Team Year foo_x foo_y 
0 Hawks 2001  5 NaN 
1 Hawks 2004  4 NaN 
2 Nets 1987  3 NaN 
4 Nets 2001  8 NaN 
5 Nets 2000  10 NaN 
6 Problem 2112 NaN NaN 

Il team di problemi nel 2112 non ha alcun valore per foo in nessuna tabella. Quindi, il join sinistro qui restituirà erroneamente quella riga, che corrisponde in entrambi i DataFrames, in quanto non presente nel DataFrame corretto.

Soluzione:

Quello che faccio è quello di aggiungere una colonna unica per il dataframe interno ed impostare un valore per tutte le righe. Quindi quando ti unisci, puoi verificare se quella colonna è NaN per la tabella interna per trovare i record univoci nella tabella esterna.

df2['in_df2']='yes' 

print df2 

    Team Year foo in_df2 
0 Pacers 2003 12  yes 
1 Heat 2004 6  yes 
2 Nets 1988 6  yes 
3 Problem 2112 NaN  yes 


new = df1.merge(df2,on=['Team','Year'],how='left') 
print new[new.in_df2.isnull()] 

    Team Year foo_x foo_y in_df1 in_df2 
0 Hawks 2001  5 NaN  yes  NaN 
1 Hawks 2004  4 NaN  yes  NaN 
2 Nets 1987  3 NaN  yes  NaN 
4 Nets 2001  8 NaN  yes  NaN 
5 Nets 2000  10 NaN  yes  NaN 

NB. La riga del problema è ora filtrata correttamente, perché ha un valore per in_df2.

Problem 2112 NaN NaN  yes  yes 
+0

Eccellente, questo ha funzionato bene per me. – Dirk

3

Considerare a seguire:

  1. df_one è il primo dataframe
  2. df_two è seconda dataframe

Presente in Prima dataframe e Non in Second dataframe

Soluzione: da Indice df = df_one[~df_one.index.isin(df_two.index)]

indice può essere sostituito da richiesta colonna su cui si desidera fare l'esclusione. Nell'esempio precedente, ho utilizzato l'indice come riferimento tra entrambi i datagrammi

Inoltre, è possibile utilizzare una query più complessa utilizzando i panda booleani.Serie da risolvere per sopra.

Problemi correlati