2016-01-13 18 views
7

का उपयोग करके सबस्ट्रिंग को हटा रहा है मैंने चारों ओर खोज करने की कोशिश की है और ऐसा करने का एक आसान तरीका नहीं पता है, इसलिए मुझे उम्मीद है कि आपकी विशेषज्ञता मदद कर सकती है।पायथन पांडस एक और कॉलम

मैं जो मुझे देता है दो कॉलम

import numpy as np 
import pandas as pd 

pd.options.display.width = 1000 
testing = pd.DataFrame({'NAME':[ 
    'FIRST', np.nan, 'NAME2', 'NAME3', 
    'NAME4', 'NAME5', 'NAME6'], 'FULL_NAME':['FIRST LAST', np.nan, 'FIRST LAST', 'FIRST NAME3', 'FIRST NAME4 LAST', 'ANOTHER NAME', 'LAST NAME']}) 

के साथ एक पांडा डेटा फ्रेम

  FULL_NAME NAME 
0  FIRST LAST FIRST 
1    NaN NaN 
2  FIRST LAST NAME2 
3  FIRST NAME3 NAME3 
4 FIRST NAME4 LAST NAME4 
5  ANOTHER NAME NAME5 
6   LAST NAME NAME6 

मैं क्या करना चाहते हैं 'NAME' कॉलम के मानों से ले और फिर हटाने है 'पूर्ण नाम' कॉलम से यदि यह वहां है। तो समारोह

  FULL_NAME NAME   NEW 
0  FIRST LAST FIRST   LAST 
1    NaN NaN   NaN 
2  FIRST LAST NAME2 FIRST LAST 
3  FIRST NAME3 NAME3   FIRST 
4 FIRST NAME4 LAST NAME4 FIRST LAST 
5  ANOTHER NAME NAME5 ANOTHER NAME 
6   LAST NAME NAME6  LAST NAME 

अब तक, मैंने नीचे एक फ़ंक्शन परिभाषित किया है और लागू विधि का उपयोग कर रहा हूं। हालांकि यह मेरे बड़े डेटा सेट पर धीमा चलता है और मुझे उम्मीद है कि ऐसा करने का एक और अधिक प्रभावी तरीका है। धन्यवाद!

def address_remove(x): 
    try: 
     newADDR1 = re.sub(x['NAME'], '', x[-1]) 
     newADDR1 = newADDR1.rstrip() 
     newADDR1 = newADDR1.lstrip() 
     return newADDR1 
    except: 
     return x[-1] 

उत्तर

4

यहाँ एक समाधान है कि अपने वर्तमान समाधान की तुलना में काफ़ी तेजी से, मुझे विश्वास है कि वहाँ कुछ तेजी से नहीं होगा, हालांकि

In [13]: import numpy as np 
     import pandas as pd 
     n = 1000 
     testing = pd.DataFrame({'NAME':[ 
     'FIRST', np.nan, 'NAME2', 'NAME3', 
     'NAME4', 'NAME5', 'NAME6']*n, 'FULL_NAME':['FIRST LAST', np.nan, 'FIRST LAST', 'FIRST NAME3', 'FIRST NAME4 LAST', 'ANOTHER NAME', 'LAST NAME']*n}) 

यह एक लंबा एक की तरह है नहीं कर रहा हूँ है

In [37]: %timeit testing ['NEW2'] = [e.replace(k, '') for e, k in zip(testing.FULL_NAME.astype('str'), testing.NAME.astype('str'))] 
100 loops, best of 3: 4.67 ms per loop 
: लाइनर, लेकिन यह क्या आप

उपवास समाधान के साथ मैं replace उपयोग कर रहा है के रूप में एक और उत्तर में उल्लेख ऊपर आ सकते हैं की जरूरत है क्या करना चाहिए

मूल जवाब:

In [14]: %timeit testing ['NEW'] = [''.join(str(e).split(k)) for e, k in zip(testing.FULL_NAME.astype('str'), testing.NAME.astype('str'))] 
100 loops, best of 3: 7.24 ms per loop 

अपने वर्तमान समाधान की तुलना में:

In [16]: %timeit testing['NEW1'] = testing.apply(address_remove, axis=1) 
10 loops, best of 3: 166 ms per loop 

ये आप अपने वर्तमान समाधान के रूप में एक ही जवाब मिल

+0

बढ़िया!मैं दूसरे समाधान के साथ आने की कोशिश कर रहा था, लेकिन तीसरा भी बेहतर है! क्या आप मुझे बताएंगे कि "ज़िप" कमांड क्या कर रहा है? – Link

+0

खुशी है कि काम किया! 'ज़िप' एकाधिक पुनरावृत्तियों को लेता है और मूल पुनरावृत्तियों से कुल का एक पुनरावर्तक देता है। अधिक शब्दों में यह आपको एक साथ दो या दो से अधिक पुनरावृत्तियों के माध्यम से लूप करने की अनुमति देता है। https://docs.python.org/3/library/functions.html#zip – johnchase

0

मुझे लगता है कि आप की जगह उपयोग करने के लिए (चाहते हैं) स्ट्रिंग्स की विधि है, यह नियमित अभिव्यक्तियों का उपयोग करने की तुलना में तीव्रता के आदेश है (मैंने अभी आईपीथॉन में तुरंत जांच की है):

%timeit mystr.replace("ello", "") 
The slowest run took 7.64 times longer than the fastest. This could mean that an intermediate result is being cached 
1000000 loops, best of 3: 250 ns per loop 

%timeit re.sub("ello","", "e") 
The slowest run took 21.03 times longer than the fastest. This could mean that an intermediate result is being cached 
1000000 loops, best of 3: 4.7 µs per loop 

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

2

आप replace विधि और regex तर्क के साथ यह कर सकता है और उसके बाद का उपयोग str.strip:

In [605]: testing.FULL_NAME.replace(testing.NAME[testing.NAME.notnull()], '', regex = True).str.strip() 
Out[605]: 
0   LAST 
1    NaN 
2  FIRST LAST 
3   FIRST 
4  FIRST LAST 
5 ANOTHER NAME 
6  LAST NAME 
Name: FULL_NAME, dtype: object 

नोट आप रिक्त स्ट्रिंग

को बदल दिया जाएगा क्योंकि इसके बिना NaN भी मान testing.NAME को notnull पास करनी होगी

बेंचमार्किंग धीमी गति से @johnchase समाधान धीमा है, लेकिन मुझे लगता है कि यह अधिक पठनीय है और सभी पांडा मेथ का उपयोग करें डेटाफ्रेम और सीरीज के ओडीएस:

In [607]: %timeit testing['NEW'] = testing.FULL_NAME.replace(testing.NAME[testing.NAME.notnull()], '', regex = True).str.strip() 
100 loops, best of 3: 4.56 ms per loop 

In [661]: %timeit testing ['NEW'] = [e.replace(k, '') for e, k in zip(testing.FULL_NAME.astype('str'), testing.NAME.astype('str'))] 
1000 loops, best of 3: 450 µs per loop 
+0

शुद्ध पांडा समाधान। अच्छा कार्य। पढ़ने के लिए निश्चित रूप से आसान है, भले ही यह तेज़ नहीं था। – floydn

+0

क्या आपके कोड में 'df' 'test' होना चाहिए? – johnchase

+0

@johnchase हाँ, क्षमा करें। यह कंसोल –

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