【问题标题】:Optimizing multiple for loop with Lambda function in python在 python 中使用 Lambda 函数优化多个 for 循环
【发布时间】:2020-05-22 03:05:01
【问题描述】:

我有一个下面的数据框 Df1 包含列“摘要”和“结束组”

Summary                         Closing Group
XX012 job abended with error    Automation
XX015 job abended with error    Automation
Front End issue TSL error       Automation
XX015 job abended with error    Automation
Front End issue TSL error       Automation
Front End issue TSL error       Automation
File not present error          Automation

我在下面有另一个数据框Df2,带有“标签”列

Label
TSL error
job abended
File not present

如果Summary 中存在来自Label 的确切字符串,我想将每个Label 映射到Summary 列。

我使用for loop 编写了以下脚本来处理我的情况:

list_label= Df2['Label']

def is_phrase_in(phrase, text):        
    return re.search(r"\b{}\b".format(phrase), text, re.IGNORECASE) is not None

for idx2,row2 in Df1.iterrows():       
    for label in list_label:
        print(label)
        if is_phrase_in(label, row2['Summary']):
            Df1.at[idx2,'Label'] =label
            break

上面的代码给了我预期的结果,但是在7000 label list 和20000 Summary 上运行时需要很长时间。

为了优化这一点,我使用了Lambda 函数,如下所示:

Df1['Label'] = Df1['Summary'].apply(lambda x : next((l for l in list_label['Label']  if is_phrase_in(l,x)), 'No Label Found'))

但是这个脚本需要更多时间,甚至比 for loop 还要多。

谁能告诉我我在这里做错了什么,或者有没有其他方法可以优化这段代码。

我的预期输出:

Summary                         Closing Group      Label
XX012 job abended with error    Automation         job abended
XX015 job abended with error    Automation         job abended
Front End issue TSL error       Automation         TSL error
Server down error               Server             No Label found
XX015 job abended with error    Automation         job abended
Front End issue TSL error       Automation         TSL error
Front End issue TSL error       Automation         TSL error
File not present error          Automation         File not present

【问题讨论】:

  • 您实际上可以尝试 numpy 或 panda。它们自然更快,因为它们为数据帧优化了引擎。像这样:stackoverflow.com/questions/41588034/…
  • 您真的有 7,000 个唯一的、可能有效的标签,仅用于 20,000 个数据点吗?必须为每个数据点搜索众多标签中的每一个标签会大大扩展时间要求 - 如果您可以优化标签列表(如果没有上下文则很难理解),那么这可能会非常有益
  • 是的,我有大约 7000 个独特的标签。
  • 我可以建议这很容易并行化吗?
  • @brunodesthuilliers - 你的意思是多线程吗?如果没有,那么您可以分享可并行化的链接

标签: python python-3.x


【解决方案1】:

必须清楚,上面代码中的大部分处理都会花在正则表达式搜索(re.search)上。

您可以尝试替代“Python String find() 方法”吗?即str.find(str, beg=0, end=len(string)) 与您的数据。

if text.find(phrase) == -1:
   return 'No Label Found'
else:
   return phrase

【讨论】:

  • 是的,我刚刚对re.search(r"\bA test\b", "this is a test you know", re.IGNORECASE)"A test".lower() in "this is a test you know".lower() 进行了测试,正则表达式慢了一个数量级(~2.5s vs ~0.15s)
  • 这不会给我精确的字符串匹配。例如我有一个phrase =' Frequent' text = 'Frequently occur error',上面的脚本会给我输出Frequent,但在我的情况下,我不希望它不完全匹配。这就是我使用正则表达式的原因。
  • @Oliver.R - 我已将短语和文本中的字符串更改为较低,但仍然需要很长时间。
  • ' Frequent' in 'Frequently occur error' == False - 短语中的前导空格可以区分它。如果该空间不应该存在并且您说FrequentFrequently 的一个子集,因此您需要使用barrier 这个词 - 这是一个昂贵的操作来确定,我认为重新定义更有意义想想你正在做的事情是否是最有效的方式。关于字符串小写,我不仅仅指将字符串更改为小写,我还指使用in 而不是正则表达式解决方案——它的速度要快一个数量级,但你比较的太多了。
  • @Oliver.R - 让我告诉你另一种情况。我的标签包含 'XXX015FS''XMLerror' 之类的值,我的文本包含一个值 'XXX015FS XMLerror404 error occured'。现在,如果我使用 re.search 函数使用我的脚本,它会给我标签为“XXX015FS”,但如果使用re.find,它可以给我'XXX015FS''XMLerror' 两者中的任何一个。我有很多这样的案例。这就是我对精确字符串匹配非常挑剔的原因。虽然我的代码运行得非常好并且给了我预期的输出,但是它在 7000 个标签和 20000 个摘要上大约需要 55 分钟。
【解决方案2】:

使用“in”而不是正则表达式替换字符串比较使代码更快一点。但是,从您提供的示例来看,摘要似乎在重复(“XX015 作业异常终止”发生了两次,“前端问题 TSL 错误”发生了 3 次)。也许您可以获取一组独特的摘要和标签并进行字符串操作,将它们作为字典存储在其他地方,然后进行最终映射。我想这比每次看到字符串时直接计算函数要快得多。

【讨论】:

  • 因此您的迭代将基于独特的摘要,而不是 Df1。根据 Df1 中的行数和 Df1 中唯一摘要的数量,事情会快很多。
  • 老实说,我有 20000 个唯一的摘要标签,其中很常见,这就是我将这些摘要映射到标签的原因
猜你喜欢
  • 1970-01-01
  • 2016-05-24
  • 2012-02-15
  • 2017-01-17
  • 2015-04-15
  • 2020-11-07
  • 1970-01-01
  • 2013-11-15
相关资源
最近更新 更多