2017-06-05 11 views
8

मैं अक्सर श्रेणी सीमा का उपयोग करके विलय (शामिल) के लिए पांडा का उपयोग कर रहा हूं।पांडा में रेंज द्वारा जुड़ने/विलय करने का सबसे अच्छा तरीका

उदाहरण के लिए अगर वहाँ 2 dataframes हैं:

एक (A_id, A_value)

बी (B_id, B_low, B_high, B_name)

जो बड़ा और के लगभग हैं एक ही आकार (मान लें कि 2 एम रिकॉर्ड प्रत्येक)।

मैं, ए और बी के बीच एक आंतरिक में शामिल होने बनाने के लिए करना इतना A_value B_low और B_high के बीच होगी।

का उपयोग करते हुए SQL सिंटैक्स कि होगा:

SELECT * 
FROM A,B 
WHERE A_value between B_low and B_high 

और कहा कि वास्तव में, आसान छोटी और कुशल हो जाएगा।

इस बीच पांडा में एकमात्र तरीका (जो मुझे मिली लूप का उपयोग नहीं कर रहा है), दोनों टेबलों में एक डमी कॉलम बनाकर, उस पर शामिल हो (क्रॉस-जॉइन के बराबर) और फिर अनियंत्रित पंक्तियों को फ़िल्टर करें। यही कारण है कि लगता है भारी और जटिल:

A['dummy'] = 1 
B['dummy'] = 1 
Temp = pd.merge(A,B,on='dummy') 
Result = Temp[Temp.A_value.between(Temp.B_low,Temp.B_high)] 

एक अन्य समाधान है कि मैं था B[(x>=B.B_low) & (x<=B.B_high)] मुखौटा का उपयोग करके एक मूल्य बी पर एक खोज समारोह में से प्रत्येक पर लगाने से है, लेकिन यह रूप में अच्छी तरह अक्षम लगता है और सूचकांक अनुकूलन की आवश्यकता हो सकती।

क्या इस कार्रवाई को करने के लिए एक और अधिक सुरुचिपूर्ण और/या कुशल तरीका है?

+1

[यह क्यू एंड ए] (https://stackoverflow.com/questions/15581829/how-to-perform-an-inner-or-outer-join-of-dataframes-with-pandas-on-non-simplisti) प्रासंगिक हो सकता है। –

+0

ऐसा लगता है कि मैंने स्वयं को सुझाए गए एक समान विधि का उपयोग किया है (डमी कॉलम, कार्टेशियन उत्पाद और मास्क फ़िल्टर)। यह आश्चर्य की बात है कि कोई अंतर्निहित समाधान नहीं है। – Dimgold

+1

क्या आपने स्वीकृत उत्तर भी देखा ...? स्टैक ओवरफ़्लो पर _questions_ से कभी भी नहीं सीखें। यद्यपि यह हो सकता है कि मैं यह महसूस नहीं कर रहा हूं कि उत्तर वही काम करता है, जिस स्थिति में खेद है :) –

उत्तर

4

सेटअप
पर विचार करें dataframes A और B

A = pd.DataFrame(dict(
     A_id=range(10), 
     A_value=range(5, 105, 10) 
    )) 
B = pd.DataFrame(dict(
     B_id=range(5), 
     B_low=[0, 30, 30, 46, 84], 
     B_high=[10, 40, 50, 54, 84] 
    )) 

A 

    A_id A_value 
0  0  5 
1  1  15 
2  2  25 
3  3  35 
4  4  45 
5  5  55 
6  6  65 
7  7  75 
8  8  85 
9  9  95 

B 

    B_high B_id B_low 
0  10  0  0 
1  40  1  30 
2  50  2  30 
3  54  3  46 
4  84  4  84 

numpy
✌easiest✌ तरीका हैउपयोग करने के लिए 10 प्रसारण।
हम A_value के प्रत्येक उदाहरण को B_low से अधिक या उसके बराबर होने के दौरान देखते हैं जबकि एक ही समय में A_valueB_high से कम या उसके बराबर है।

a = A.A_value.values 
bh = B.B_high.values 
bl = B.B_low.values 

i, j = np.where((a[:, None] >= bl) & (a[:, None] <= bh)) 

pd.DataFrame(
    np.column_stack([A.values[i], B.values[j]]), 
    columns=A.columns.append(B.columns) 
) 

    A_id A_value B_high B_id B_low 
0  0  5  10  0  0 
1  3  35  40  1  30 
2  3  35  50  2  30 
3  4  45  50  2  30 

+0

अद्भुत समाधान .. क्या हम कह सकते हैं कि यह एक क्रॉस शामिल है ... अगर मैं केवल 'ए' की सभी पंक्तियां रखना चाहता था (मूल रूप से 'ए' पर शामिल हो गया) तो मुझे किस बदलाव की आवश्यकता होगी? –

+0

मैं भी होने वाली पंक्तियों के फटने को कम करना चाहता था। कोई विचार? –

0

नहीं लगता है कि और अधिक कुशल है, लेकिन आप पांडा (this question से प्रेरित) के साथ (उदाहरण के लिए मॉड्यूल sqlite3 से) सीधे एसक्यूएल का उपयोग की तरह कर सकते हैं:

conn = sqlite3.connect(":memory") 
df2 = pd.DataFrame(np.random.randn(10, 5), columns=["col1", "col2", "col3", "col4", "col5"]) 
df1 = pd.DataFrame(np.random.randn(10, 5), columns=["col1", "col2", "col3", "col4", "col5"]) 
df1.to_sql("df1", conn, index=False) 
df2.to_sql("df2", conn, index=False) 
qry = "SELECT * FROM df1, df2 WHERE df1.col1 > 0 and df1.col1<0.5" 
tt = pd.read_sql_query(qry,conn) 

आप क्वेरी के रूप में की जरूरत अनुकूलित कर सकते हैं अपने आवेदन

0

एक सरल उदाहरण ले सकते हैं:

df=pd.DataFrame([2,3,4,5,6],columns=['A']) 

रिटर्न

A 
0 2 
1 3 
2 4 
3 5 
4 6 

अब

B_low B_high 
0 1  2 
1 6  8 
2 2  4 
3 3  6 
4 5  6 

ये हम चले में एक दूसरे dataframe परिभाषित

df2=pd.DataFrame([1,6,2,3,5],columns=['B_low']) 
df2['B_high']=[2,8,4,6,6] 

परिणाम देता है; और हम उत्पादन

A 
3 5.0 
+0

जो शामिल नहीं है, बस स्टैकिंग – Dimgold

0

में सूचकांक 3 और एक मूल्य 5

df.where(df['A']>=df2['B_low']).where(df['A']<df2['B_high']).dropna() 

परिणाम होना चाहता हूँ ध्यान रखें कि आपकी एक dataframe

A = pd.DataFrame([[0,2],[1,3],[2,4],[3,5],[4,6]],columns=['A_id', 'A_value']) 

है और बी dataframe

B = pd.DataFrame([[0,1,2,'a'],[1,4,9,'b'],[2,2,5,'c'],[3,6,7,'d'],[4,8,9,'e']],columns=['B_id', 'B_low', 'B_high', 'B_name']) 
है

नीचे इसका उपयोग करके आप डी प्राप्त करेंगे esired उत्पादन

A = A[(A['A_value']>=B['B_low'])&(A['A_value']<=B['B_high'])] 
+0

लेकिन ए और बी एक ही आकार और क्रम आवश्यक नहीं हैं। आइए कहें कि ए 3 एम रिकॉर्ड है और बी 500 के है। – Dimgold

1

मैं इसे कैसे कुशल है पता नहीं है, लेकिन किसी को एक आवरण है कि आप पांडा वस्तुओं के साथ SQL सिंटैक्स का उपयोग करने की अनुमति देता है लिखा था। इसे pandasql कहा जाता है। दस्तावेज़ीकरण स्पष्ट रूप से बताता है कि जुड़ने का समर्थन किया जाता है। एसक्यूएल सिंटैक्स बहुत पठनीय है क्योंकि यह पढ़ने के लिए कम से कम आसान हो सकता है।

संबंधित मुद्दे