2016-08-30 2 views
3

Ich kann nicht einen einfachen Weg finden, alle Zeilen eines Datenrahmens, die in einem Datenrahmen, aber nicht in einem zweiten Datenrahmen gefunden werden, wenn die Daten nicht geordnet sind.Pandas alle Zeilen in einem Datenrahmen, aber nicht die anderen gelisteten UNORDERD

Diese beiden Antworten Talk sind Lösungen für geordnete Daten:

Get rows that are present in one dataframe, but not the other

pandas get rows which are NOT in other dataframe

So einfach machen es klar, ich versuche, diese zu bekommen: data from one dataframe thats not found in the other dataframe

In einer der oben genannten verwandten Frage I Ich habe eine Multiindex-Lösung gefunden, die angeblich mit ungeordneten Daten arbeitet, aber ich konnte sie nicht implementieren. Ich hoffe, es gibt einen leichteren Weg.

lassen Sie mich Ihnen ein Beispiel für die Daten mit Ich arbeite:

DF1 
col_a col_b 
1325 foo 
1397 foo  #<---matching value, but not matching index in DF2 
1645 foo 
...  ... 

DF2 
col_1 col_2 
1397 foo  #<---matching value, but not matching index in DF1 
1500 foo 
1621 foo 
...  ... 

Nun, wenn das in den beiden Datenrahmen alle Daten waren das Ergebnis dieses für DF1 speziell für die Verarbeitung würde wie folgt aussehen:

DF1_UNIQUE 
col_a col_b 
1325 foo 
1645 foo 

(also wirklich nur ich die Sorge um col_a oder für DF2 col_1). Beachten Sie, dass die Zeile 1397 fehlt. Das liegt daran, dass es in DF2 gefunden wird, also möchte ich nicht, dass es zu meinem neuen DF zurückkehrt. Aber es ist nicht im selben Index gefunden und da liegt das Problem, das ich habe. Ich habe bereits eine Lösung leicht erstellt, wenn alle übereinstimmenden Indizes aufgereiht sind, aber ich weiß nicht, wo ich auf den nicht aufgereihten Indizes anfangen soll. Kann ich die Zusammenführungsfunktion verwenden? Oder ist das das falsche Werkzeug für diesen Job?

Dieser Code ist nicht ganz relevant, aber es ist die Lösung kam ich mit, wenn alle Indizes ausgekleidet richtig:

def getUniqueEntries(df1, df2): 
    """takes two dataframes, returns a dataframe that is comprized of all the rows unique to the first dataframe.""" 
    d1columns = df1.columns 
    d2columns = df2.columns 
    df3 = pd.merge(df1, df2, left_on=d1columns[0], right_on=d2columns[0]) 
    print(df3) 
    return df1[(~df1[d1columns[0]].isin(df3[d1columns[0]]))]  

def main(fileread1, fileread2, writeprefix): 
    df1 = pd.read_csv(fileread1) 
    df2 = pd.read_csv(fileread2) 

    df3 = getUniqueEntries(df1, df2) 
    df4 = getUniqueEntries(df2, df1) 

    print(df3) 
    print(df4) 

    df3.to_csv(writeprefix+fileread1, index=False) 
    df4.to_csv(writeprefix+fileread2, index=False) 

if __name__ == '__main__': 
    main(sys.argv[1], sys.argv[2], sys.argv[3]) 

Antwort

3

Ja, können Sie verschmelzen verwenden mit der indicator Parameter:

I umbenannt die Spalten duplizierten Spalten vermeiden Sie auch left_on und right_on

merged = DF1.merge(DF2.rename(columns={'col_1': 'col_a', 'col_2': 'col_b'}), how='left', indicator=True) 
merged 
Out: 
    col_a col_b  _merge 
0 1325 foo left_only 
1 1397 foo  both 
2 1645 foo left_only 

jetzt passieren kann, Sie merged mit der Anzeigesäule filtern:

merged[merged['_merge']=='left_only'] 
Out: 
    col_a col_b  _merge 
0 1325 foo left_only 
2 1645 foo left_only 
+1

Schön, ich wusste nicht über "Indikator" -Parameter – MaxU

+1

@ MaxU und ich wusste nicht, dass Sie ein Diktat an "Isin" übergeben können. :) – ayhan

+0

danke allen, die geantwortet haben! Diese Antwort ist für mich am einfachsten zu verstehen, ich bin 1 Tag neu bei Pandas, nochmals vielen Dank! –

3

Dies verwendet boolean Indizierung alle Zeilen in df1 zu lokalisieren, wo die Werte in col_a sind NICHT (~) in col_a von df2. Es verwendet isin(), um übereinstimmende Zeilen zu finden, und den Negationsoperator (~), um das Gegenteil von denen zu finden (d. H. Die, die nicht übereinstimmen).

df1[~df1.col_a.isin(df2.col_a)] 

Sie erwähnten einen Index, aber Ihre Beispieldaten haben keinen Index. Die Anpassung erfolgt somit nur an den Werten in col_a an Ihrem Beispiel.

+0

ich es werde einen Versuch geben, aber ist das 'isin' nicht mit den gleichen Indizes zwischen den beiden Spalten identisch? Ich war unter diesem Eindruck. –

+0

Ich habe es vielleicht falsch implementiert, aber diese Lösung hat nicht funktioniert. Es hat die gesamte Liste zurückgegeben und keine Übereinstimmungen gefunden (ich glaube, das liegt daran, dass sich alle Übereinstimmungen in verschiedenen Indizes befinden, wie ich bereits erwähnt habe). –

+0

Können Sie ein besseres Beispiel für Ihren Datenrahmen angeben? z.B. 'df1.to_dict ('list')' Sie erwähnen einen Index, aber Ihr Beispiel hat keinen Index. Ist es möglich, den gleichen Wert in 'col_a' zu haben, aber unterschiedliche Werte in' col_b'? Wenn ja, wie wollen Sie damit umgehen? – Alexander

3

hier ist ein Pandas Äquivalent für SQL (Oracle) minus Betrieb:

select col1, col2 from tab1 
minus 
select col1, col2 from tab2 

in Pandas:

In [59]: df1[~df1.isin(pd.DataFrame(df2.values, columns=df1.columns).to_dict('l')).all(1)] 
Out[59]: 
    col_a col_b 
0 1325 foo 
2 1645 foo 

Erläuterung:

In [60]: pd.DataFrame(df2.values, columns=df1.columns) 
Out[60]: 
    col_a col_b 
0 1397 foo 
1 1500 foo 
2 1621 foo 

In [61]: pd.DataFrame(df2.values, columns=df1.columns).to_dict('l') 
Out[61]: {'col_a': [1397, 1500, 1621], 'col_b': ['foo', 'foo', 'foo']} 

In [62]: df1.isin(pd.DataFrame(df2.values, columns=df1.columns).to_dict('l')) 
Out[62]: 
    col_a col_b 
0 False True 
1 True True 
2 False True 

In [63]: df1.isin(pd.DataFrame(df2.values, columns=df1.columns).to_dict('l')).all(1) 
Out[63]: 
0 False 
1  True 
2 False 
dtype: bool 
Verwandte Themen