提高非常慢的python代码的执行时间

2024-09-27 07:25:06 发布

您现在位置:Python中文网/ 问答频道 /正文

这是我的第一篇文章,请耐心等待。我需要一些帮助来优化下面的一行

pd_df.loc[flag, 'COL_{}'.format(col_number)] = pd_df.loc[flag,'COL{}'.format(col_number)].apply(lambda x: x + str(userid) + "@")

pd_df:Panda数据帧包含2M行

flag=numpy一维布尔数组,一次过滤/更新pd_df中的多行

COL_{}.format(COL_number)=根据循环(如COL_1、COL_5到COL_15)的主列的随机列数(长度为5000个字符的数据类型字符串)

一般来说,这段代码的作用是,首先根据要更新的标志和列(根据列号)过滤要更新的行,然后在这些多行和单列中附加用户id列表,并使用@作为分隔符。例如@userid1@userid2@userid2等等

由于pandas数据帧loc功能较慢,行数较多,例如2M,这行代码占用了我总时间的75%

有人能帮我把这篇文章转换成更优化的方式,比如dictionary/numpy数据类型吗

下面是代码正在创建的上面的输出。根据与国家和类别相关的用户id,其用户id将附加到该列编号。假设Col_1最多可以包含userid3,column2最多可以包含userid7,以此类推,直到col15

enter image description here

提前谢谢

问候,, 利瓦


Tags: 数据代码用户numpyidformatnumberdf
3条回答

同意apply()可以很慢。您希望尽可能利用矢量化操作。尝试使用连接运算符(+)。这能更快吗

pd_df.loc[flag, 'COL_{}'.format(col_number)] = pd_df.loc[flag,'COL{}'.format(col_number)] + (str(userid) + "@")

此外,不确定这是否有帮助,但其中一些字符串应该预先计算(可能Python已经在缓存它们,但万一没有):

col_name = 'COL_{}'.format(col_number)
suffix = str(userid) + "@"
pd_df.loc[flag, col_name] = pd_df.loc[flag, col_name] + suffix

有两点:

  1. f-strings始终比str.format快,请尽可能使用它们:

    In [3]: fmt = "{foo}"
    In [4]: %timeit fmt.format(foo=5)
    299 ns ± 21.7 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
    In [5]: foo = 5
    In [6]: %timeit f"{foo}"
    79.2 ns ± 2.31 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
    
  2. 似乎userid独立于数据帧,我不确定为什么要使用apply,只需使用broadcasting

    In [8]: userid = "abcdef"
    In [9]: pd.Series('abc def ghi jkl'.split()) + f'@{userid}'
    Out[9]:
    0    abc@abcdef
    1    def@abcdef
    2    ghi@abcdef
    3    jkl@abcdef
    dtype: object
    

所以最后的方法可能是这样的:

for num in range(5):
    flag = ... # calculate flag
    df[flag, f"col_{num}"] = df[flag, f"col_{num}"] + f"@{userid}"

apply是对每个项运行函数的较慢方式之一

pd_df.loc[flag, f’COL_{col_number}’] = pd_df.loc[flag, f’COL_{col_number}’].map(lambda x: f’{x}{userid}@‘)

相关问题 更多 >

    热门问题