векторизация с сериями панд - множественная «сложная» логическая категоризация - оптимизация времени выполнения - PullRequest
0 голосов
/ 26 октября 2018

Поскольку я обрабатываю все больше и больше данных, функция применения, которую я использую, теперь замедляет мои проекты. Я очень часто использую векторизацию в своей работе, но для какой-то функции я попробовал безуспешно (пока).

Вопрос: Как векторизовать эту функцию, содержащую множественное решение?

Здесь вы найдете неоптимизированный пример кода (с использованием 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)) 

Это займет 16 секунд, чтобы обработать 100 тыс. Строк.

Результат должен выглядеть примерно так:

df.eat_cat => 0 cat5 1 кат5 2 кат3 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 голосов
/ 26 октября 2018

Я нашел способ пойти в 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 секунд (с применением). Я надеюсь, что это поможет другим, кто борется со мной в этом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...