Как ускорить вычисление оценки на основе двух строк в фрейме данных Pandas?

TLDR: как можно настроить цикл for для более быстрого выполнения:

import numpy as np
import pandas as pd
import time

np.random.seed(0)

# Given a DataFrame df and a row_index
df = pd.DataFrame(np.random.randint(0, 3, size=(30000, 50)))
target_row_index = 5

start = time.time()

target_row = df.loc[target_row_index]
result = []

# Method 1: Optimize this for-loop
for row in df.iterrows():
    """
    Logic of calculating the variables check and score: 
    if the values for a specific column are 2 for both rows (row/target_row), it should add 1 to the score
    if for one of the rows the value is 1 and for the other 2 for a specific column, it should subtract 1 from the score.
    """
    check = row[1]+target_row  # row[1] takes 30 microseconds per call
    score = np.sum(check == 4) - np.sum(check == 3) # np.sum takes 47 microseconds per call
    result.append(score)

print(time.time()-start)

# Goal: Calculate the list result as efficient as possible

# Method 2: Optimize Apply
def add(a, b):
    check = a + b
    return np.sum(check == 4) - np.sum(check == 3)
    
start = time.time()
q = df.apply(lambda row : add(row, target_row), axis = 1)
print(time.time()-start)

Итак, у меня есть фрейм данных размером 30 000 и целевая строка в этом фрейме данных с заданным индексом строки. Теперь я хочу сравнить эту строку со всеми другими строками в наборе данных, вычислив оценку. Оценка рассчитывается следующим образом:

  1. если значения для определенного столбца равны 2 для обеих строк, он должен добавить 1 к оценке
  2. если для одной из строк значение равно 1, а для другой 2 для определенного столбца, из оценки следует вычесть 1.

Результатом будет список всех оценок, которые мы только что подсчитали.

Поскольку мне нужно выполнять этот код довольно часто, я хотел бы оптимизировать его для повышения производительности. Любая помощь очень ценится.

Я уже прочитал Оптимизация при использовании Pandas. Можете ли вы порекомендовать дополнительные ресурсы? Спасибо

Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно...
Flatpickr: простой модуль календаря для вашего приложения на React
Flatpickr: простой модуль календаря для вашего приложения на React
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей....
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Клиент для URL-адресов, cURL, позволяет взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL.
Четыре эффективных способа центрирования блочных элементов в CSS
Четыре эффективных способа центрирования блочных элементов в CSS
У каждого из нас бывали случаи, когда нам нужно отцентрировать блочный элемент, но мы не знаем, как это сделать. Даже если мы реализуем какой-то...
0
0
20
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Если вы хотите преобразовать свой df в массив NumPy, у NumPy есть действительно хорошая векторизация, которая поможет. Мой код с использованием NumPy выглядит следующим образом:

df = pd.DataFrame(np.random.randint(0, 3, size=(30000, 50)))
target_row_index = 5

start_time = time.time()

# Converting stuff to NumPy arrays
target_row = df.loc[target_row_index].to_numpy()
np_arr = df.to_numpy()

# Calculations
np_arr += target_row
check = np.sum(np_arr == 4, axis=1) - np.sum(np_arr == 3, axis=1)
result = list(check)

end_time = time.time()
print(end_time - start_time)

Ваш полный код (для меня в Google Colab) выводит время 14.875332832336426 s, в то время как приведенный выше код NumPy выводит время 0.018691539764404297 s, и, конечно же, список result одинаков в обоих случаях.

Обратите внимание, что в целом, если ваши расчеты чисто числовые, NumPy практически всегда будет лучше, чем Pandas и цикл for. Pandas действительно хорошо работает со строками и когда вам нужны имена столбцов и строк, но для чистых чисел NumPy — это то, что нужно из-за векторизации.

Другие вопросы по теме