@AlexShilov

Как быстро пройтись по всем строкам в Python Pandas?

Доброго времени суток, друзья. У меня есть более 3 млн. строк в ДатаФрэйме. Мне необходимо взять первого клиента, посмотреть все его операции за каждый месяц, занести все эти операции в другой ДатаФрэйм, добавив некоторые данные на основе операций. И затем так пройтись по всем клиентам. 3 млн. строк - это все операции, всех клиентов.

Как реализовал это я
Я формирую ДатаФрэйм по одному клиента и через itertuples пробегаю по всем его операциям. Затем удаляю все, что связано с этим клиентом из ДатаФрэйма, беру другого и все по накатанной. Но этот алгоритм очень медленный. Может подскажите что можно сделать, чтобы обработать таким образом данные значительно быстрее.


Заранее благодарю!
  • Вопрос задан
  • 542 просмотра
Пригласить эксперта
Ответы на вопрос 3
@zexer
Судя по всему здесь вы создаете однострочный датафрейм, однако можно создать обычную серию (pd.Series)
datareport = pd.DataFrame({'ODATE': {0:0},
                           'TENOR': {0:0},
                           'VDATE': {0:0},
                           'R': {0:0},
                           'RC': {0:0},
                           'DE': {0:0},
                           'I': {0:0},
                           'DEB': {0:0},
                           'D': {0:0}}


Далее вы этот однострочный датафрейм через pd.concat присоединяете к еще одному однострочному датафрейму:
datareport = pd.concat([datareport, pd.DataFrame({'ODATE': {0:row.odate},
                                                          'TENOR': {0:tenor(row.ltt)},
                                                          'VDATE': {0:row.vdate},
                                                          'R': {0:bucket_class_old},
                                                          'RC': {0:buckclass(row.odues)},
                                                          'DE': {0:row.ball},
                                                          'I': {0:0},
                                                          'DEB': {0:ball_old},
                                                          'D': {0:0}})])

а после этого еще раз к одному однострочному датафрейму
datareport = pd.concat([datareport, pd.DataFrame({'ODATE': {0:row.odate},
                                                          'TENOR': {0:tenor(row.ltt)},
                                                          'VDATE': {0:row.vdate},
                                                          'R': {0:bucket_class_old},
                                                          'RC': {0:100},
                                                          'DE': {0:difference},
                                                          'I': {0:0},
                                                          'DEB': {0:ball_old},
                                                          'D': {0:0}})])

Вместо них тоже можно использовать pd.Series.
Данный код отрабатывает в среднем за 2.5 миллисикунды
ser1 = pd.Series({'ODATE': 0,
           'TENOR': 0,
           'VDATE':0,
           'R': 0,
           'RC': 0,
           'DE': 0,
           'I': 0,
           'DEB': 0,
           'D': 0})
ser2 = pd.Series({'ODATE': 0,
           'TENOR': 1,
           'VDATE':2,
           'R': 3,
           'RC': 4,
           'DE': 5,
           'I': 6,
           'DEB': 7,
           'D': 8})
df = pd.concat([ser1, ser2], axis=1).T

В то время как данный код отрабатывает в среднем за 5.2 миллисекунды, при этом результат аналогичен.
datareport1 = pd.DataFrame({'ODATE': {0:0},
                           'TENOR': {0:0},
                           'VDATE': {0:0},
                           'R': {0:0},
                           'RC': {0:0},
                           'DE': {0:0},
                           'I': {0:0},
                           'DEB': {0:0},
                           'D': {0:0}})
datareport2 = pd.DataFrame({'ODATE': {0:1},
                           'TENOR': {0:2},
                           'VDATE': {0:3},
                           'R': {0:4},
                           'RC': {0:5},
                           'DE': {0:6},
                           'I': {0:7},
                           'DEB': {0:8},
                           'D': {0:9}})
df2 = pd.concat([datareport1, datareport2])

Так что можете попробовать выиграть в скорости, перебравшись с однострочных датафреймов на серии.
Ответ написан
Viktor_T2
@Viktor_T2
python developer
Можно попробовать обычную базу данных,
но данные запихнуть в оперативную память.
Проиндексировать по клиенту.
Гуглить "sqlite in memory"
Ответ написан
@AlexShilov Автор вопроса
Единственная на текущий момент оптимизация, которая мне пришла на ум, это убрать операцию конкатенации и вместо ее создать массив типа:
array_data = []

'''
    Тут находиться код программы
'''

array_data.append([row['odate'], tenor(row(ltt)), row['vdate'], bucket_class_old, buckclass(row['odues']), row['ball'], 0, ball_old, 0])
array_data.append([row['odate'], tenor(row(ltt)), row['vdate'], bucket_class_old, 100, difference, 0, ball_old, 0])

'''
    Тут остальной код программы
'''

pandas.DataFrame(array_data)
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы