Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
String 用字典替换子字符串的最快方法(在大型数据集上)_String_Pandas_Numpy_Replace_Substring - Fatal编程技术网

String 用字典替换子字符串的最快方法(在大型数据集上)

String 用字典替换子字符串的最快方法(在大型数据集上),string,pandas,numpy,replace,substring,String,Pandas,Numpy,Replace,Substring,我有1000万个文本(适合RAM)和一本python字典: "old substring":"new substring" 字典的大小约为15k子字符串 我正在寻找用dict替换每个文本的最快方法(找到每个文本中的每个“旧子字符串”,并用“新子字符串”替换它) 源文本在数据框中。 目前,我已经尝试了以下方法: 1) 使用reduce和str Replace在循环中替换(~120行/秒) 2) 具有简单替换功能的循环中(“映射”是15k指令)(~160行/秒): 而且.iterrows()的工作

我有1000万个文本(适合RAM)和一本python字典:

"old substring":"new substring"
字典的大小约为15k子字符串

我正在寻找用dict替换每个文本的最快方法(找到每个文本中的每个“旧子字符串”,并用“新子字符串”替换它)

源文本在数据框中。 目前,我已经尝试了以下方法:

1) 使用reduce和str Replace在循环中替换(~120行/秒)

2) 具有简单替换功能的循环中(“映射”是15k指令)(~160行/秒):

而且.iterrows()的工作速度比.itertuples()慢20%

3) 在系列上使用“应用”(也可约160行/秒):

以这样的速度处理整个数据集需要几个小时

有人有过这种大规模子串替换的经验吗?有可能加快速度吗?这可能是棘手的或丑陋的,但必须尽可能快,没有必要使用熊猫

谢谢

更新: 检查想法的玩具数据:

df = pd.DataFrame({ "old":
                    ["first text to replace",
                   "second text to replace"]
                    })

mapping = {"first text": "FT", 
           "replace": "rep",
           "second": '2nd'}
预期结果:

                      old         replaced
0   first text to replace        FT to rep
1  second text to replace  2nd text to rep

我想您正在寻找df上的正则表达式替换,即

如果您有字典,则将其作为参数传递

d = {'old substring':'new substring','anohter':'another'}
对于整个数据帧

df.replace(d,regex=True)
对于系列

df[columns].replace(d,regex=True)
范例

df = pd.DataFrame({ "old":
                ["first text to replace",
               "second text to replace"]
                })

mapping = {"first text": "FT", 
       "replace": "rep",
       "second": '2nd'}

df['replaced'] = df['old'].replace(mapping,regex=True)

一种解决方案是将字典转换为a,并编写代码,以便只传递一次修改后的文本

基本上,您可以一次遍历文本和trie一个字符,一旦找到匹配项,就可以替换它


当然,如果你还需要对已经替换的文本进行替换,这就更难了。

我再次克服了这个问题,找到了一个很棒的库,名为

在10M记录和15k词汇表上的加速约为x100(比我第一篇文章中的regexp或其他方法快一百倍)

非常容易使用:

df = pd.DataFrame({ "old":
                    ["first text to replace",
                   "second text to replace"]
                    })

mapping = {"first text": "FT", 
           "replace": "rep",
           "second": '2nd'}

import flashtext
processor = flashtext.KeywordProcessor()

for k, v in mapping.items():
    processor.add_keyword(k, v)

print(list(map(processor.replace_keywords, df["old"])))
结果:

['FT to rep', '2nd text to rep']
如果需要,还可以使用processor.non_word_bounders属性灵活地适应不同的语言


这里使用的基于Trie的搜索速度惊人

检查。谢谢Wiktor,我现在看到了regexp=True的想法,但它比头条文章中的简单方法慢得多。你可以直接把字典递给我谢谢。不幸的是,这是一种慢得多的方法~每秒100行。@AlexeyTrofimov Try
regex=False
@cᴏʟᴅsᴘᴇᴇᴅ 他想替换字符串的子字符串。@Bharathshetty简单的替换不需要正则表达式
df = pd.DataFrame({ "old":
                ["first text to replace",
               "second text to replace"]
                })

mapping = {"first text": "FT", 
       "replace": "rep",
       "second": '2nd'}

df['replaced'] = df['old'].replace(mapping,regex=True)
df = pd.DataFrame({ "old":
                    ["first text to replace",
                   "second text to replace"]
                    })

mapping = {"first text": "FT", 
           "replace": "rep",
           "second": '2nd'}

import flashtext
processor = flashtext.KeywordProcessor()

for k, v in mapping.items():
    processor.add_keyword(k, v)

print(list(map(processor.replace_keywords, df["old"])))
['FT to rep', '2nd text to rep']