2016-11-13 6 views
1

Ich habe 2 Datenrahmen, beide haben eine Schlüsselspalte, die Duplikate haben könnte, aber die Datenrahmen haben meist die gleichen duplizierten Schlüssel. Ich möchte diese Datenrahmen für diesen Schlüssel zusammenführen, aber so, dass beide Duplikate zusammengeführt werden, wenn beide dasselbe Duplikat haben. Wenn ein Datenrahmen mehr Duplikate eines Schlüssels hat als der andere, möchte ich, dass seine Werte als NaN gefüllt werden. Zum Beispiel:Merge Pandas Datenrahmen mit Schlüssel Duplikate

df1 = pd.DataFrame({'key': ['K0', 'K1', 'K2', 'K2', 'K2', 'K3'], 
        'A': ['A0', 'A1', 'A2', 'A3', 'A4', 'A5']}, 
        columns=['key', 'A']) 
df2 = pd.DataFrame({'B': ['B0', 'B1', 'B2', 'B3', 'B4', 'B5', 'B6'], 
        'key': ['K0', 'K1', 'K2', 'K2', 'K3', 'K3', 'K4']}, 
        columns=['key', 'B']) 

    key A 
0 K0 A0 
1 K1 A1 
2 K2 A2 
3 K2 A3 
4 K2 A4 
5 K3 A5 

    key B 
0 K0 B0 
1 K1 B1 
2 K2 B2 
3 K2 B3 
4 K3 B4 
5 K3 B5 
6 K4 B6 

Ich versuche, die folgende Ausgabe

key A B 
0 K0 A0 B0 
1 K1 A1 B1 
2 K2 A2 B2 
3 K2 A3 B3 
6 K2 A4 NaN 
8 K3 A5 B4 
9 K3 NaN B5 
10 K4 NaN B6 

Also im Grunde zu bekommen, Ich mag würde den duplizierten K2 Schlüssel als K2_1, K2_2 zu behandeln, ... und dann tun Das How = 'Outer' verschmelzen auf den Datenrahmen. Irgendwelche Ideen, wie ich das erreichen kann?

Antwort

3

schneller wieder

%%cython 
# using cython in jupyter notebook 
# in another cell run `%load_ext Cython` 
from collections import defaultdict 
import numpy as np 

def cg(x): 
    cnt = defaultdict(lambda: 0) 

    for j in x.tolist(): 
     cnt[j] += 1 
     yield cnt[j] 


def fastcount(x): 
    return [i for i in cg(x)] 

df1['cc'] = fastcount(df1.key.values) 
df2['cc'] = fastcount(df2.key.values) 

df1.merge(df2, how='outer').drop('cc', 1) 

schnelle Antwort; nicht skalierbar

def fastcount(x): 
    unq, inv = np.unique(x, return_inverse=1) 
    m = np.arange(len(unq))[:, None] == inv 
    return (m.cumsum(1) * m).sum(0) 

df1['cc'] = fastcount(df1.key.values) 
df2['cc'] = fastcount(df2.key.values) 

df1.merge(df2, how='outer').drop('cc', 1) 

alte Antwort

df1['cc'] = df1.groupby('key').cumcount() 
df2['cc'] = df2.groupby('key').cumcount() 

df1.merge(df2, how='outer').drop('cc', 1) 

enter image description here

+0

Gibt es eine Möglichkeit, dies schneller zu machen? Ich arbeite mit Datenrahmen mit ungefähr 4 Millionen Einträgen und während die Zusammenführung im Prinzip sofort erfolgt, dauert der Aufruf von cumcount() ungefähr eine Minute. – dcmm88

+0

@ dcmm88 Ich schrieb diese Funktion speziell. überprüfen Sie, ob es die Situation nicht verbessert. – piRSquared

+0

Die '' 'np.arange ... == inv''' Zeile, du wolltest dort np.equal verwenden? Denn zumindest für mich ist das Ergebnis von '==' ein Bool. Selbst wenn ich np.equal verwende, erhalte ich einen Speicherfehler, vielleicht sind meine Datenrahmen zu groß? – dcmm88

Verwandte Themen