用熊猫系列进行矢量化-多个“复杂”布尔分类-运行时优化

时间:2018-10-26 12:18:24

标签: python pandas optimization vectorization

随着我处理越来越多的数据,我使用的Apply功能现在对我的项目速度变慢。我确实在工作中经常使用向量化,但是对于某些功能,我尝试仍然没有成功。

问题是: 如何向量化包含多个决策的函数?

请在此处找到未优化的代码示例(使用Apply):

df = pd.DataFrame(np.random.randint(0,1000,size=(100000, 4)), columns=list('ABCD'))

def what_should_eat_that_cat(row):
    start_ = row[0]<=500
    end_ = row[1] <=500  
    miaw = row[2]<=200

    if start_ & end_:
        if miaw:
            return 'cat1'
        else:
            return 'cat2'        
    if start_ & ~end_:
        return 'cat3'   
    if ~start_ & end_:
        return 'cat4'
    else :
        return 'cat5'

start_time = time.time()

df.loc[:,'eat_cat'] = df.loc[:,['A','B','C']].apply(what_should_eat_that_cat,axis=1)

print("--- %s seconds ---" % (time.time() - start_time)) 

处理10万行需要16秒。

结果应该类似于:

df.eat_cat => 0猫5 1只猫5 2猫 3猫5 4猫4

到目前为止,这是我的进度。

def what_should_eat_that_cat(A,B,C):
    start_ = A <=500
    end_ = B <=500  
    miaw = C <=200

    if start_ & end_:
        if miaw:
            return 'cat1'
        else:
            return 'cat2'        
    if start_ & ~end_:
        return 'cat3'   
    if ~start_ & end_:
        return 'cat4'
    else :
        return 'cat5'

df.loc[:,'eat_cat'] = what_should_eat_that_cat(df.A, df.B, df.C)

我收到此错误:系列的真值不明确。使用a.empty,a.bool(),a.item(),a.any()或a.all()。 我明白为什么。但是我仍然不知道如何向量化。

以下是有关向量化的一些文档: https://engineering.upside.com/a-beginners-guide-to-optimizing-pandas-code-for-speed-c09ef2c6a4d6 根据该网站的介绍,此操作的运行速度可能提高了50倍。

1 个答案:

答案 0 :(得分:0)

我找到了将速度提高52倍的方法:

def categ(dataframe):
    start_ = dataframe.A <=500
    end_ = dataframe.B <=500  
    miaw = dataframe.C <=200

    #we treat each case separately in a vectorial way
    dataframe.loc[start_ & end_ & miaw, 'cat'] = 'cat1'
    dataframe.loc[start_ & end_ & ~miaw, 'cat'] = 'cat2'
    dataframe.loc[start_ & ~end_, 'cat'] = 'cat3'
    dataframe.loc[~start_ & end_, 'cat'] = 'cat4'
    dataframe.loc[~start_ & ~end_, 'cat'] = 'cat5'

    return dataframe.cat


df = pd.DataFrame(np.random.randint(0,1000,size=(100000, 4)), columns=list('ABCD'))

start_time = time.time()
df.loc[:,'eat_cat'] = categ (df)
print("--- %s seconds ---" % (time.time() - start_time)) 

这需要0.3秒,而不是16秒(适用)。 我希望这会帮助其他与我一样挣扎的人。