2017-01-02 4 views
5

Ich möchte einen Self-Join auf einem Pandas-Datenrahmen durchführen, so dass einige Zeilen an die ursprünglichen Zeilen angehängt werden. Jede Zeile hat eine Markierung "i", die angibt, welche Zeile rechts davon angehängt werden soll.Self-Join mit Pandas

d = pd.DataFrame(['A','B','C'], columns = ['some_col']) 
d['i'] = [2,1,1] 

In [17]: d 
Out[17]: 
    some_col i 
0  A 2 
1  B 1 
2  C 1 

gewünschter Ausgang:

some_col i some_col_y 
0  A 2   C 
1  B 1   B 
2  C 1   B 

Das heißt, Zeile 2 wird angehängt 0 bis Zeile, Zeile 1 1 Zeile, Zeile 1 zu Zeile 2 (wie durch i angedeutet).

Meine Vorstellung davon, wie man das macht war

pd.merge(d, d, left_index = True, right_on = 'i', how = 'left') 

Aber es produziert ganz etwas anderes. Wie mache ich das richtig?

Antwort

3

join mit on='i'

d.join(d.drop('i', 1), on='i', rsuffix='_y') 

    some_col i some_col_y 
0  A 2   C 
1  B 1   B 
2  C 1   B 
1

Versuchen Sie folgendes:

In [69]: d.join(d.set_index('i'), rsuffix='_y') 
Out[69]: 
    some_col i some_col_y 
0  A 2  NaN 
1  B 1   B 
1  B 1   C 
2  C 1   A 

oder:

In [64]: pd.merge(d[['some_col']], d, left_index=True, right_on='i', suffixes=['_y','']).sort_index() 
Out[64]: 
    some_col_y some_col i 
0   C  A 2 
1   B  B 1 
2   B  C 1 
4

Statt merge verwenden Sie auch die Indizierung und Zuordnung verwenden können:

>>> d['new_col'] = d['some_col'][d['i']].values 
>>> d 
    some_col i new_col 
0  A 2  C 
1  B 1  B 
2  C 1  B 
+0

Ich mag deine Antwort mehr als meine. Wenn OP eine virtuelle Spalte benötigt, kann dies folgendermaßen geschehen: 'd.assign (some_col_y = d ['some_col']. Loc [d ['i']]. Values)' – MaxU