一次传递pandas str.replace函数中的文本列表,而不是迭代单个列表元素

时间:2017-06-01 08:55:20

标签: python performance pandas for-loop vectorization

pandas function str.replace有两个参数,一个是要搜索的,另一个是需要替换的值。假设我有两个列表keywordlookupId如下。

lookupid = ['##10##','##13##','##12##','##13##']
keyword = ['IT Manager', 'Sales Manager', 'IT Analyst', 'Store Manager']

不是使用zip()或任何其他方法迭代列表,而是希望直接在str.replace代码中插入两个列表。有什么方法可以避免循环,仍然以更快的方式做到这一点?我的数据包含数据框中的数百万条记录,我可以查找和替换这些记录,lookupinkeyword列表中有近200000个元素。因此表现很重要。我怎样才能更快地执行此操作?

df_find.currentTitle.str.replace(r'keyword'\b',r'lookupId',case=False)

我收到以下错误。

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-12-cb36f6429008> in <module>()
----> 1 df_find.currentTitle=df_find.currentTitle.str.replace(r'\b'+df_replace.keyword+r'\b',r' '+df_replace.lookupId+ ' ',case=False)

c:\python27\lib\site-packages\pandas\core\strings.pyc in replace(self, pat, repl, n, case, flags)
   1504     def replace(self, pat, repl, n=-1, case=True, flags=0):
   1505         result = str_replace(self._data, pat, repl, n=n, case=case,
-> 1506                              flags=flags)
   1507         return self._wrap_result(result)
   1508 

c:\python27\lib\site-packages\pandas\core\strings.pyc in str_replace(arr, pat, repl, n, case, flags)
    320     # Check whether repl is valid (GH 13438)
    321     if not is_string_like(repl):
--> 322         raise TypeError("repl must be a string")
    323     use_re = not case or len(pat) > 1 or flags
    324 

TypeError: repl must be a string

我的输入数据就像

current_title
I have been working here as a store manager since after I passed from college
I am sales manager and primarily work in the ASEAN region. My primary rolw is to bring new customers.
I initially joined as a IT analyst and because of my sheer drive and dedication, I was promoted to IT manager position within 3 years

输出

current_title
I have been working here as a ##13## since after I passed from college
I am ##13## and primarily work in the ASEAN region. My primary rolw is to bring new customers.
I initially joined as a ##12## and because of my sheer drive and dedication, I was promoted to ##10## position within 3 years

编辑:根据jezrel的回答,我提出了建议,我收到了新的错误。

TypeError                                 Traceback (most recent call last)
<ipython-input-8-699e487f230e> in <module>()
----> 1 df_find.currentTitle.replace(keyword, df_replace['lookupId'], regex=True)

c:\python27\lib\site-packages\pandas\core\generic.pyc in replace(self, to_replace, value, inplace, limit, regex, method, axis)
   3506                                                        dest_list=value,
   3507                                                        inplace=inplace,
-> 3508                                                        regex=regex)
   3509 
   3510                 else:  # [NA, ''] -> 0

c:\python27\lib\site-packages\pandas\core\internals.pyc in replace_list(self, src_list, dest_list, inplace, regex, mgr)
   3211                                      operator.eq)
   3212 
-> 3213         masks = [comp(s) for i, s in enumerate(src_list)]
   3214 
   3215         result_blocks = []

c:\python27\lib\site-packages\pandas\core\internals.pyc in comp(s)
   3209                 return isnull(values)
   3210             return _possibly_compare(values, getattr(s, 'asm8', s),
-> 3211                                      operator.eq)
   3212 
   3213         masks = [comp(s) for i, s in enumerate(src_list)]

c:\python27\lib\site-packages\pandas\core\internals.pyc in _possibly_compare(a, b, op)
   4613             type_names[1] = 'ndarray(dtype=%s)' % b.dtype
   4614 
-> 4615         raise TypeError("Cannot compare types %r and %r" % tuple(type_names))
   4616     return result
   4617 

TypeError: Cannot compare types 'ndarray(dtype=object)' and 'str'

2 个答案:

答案 0 :(得分:2)

试试这个:

In [177]: df.current_title.replace([r'\b(?i){}\b'.format(k) for k in keyword], lookupid, regex=True)
Out[177]:
0                                                     I have been working here as a ##13## since after I passed from college
1                             I am ##13## and primarily work in the ASEAN region. My primary rolw is to bring new customers.
2    I initially joined as a ##12## and because of my sheer drive and dedication, I was promoted to ##10## position withi...
Name: current_title, dtype: object

答案 1 :(得分:2)

您似乎需要list comprehension Series.replace(不是Series.str.replace):

keyword = [ r'\b(?i)' + x +r'\b' for x in keyword]
df_find.currentTitle = df_find.currentTitle.replace(keyword,lookupid,regex=True)

#temporary display long strings
with pd.option_context('display.max_colwidth', 130):
    print (df_find)
                                                                                                                    currentTitle
0                                                         I have been working here as a ##13## since after I passed from college
1                                 I am ##13## and primarily work in the ASEAN region. My primary rolw is to bring new customers.
2  I initially joined as a ##12## and because of my sheer drive and dedication, I was promoted to ##10## position within 3 years