Если вы используете Python для анализа данных и извлечения функций, очень важно понимать негативное влияние зацикливания на производительность. Вот почему так важно найти альтернативные методы и отказаться от циклов.

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

Рассмотрим сценарий, в котором нам предоставляется набор данных об оценках учащихся по всем предметам в классе, и нам нужно выставить оценку на основе следующих критериев:

  • Когда все предметные оценки выше 90, присваивается оценка «Отлично».
  • Когда все предметные оценки ниже 50, присваивается оценка «Ниже среднего».
  • В противном случае оценка «Средняя».
import pandas as pd
import numpy as np

#Function to generate the dataset for the scenario
def Student_data(Size=100):
    Data = pd.DataFrame()
    Data['Student_ID'] = np.arange(1,Size+1)
    Data['English']= np.random.randint(0,100,size=Size)
    Data['Tamil']= np.random.randint(0,100,size=Size)
    Data['Maths']= np.random.randint(0,100,size=Size)
    return Data

Мы случайным образом выбрали оценки по трем предметам из набора данных из 100 студентов, чтобы выставить оценки. Как только набор данных подготовлен, мы можем вызвать функцию данных о студентах и ​​распечатать первые несколько записей, чтобы проверить результаты.

Data = Student_data()
Data.head()

Подход 1 – зацикливание

В этом методе мы будем перебирать каждую строку набора данных и назначать оценку на основе предварительно определенных условий.

def grade(data):
    if (data['English'] > 90) & (data['Tamil'] > 90) & (data['Maths'] > 90):
        return "Excellent"
    if (data['English'] < 50) & (data['Tamil'] < 50) & (data['Maths'] < 50):
        return "Below Average"
    else:
        return "Average"

%%timeit
for i,j in Data.iterrows():
    Data['Grade'] = grade(j)
39.7 ms ± 9.43 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

Как мы видим, мы получили время выполнения 39,7 миллисекунд для перебора 100 записей.

Подход 2 — Применить

В этом методе мы применим функцию «Оценка» непосредственно к фрейму данных и измерим время выполнения для сравнения.

%%timeit
Data['Grade'] = Data.apply(grade,axis=1)
5.18 ms ± 822 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

при таком подходе мы смогли получить гораздо более быстрые результаты со временем выполнения 5 миллисекунд

Подход 3 — векторизация

Это кардинально меняет правила игры: блюдо подается к столу быстрее, чем вы успеваете сказать «Приятного аппетита!».

%%timeit
Data['Grade'] = "Average"
Data.loc[(Data['English'] > 90) & (Data['Tamil'] > 90) 
         & (Data['Maths'] > 90),'Grade'] = "Excellent"
Data.loc[(Data['English'] < 50) & (Data['Tamil'] < 50) 
         & (Data['Maths'] < 50),'Grade'] = "Below Average"
3.23 ms ± 117 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

Очевидно, что этот метод требует наименьшего количества времени по сравнению с тремя другими методами с 3,23 миллисекундами.

Вы можете подумать, что 3,23 миллисекунды против 39 миллисекунд не имеет большого значения, но важно отметить, что эти измерения были сделаны при работе всего со 100 записями. При работе с большими наборами данных, содержащими более 1 миллиона записей, эта разница становится гораздо более существенной.

Позвольте мне показать вам распределение времени выполнения по мере увеличения количества записей. Вы заметите, что при использовании цикла время выполнения имеет тенденцию экспоненциально увеличиваться после 10 000 записей.

Из таблицы видно, что по мере увеличения количества записей производительность метода зацикливания значительно снижается, в то время как методы применения и векторизации остаются относительно стабильными.

При 100 000 записей циклический метод занимает 143 000 миллисекунд, что более чем в 1000 раз медленнее векторизованного метода, который занимает всего 11,4 миллисекунды.

Это подчеркивает важность использования векторизованных методов при работе с большими наборами данных для поддержания эффективной производительности.

Таким образом, при применении операций к фрейму данных в Python есть три основных способа сделать это: использование циклов, использование метода применения и использование векторизованных операций. Зацикливание — это наиболее затратный в вычислительном отношении метод, метод применения быстрее, чем циклы, но медленнее, чем векторизованные операции, а векторизованные операции — это наиболее эффективный способ выполнения операций с фреймом данных.

Дайте мне знать ваши комментарии и следите за новостями…