2016-09-30 11 views
3

Ich habe folgende pandas Datenrahmen:Wie mehrere Spalten in Pandas DataFrame für ein "Intervall" übereinstimmen?

import pandas as pd 
df = pd.DataFrame('filename.csv') 
print(df) 

order start end value  
1  1342 1357 category1 
1  1459 1489 category7 
1  1572 1601 category23 
1  1587 1599 category2 
1  1591 1639 category1 
.... 
15  792  813 category13 
15  892  913 category5 
.... 

So gibt es eine Spalte order jeweils viele Zeilen umfasst, und dann wird ein Bereich/Intervall von start zu end für jede Zeile. Jede Zeile ist dann mit einem bestimmten value (z. B. Kategorie1, Kategorie2 usw.) markiert.

Jetzt habe ich einen anderen Datenrahmen key_df genannt. Es ist im Grunde genau die gleiche Format:

import pandas as pd 
key_df = pd.DataFrame(...) 
print(key_df) 

order start end value  
1  1284 1299 category4 
1  1297 1309 category9 
1  1312 1369 category3 
1  1345 1392 category29 
1  1371 1383 category31 
.... 
1  1471 1501 category31 
... 

Mein Ziel ist es, die key_df Datenrahmen zu nehmen und prüfen, ob die Intervalle eine der Zeilen in dem ursprünglichen Datenrahmen df entsprechen start:end. Wenn dies der Fall ist, sollte diese Zeile in df mit dem key_df Datenrahmen value Wert gekennzeichnet werden.

In unserem Beispiel oben, der Datenrahmen df würde bis am Ende wie folgt:

order start end value  key_value 
1  1342 1357 category1 category29 
1  1459 1489 category7 category31 
.... 

Dies liegt daran, wenn man sich key_df suchen, die Reihe

1  1345 1392 category29 

mit Intervall 1::1345-1392 im Intervall fällt 1::1342-1357 im Original df. Ebenso die key_df Reihe:

1  1471 1501 category31 

entspricht die zweite Reihe in df:

1  1459 1489 category7 category31 

Ich bin nicht ganz sicher,

(1), wie diese Aufgabe in Pandas erreichen

(2) wie man das effizient in Pandas skalieren

Man könnte mit einer if-Anweisung beginnen, z.

if df.order == key_df.order: 
    # now check intervals...somehow 

, aber dies nutzt nicht die Datenstruktur. Man muss dann nach Intervall prüfen, d. H. So etwas wie (df.start =< key_df.start) && (df.end => key_df.end)

Ich stecke fest. Was ist der effizienteste Weg, mehrere Spalten in einem "Intervall" in Pandas zu finden? (Erstellen einer neuen Spalte, wenn diese Bedingung erfüllt ist, wird dann einfach)

Antwort

1

Sie merge mit boolean indexing verwenden können, aber wenn DataFrames groß sind, Skalierung ist problematisch:

df1 = pd.merge(df, key_df, on='order', how='outer', suffixes=('','_key')) 
df1 = df1[(df1.start <= df1.start_key) & (df1.end <= df1.end_key)] 
print (df1) 
    order start end  value start_key end_key value_key 
3  1 1342 1357 category1  1345.0 1392.0 category29 
4  1 1342 1357 category1  1371.0 1383.0 category31 
5  1 1342 1357 category1  1471.0 1501.0 category31 
11  1 1459 1489 category7  1471.0 1501.0 category31 

EDIT von Kommentar:

df1 = pd.merge(df, key_df, on='order', how='outer', suffixes=('','_key')) 
df1 = df1[(df1.start <= df1.start_key) & (df1.end <= df1.end_key)] 
df1 = pd.merge(df, df1, on=['order','start','end', 'value'], how='left') 
print (df1) 
    order start end  value start_key end_key value_key 
0  1 1342 1357 category1  1345.0 1392.0 category29 
1  1 1342 1357 category1  1371.0 1383.0 category31 
2  1 1342 1357 category1  1471.0 1501.0 category31 
3  1 1459 1489 category7  1471.0 1501.0 category31 
4  1 1572 1601 category23  NaN  NaN   NaN 
5  1 1587 1599 category2  NaN  NaN   NaN 
6  1 1591 1639 category1  NaN  NaN   NaN 
7  15 792 813 category13  NaN  NaN   NaN 
8  15 892 913 category5  NaN  NaN   NaN 
+0

Ich habe hier einen Fehler festgestellt. Wenn für eine gegebene Zeile kein 'value_key' existiert, wird dieser weggeworfen. Für unsere Zwecke sind alle Zeilen in 'df' gut - keine sollte verworfen werden. Wenn kein "value_key" in einer gegebenen Zeile anwendbar ist (d. H.es fällt nicht in das Intervall), dann sollte ein "NaN" aufgezeichnet werden. – ShanZhengYang

+0

Also brauchen Sie hinzufügen "merge" mit linken Join zu meinem Code? 'df1 = pd.merge (df, df1, ein = ['order', 'start', 'end', 'wert'], wie = 'links')'? – jezrael

+0

Danke für die Antwort. Ich sollte erwähnen, dass dies für Datenrahmen mit einer Größe von ca. 100 MB nicht skalierbar ist (und darüber hinaus). Ich erhalte einen 'MemoryError'. Irgendwelche Ideen, wie man dies besser skalierbar macht? Anstatt viele, eine for-Schleife zu verschmelzen? Hier ist der Fehler: 'Datei" pandas/src/join.pyx ", Zeile 187, in pandas.algos.full_outer_join'' (pandas/algos.c: 61680) ' ' Datei "pandas/src/join.pyx" , Zeile 196, in ' ' pandas.algos._get_result_indexer (pandas/algos.c: 61978) ' ' MemoryError' – ShanZhengYang

Verwandte Themen