2017-12-30 23 views
5

Als Eingabe Ich habe zwei Datenrahmen:Zusammenführen von zwei Datenrahmen mit Intervalldaten in einem von ihnen

data1 = [{'code':100}, {'code':120}, {'code':110}] 
data1 = pd.DataFrame(data1) 

    code 
0 100 
1 120 
2 110 

data2 = [{'category':1, 'l_bound':99, 'r_bound':105},{'category':2, 'l_bound':107, 'r_bound':110},{'category':3, 'l_bound':117, 'r_bound':135}] 
data2 = pd.DataFrame(data2) 

    category l_bound r_bound 
0   1  99  105 
1   2  107  110 
2   3  117  135 

I mit zusätzlichen Spalt in dem ersten Datenrahmen als Kategorienummer am Ende des folgende Datenrahmen, erhalten möchte, wenn der code liegt im entsprechenden intervall:

code category 
0 100   1 
1 120   3 
2 110   2 

Intervalle sind zufällig und die ursprünglichen Datenrahmen sind ziemlich groß. Looping mit Itertuples ist zu langsam. Irgendwelche pythonischen Lösungen?

+0

reine Python - https://eval.in/928533 – splash58

+1

@AntonvBR ich nicht eng am Beispiel ausgesehen haben, aber das Problem (und Antworten) zwischen den beiden scheinen identisch ... –

+0

** Nützliche Beobachtung **: Die folgenden Lösungen funktionieren möglicherweise nicht, wenn die Daten nicht in einem geeigneten Format vorliegen. Stellen Sie sicher, dass 'data1' und' data2' Integer sind. In einigen Spalten der ursprünglichen Datasets können auch gemischte Formate enthalten sein (z. B. "code": "123a"). Um es loszuwerden, fügen Sie einfach 'data1 = data1 [pd.to_numeric (data1 ['code'], errors = 'coerce') hinzu. Notnull()] data1 ['code'] = pd.to_numeric (data1 ['code ']) ' –

Antwort

1

den Datensatz neu erstellen:

import pandas as pd 

data1 = [{'code':100}, {'code':120}, {'code':113}] 
data2 = [{'category':1, 'l_bound':99, 'r_bound':105}, 
     {'category':2, 'l_bound':107, 'r_bound':110}, 
     {'category':3, 'l_bound':117, 'r_bound':135}] 

data1 = pd.DataFrame(data1) 
data2 = pd.DataFrame(data2) 

@ cᴏʟᴅsᴘᴇᴇᴅ Antwort ( bevorzugt), folgen Duplikat Link:

idx = pd.IntervalIndex.from_arrays(data2['l_bound'], data2['r_bound'], closed='both') 
category = data2.loc[idx.get_indexer(data1.code), 'category'] 

data1['category'] = category.values 

Hier ist ein anderer Ansatz. Erstellen Sie eine Karte mit einem Wert in Bereich und Kategorien.

# Create a map 
d = {i:k for k,v in data2.set_index('category').to_dict('i').items() 
    for i in range(v['l_bound'],v['r_bound']+1)} 

# Use map to add new column 
data1['category'] = data1.code.map(d) 

Schließlich

print(data1) 

Returns:

code category 
0 100  1.0 
1 120  3.0 
2 113  NaN 

Wenn Sie int wollen wir dies tun können:

data1.code.map(d).fillna(-1).astype(int) # -1 meaning no match 

Und w e erhalten:

code category 
0 100   1 
1 120   3 
2 113  -1 
+0

Ich weiß nicht warum, aber IntervalIndex scheint nicht zu funktionieren. Ich habe einen Fehler "AttributError: 'Modul' Objekt hat kein Attribut 'IntervalIndex'" –

+0

Vielleicht haben Sie nicht die neueste Pandas-Version. –

+0

Ja, das stimmt. –

Verwandte Themen