2017-07-28 8 views
5

शीर्षक थोड़ा उलझन में है लेकिन मैं अपनी समस्या को समझाने के लिए अपनी पूरी कोशिश करूंगा। मैं 2 पांडा dataframes, ए और बी है:किसी डेटाफ्रेम से किसी डेटाफ्रेम से मूल्यों की तुलना किसी अन्य डेटाफ्रेम में कॉलम से मूल्यों के साथ और तीसरे कॉलम से डेटा प्राप्त करना

>> print a 

id | value 
1 | 250 
2 | 150 
3 | 350 
4 | 550 
5 | 450 

>> print b 

low | high | class 
100 | 200 | 'A' 
200 | 300 | 'B' 
300 | 500 | 'A' 
500 | 600 | 'C' 

मैं एक नया स्तंभ तालिका एक में कक्षा कहा जाता है कि तालिका ख के अनुसार मूल्य के वर्ग में शामिल है बनाना चाहते हैं। यहाँ परिणाम मैं चाहता हूँ:

>> print a 

id | value | class 
1 | 250 | 'B' 
2 | 150 | 'A' 
3 | 350 | 'A' 
4 | 550 | 'C' 
5 | 450 | 'A' 

मैं निम्नलिखित कोड है कि एक तरह से लिखा है जो मैं चाहता है:

a['class'] = pd.Series() 
for i in range(len(a)): 
    val = a['value'][i] 
    cl = (b['class'][ (b['low'] <= val) \ 
         (b['high'] >= val) ].iat[0]) 
    a['class'].set_value(i,cl) 

समस्या है, यह 10 या तो की टेबल लंबाई के लिए त्वरित है, लेकिन मैं मैं ए और बी दोनों के लिए 100,000+ के टेबल आकार के साथ ऐसा करने की कोशिश कर रहा हूं। क्या पांडा में कुछ फ़ंक्शन/विशेषता का उपयोग करके ऐसा करने का कोई तेज तरीका है?

उत्तर

1

यहाँ, एक समाधान है कि Series.searchsorted का उपयोग करने से बेशक कम खूबसूरत है, लेकिन यह सुपर फास्ट चलाता है!

मैं पैंडस डेटाफ्रेम से डेटा खींचता हूं और उन्हें सूचियों में परिवर्तित करता हूं और फिर "एक्लास" नामक एक चर को पॉप्युलेट करने के लिए np.where का उपयोग करता हूं जहां स्थितियां संतृप्त होती हैं (लूप के लिए ब्रूट फोर्स में)। फिर मैं मूल डेटा फ्रेम ए में "एक्लास" लिखता हूं।

मूल्यांकन समय 0.07489705 एस था, इसलिए यह 200,000 डेटा पॉइंट्स के साथ भी बहुत तेज़ है!

# create 200,000 fake a data points 
avalue = 100+600*np.random.random(200000) # assuming you extracted this from a with avalue = np.array(a['value']) 

blow = [100,200,300,500] # assuming you extracted this from b with list(b['low']) 
bhigh = [200,300,500,600] # assuming you extracted this from b with list(b['high']) 
bclass = ['A','B','A','C'] # assuming you extracted this from b with list(b['class']) 

aclass = [[]]*len(avalue) # initialize aclass 

start_time = time.time() # this is just for timing the execution 
for i in range(len(blow)): 
    for j in np.where((avalue>=blow[i]) & (avalue<=bhigh[i]))[0]: 
     aclass[j]=bclass[i] 

# add the class column to the original a DataFrame 
a['class'] = aclass 

print("--- %s seconds ---" % np.round(time.time() - start_time,decimals = 8)) 
+0

मेरे लूपिंग योजना से बहुत तेज़ है! इस समाधान का भी परीक्षण करेंगे! – rbae

5

यहाँ एक रेंज करने के लिए एक रास्ता @ से प्रेरित शामिल होने है piRSquared के solution:

A = a['value'].values 
bh = b.high.values 
bl = 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) 
) 

आउटपुट:

id value low high class 
0 1 250 200 300 'B' 
1 2 150 100 200 'A' 
2 3 350 300 500 'A' 
3 4 550 500 600 'C' 
4 5 450 300 500 'A' 
+0

आह, यह एक उत्कृष्ट समाधान है। हालांकि, मैं एक मेमोरी त्रुटि प्राप्त कर रहा हूं। piRSquared के समाधान में लंबाई 2 एम + की सारणी शामिल है, जबकि मेरा केवल 100,000 है। मैं किसी भी बग के लिए दोबारा जांच करूंगा। – rbae

+0

@ स्कॉट बोस्टन, क्या आप कृपया मेरे द्वारा पोस्ट किए गए प्रश्न को देख सकते हैं, किसी ने अभी तक इसका उत्तर नहीं दिया है, अगर आप मेरी मदद करते हैं तो मुझे खुशी होगी। https://stackoverflow.com/questions/45511223/how-to-perform-single-operation-on-multiple-columns-of-dataframe – BlueQuant

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