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 и целевая строка в этом фрейме данных с заданным индексом строки. Теперь я хочу сравнить эту строку со всеми другими строками в наборе данных, вычислив оценку. Оценка рассчитывается следующим образом:
Результатом будет список всех оценок, которые мы только что подсчитали.
Поскольку мне нужно выполнять этот код довольно часто, я хотел бы оптимизировать его для повышения производительности. Любая помощь очень ценится.
Я уже прочитал Оптимизация при использовании Pandas. Можете ли вы порекомендовать дополнительные ресурсы? Спасибо
Если вы хотите преобразовать свой 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
— это то, что нужно из-за векторизации.