2016-04-03 16 views
4

Ich habe zwei Pandas Datenrahmen. Die erste ist:Python Pandas- Mischen von zwei Datenrahmen basierend auf einer Indexreihenfolge

df1 = pd.DataFrame({"val1" : ["B2","A1","B2","A1","B2","A1"]}) 

der zweite Datenrahmen ist:

df2 = pd.DataFrame({"val1" : ["A1","A1","A1","B2","B2","B2"], 
        "val2" : [10, 13, 16, 11, 20, 22]}) 

Ich mag die beide zusammen in eine Art und Weise fusionieren, in denen die Zeilenordnung von df1 verwendet wird und die Werte von DF2 folgen diese Bestellung. Im Idealfall würde Ich mag es so aussehen:

df_final = pd.DataFrame({"val1" : ["B2","A1","B2","A1","B2","A1"], 
         "val2" : [11, 10, 20, 13, 22, 16]}) 

Ich habe versucht, die Merge-Funktion mit left_on und right_on, aber ich habe nicht den Ausgang, den ich suche. Jede Hilfe würde sehr geschätzt werden.

+0

Vielleicht 'df2.update (df1)' und dann Vals sortieren? –

+0

@PadraicCunningham, die Frage ist, wie man sie sortiert? ;) – MaxU

+0

@MaxU, es ist ziemlich einfach mit regulären Python –

Antwort

1

Sie können es auf diese Weise tun:

  1. Sortierwerte in df2 von ['val1', 'val2'], Gruppe durch val1 und speichern Sie es als g2?
  2. hinzufügen idx Spalte df1, die verwendet werden, Werte von df2

-Code wählen:

In [176]: df1['idx'] = 1 

In [177]: df1['idx'] = df1.groupby('val1')['idx'].cumsum()-1 

In [178]: df1 
Out[178]: 
    val1 idx 
0 B2 0 
1 A1 0 
2 B2 1 
3 A1 1 
4 B2 2 
5 A1 2 

In [179]: g2 = df2.sort_values(['val1', 'val2']).groupby('val1') 

In [180]: g2.groups 
Out[180]: {'A1': [0, 1, 2], 'B2': [3, 4, 5]} 

In [181]: df2.iloc[g2.groups['A1'][1]] 
Out[181]: 
val1 A1 
val2 13 
Name: 1, dtype: object 

In [182]: df1.apply(lambda x: df2.iloc[g2.groups[x['val1']][x['idx']]], axis=1) 
Out[182]: 
    val1 val2 
0 B2 11 
1 A1 10 
2 B2 20 
3 A1 13 
4 B2 22 
5 A1 16 
0

Sie könnten groupby/cumcount verwenden, um eine eindeutige Nummer, die jede Zeile in jeder Gruppe zuzuordnen:

df1['cumcount'] = df1.groupby('val1').cumcount() 
# val1 cumcount 
# 0 B2   0 
# 1 A1   0 
# 2 B2   1 
# 3 A1   1 
# 4 B2   2 
# 5 A1   2 

Wenn wir das tun, das gleiche zu df2:

df2['cumcount'] = df2.groupby('val1').cumcount() 
# val1 val2 cumcount 
# 0 A1 10   0 
# 1 A1 13   1 
# 2 A1 16   2 
# 3 B2 11   0 
# 4 B2 20   1 
# 5 B2 22   2 

dann df1 mit df2 auf den gemeinsamen Spalten verschmelzenden (val1 und cumcount) erzeugt das gewünschte Ergebnis:

import numpy as np 
import pandas as pd 

df1 = pd.DataFrame({"val1" : ["B2","A1","B2","A1","B2","A1"]}) 
df2 = pd.DataFrame({"val1" : ["A1","A1","A1","B2","B2","B2"], 
        "val2" : [10, 13, 16, 11, 20, 22]}) 
df_final = pd.DataFrame({"val1" : ["B2","A1","B2","A1","B2","A1"], 
         "val2" : [11, 10, 20, 13, 22, 16]}) 

df1['cumcount'] = df1.groupby('val1').cumcount() 
df2['cumcount'] = df2.groupby('val1').cumcount() 
result = pd.merge(df1, df2, how='left') 
result = result.drop('cumcount', axis=1) 
print(result) 
assert result.equals(df_final) 

Ausbeuten

val1 val2 
0 B2 11 
1 A1 10 
2 B2 20 
3 A1 13 
4 B2 22 
5 A1 16 

anzumerken, dass ein Ergebnis mit how='left' verschmelzenden erzeugt mit die gleiche Anzahl von Zeilen wie der erste DataFrame, df1, und behält die gleiche Reihenfolge o f Zeilen wie df1.

Verwandte Themen