gpt4 book ai didi

python - 加速Python应用行明智函数

转载 作者:行者123 更新时间:2023-12-01 02:48:02 25 4
gpt4 key购买 nike

我正在从事一个数据清理项目,我必须清理 pandas 数据帧的多个字段作为其中的一部分。我主要编写正则表达式和简单函数。下面的例子,

def func1(s):
s = str(s)
s = s.replace(' ', '')
if len(s) > 0 and s != '0':
if s.isalpha() and len(s) < 2:
return s

def func2(s):
s = str(s)
s = s.replace(' ', '')
s = s.strip(whitespace+','+'-'+'/'+'\\')
if s != '0':
if s.isalnum() or s.isdigit():
return s

def func3(s):
s = str(s)
if s.isdigit() and s != '0':
return s
else:
return None

def func4(s):
if str(s['j']).isalpha() and str(s['k']).isdigit() and s['l'] is none:
return s['k']

并这样称呼他们。

x['a'] = x['b'].apply(lambda x: func1(x) if pd.notnull(x) else x)
x['c'] = x['d'].apply(lambda x: func2(x) if pd.notnull(x) else x)
x['e'] = x['f'].apply(lambda x: func3(x) if pd.notnull(x) else x)
x['g'] = x.apply(lambda x: func4(x), axis = 1)

这里一切都很好,但是我已经编写了近 50 个这样的函数,并且我的数据集有超过 1000 万条记录。脚本运行几个小时,如果我的理解是正确的,这些函数是按行调用的,因此每个函数被调用的次数与行数一样多,并且需要很长时间来处理它。有没有办法优化这个?我怎样才能以更好的方式处理这个问题?可能不是通过apply函数?谢谢。

示例数据集:-

        Name                               f    j    b
339043 Moir Point RD 3 0
21880 Fisher-Point Drive Freemans Ba 6 0
457170 Whakamoenga Point 29 0
318399 Motukaraka Point RD 0 0
274047 Apirana Avenue Point England 360 0 366
207588 Hobsonville Point RD 127 0
747136 Dog Point RD 130 0
325704 Aroha Road Te Arai Point 36 0
291888 One Tree Point RD 960 0
207954 Hobsonville Point RD 160 0 205D
248410 Huia Road Point Chevalier 106 0

最佳答案

一般来说,您应该避免调用 .applyDataFrame上。这才是你真正想要的。在幕后,它正在创建一个新的 Series对于 DataFrame 中的每一行并将其发送到传递给 .apply 的函数。不用说,每行的开销相当大,因此 .apply已满DataFrame是慢的。

在下面的示例中,由于示例数据有限,我重命名了函数调用中的一些列。

import sys
import time
import contextlib
import pandas as pd

@contextlib.contextmanager
def timethis(label):
'''A context manager to time a bit of code.'''
print('Timing', label, end=': ')
sys.stdout.flush()
start = time.time()
yield
print('{:.4g} seconds'.format(time.time() - start))

... func1, func2, and func3 definitions...

def func4(s):
if str(s['j']).isalpha() and str(s['f']).isdigit() and s['b'] is none:
return s['f']

x = pd.DataFrame({'f': [3, 6, 29, 0, 360, 127, 130, 36, 960, 160, 106],
'j': 0,
'b': [None, None, None, None, 366, None, None, None, None, '205D', None]})
x = pd.concat(x for _ in range(100000))
y = x.copy()

x['a'] = x['b'].apply(lambda x: func1(x) if pd.notnull(x) else x)
x['c'] = x['j'].apply(lambda x: func2(x) if pd.notnull(x) else x)
x['e'] = x['f'].apply(lambda x: func3(x) if pd.notnull(x) else x)
with timethis('func4'):
x['g'] = x.apply(func4, axis = 1) # The lambda in your example was not needed

...

def vectorized_func4(df):
'''Accept the whole DataFrame and not just a single row.'''
j_isalpha = df['j'].astype(str).str.isalpha()
f_isdigit = df['f'].astype(str).str.isdigit()
b_None = df['b'].isnull()
ret_col = df['f'].copy()
keep_rows = j_isalpha & f_isdigit & b_None
ret_col[~keep_rows] = None
return ret_col

y['a'] = vectorized_func1(y['b'])
y['c'] = vectorized_func2(y['j'])
y['e'] = vectorized_func3(y['f'])
with timethis('vectorized_func4'):
y['g'] = vectorized_func4(y)

输出:

Timing func4: 115.9 seconds
Timing vectorized_func4: 25.09 seconds

事实证明,对于 func1 , func2 ,和func3与矢量化方法相比,它的性能是一个缺陷。 .apply (和 .map 就此而言)在 Series 上并没有那么慢,因为每个元素没有额外的开销。但是,这并不意味着您应该只使用 .apply当你有 Series并且不研究 Series 的矢量化内置方法- 通常情况下,您可能能够做得比 apply 更好.

您可以这样重写 func3进行矢量化(我添加了计时语句,以便我们可以看到什么花费了最多的时间)。

def vectorized_func3(col):
with timethis('fillna'):
col = col.fillna('')
with timethis('astype'):
col = col.astype(str)
with timethis('rest'):
is_digit_string = col.str.isdigit()
not_0_string = col != '0'
keep_rows = is_digit_string & not_0_string
col[~keep_rows] = None
return col

这是与 func3 相比的时间安排:

Timing func3: 8.302 seconds
Timing fillna: 0.006584 seconds
Timing astype: 9.445 seconds
Timing rest: 1.65 seconds

仅仅更改 dtype 就需要很长时间的Series ,自从有了新的 Series必须创建,然后每个元素都会被强制转换。其他一切都炽热。如果您可以更改算法以不需要将数据类型更改为 str ,或者可以简单地存储为 str首先,矢量化方法会快得多(尤其是 vectorized_func4 )。

外卖

  • 请勿使用.apply完整DataFrame除非你绝对必须这样做。如果你认为必须这样做,那就去喝杯咖啡,思考十分钟,然后尝试想出一种无需 .apply 就能做到的方法。 .
  • 尽量不要使用.applySeries上,你可能可以做得更好,但不会像完整的DataFrame那么糟糕。 .
  • 尝试提出一种不需要不断转换的算法 dtype .

关于python - 加速Python应用行明智函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45080003/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com