数据帧应用函数需要超过24小时才能执行


def city_check(test):
test=str(test)
for ele in city:    #city is a list containing 2200 city names.
ele=str(ele)

result = re.findall('\b'+ele+'\b', test, flags=re.IGNORECASE)
if len(result)>0:
return ele
return "Not Found"
df['city']=df['address_line_1'].apply(city_check) #df has 2.5 million rows

为什么要花这么长时间?我怎样才能让它更快?

为什么要花这么长时间?:

您对所有250万个条目调用该函数。每次你这样做,你都会在2500个城市中循环(早期回报很少见,所以我忽略了它们(。所以你调用re.findall()2 500 000*2 500=5 500 000 000次。

仅仅增加+1亿次,我的笔记本电脑就花了大约7秒。这将超过6分钟55亿次,我只测试了一个最快的操作,而你使用的操作要复杂得多。

怎样才能更快?:

您的大部分时间都由regex函数使用。这里不需要regex,可以使用"sub" in "string",这要快得多(在我刚刚做的一个小测试中,它大约快了15倍

if city.lower() in test.lower(): # in reply to some comments: yes that can lead to wrong results, but keep reading
...

您可以通过不每次调用.lower()来进行更多优化。在执行.apply()之前,请创建一个所有小写城市名称的列表(并在每个城市名称的开头和结尾添加类似环境的空格,以解决错误的结果问题(,因此您只需要执行一次,并在函数开始时将test转换为小写。

def city_check(test):
test=str(test).lower()
for ele in cityLowerNames:
if ele in test:
return ele
return "Not Found"

作为进一步的优化,你可以并行运行循环,但由于你只循环了2500个项目,所以当你每次启动额外的线程时,它不会那么有效,甚至可能更糟。因此,如果您尝试并行执行,请确保启动线程一次并保持其运行。也许你可以用它快4倍,这取决于需要多少额外的逻辑。

如果只需要通过函数返回第一个匹配项,我建议使用re.searchre.match进行此regex操作。就处理能力而言,re.findall的成本相当高,尤其是考虑到您正在处理的大量行。

关于不同正则表达式函数的详细信息:此处

可以通过使用像multiprocessing这样的多处理模块来进一步提高该操作的速度。此处的文档

然而,这将取决于你需要多久运行一次这个函数,以及它是否值得开发时间!

我试过这个:

import pandas as pd
import numpy as np
d = {'address_line_1': ['93346 INDIA BULLS 2ND FLOOR GARND MALL GT ROAD JAL... 1', 'None', 'None', '5 93346 U WB FAIRLAND COLONY FGC ROAD JALANDHAR PUNJAB 1', 'None', 'None', '6 129128 D 501 WHESPERING PALMS XCLUSIVE AKURLI ROAD LO... 1', 'None', 'None', '7 62321 GUT NO: BUILDING NAME: BUILDING NO 130 HOUSE N...1', 'None', 'None', '8 147383 D NO 20 1 272 RAMALAYAM STREET MANGALAM ROAD']}
df = pd.DataFrame(data=d)
city=list(['akurli','ramalayam'])
df['city'] = df['address_line_1'].apply(lambda x: [item for item in str(x).lower().split() if item in city])
df['city'] = df['city'].str[0]
df

我得到

address_line_1                                      city
0   93346 INDIA BULLS 2ND FLOOR GARND MALL GT ROAD...   NaN
1   None                                                NaN
2   None                                                NaN
3   5 93346 U WB FAIRLAND COLONY FGC ROAD JALANDHA...   NaN
4   None                                                NaN
5   None                                                NaN
6   6 129128 D 501 WHESPERING PALMS XCLUSIVE AKURL...   akurli
7   None                                                NaN
8   None                                                NaN
9   7 62321 GUT NO: BUILDING NAME: BUILDING NO 130...   NaN
10  None                                                NaN
11  None                                                NaN
12  8 147383 D NO 20 1 272 RAMALAYAM STREET MANGAL...   ramalayam

现在,这可能不是最有效的方法,但我可以很快在大的df上复制它:

dff = pd.concat([df]*1000000, ignore_index=True)
dff.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 13000000 entries, 0 to 12999999
Data columns (total 1 columns):
#   Column          Dtype 
---  ------          ----- 
0   address_line_1  object
dtypes: object(1)
memory usage: 99.2+ MB
%%time
dff['city'] = dff['address_line_1'].apply(lambda x: [item for item in str(x).lower().split() if item in city])
CPU times: user 19.7 s, sys: 856 ms, total: 20.5 s
Wall time: 20.5 s

最新更新