Поиск дубликатов в датафреймах большого объёма

Коллеги, добрый день!
Появилась следующая задача: имеется датафрейм большого объёма, который включает в себя ФИО клиента и программу, по которой он пришел. Мне необходимо сравнить df_1 и df_2, и, тем самым, выявить тех, кто был до НГ, и тех, кто пришел повторно после НГ.
Пытался с помощью #s1 = pd.merge(df_1, df_2, how='inner', on=['Отбор:']) , но collab просто выдает ошибку о превышении объёма ОЗУ.

Ниже представлен пример фрейма данных.

Indx        Отбор:
201 Павловский Александр Танцыс
202 Штраф за задержку в клубе
203 Посещение 2 часа
204 Посещение 2 часа (Выходные дни)
205 Посещение 3 часа (Выходные дни)
206 Татинцян Оганес Валерьевич
207 Штраф за задержку в клубе
208 Посещение 2 часа
209 Посещение 1 час
210 Посещение 1 час (Выходные дни)
211 Посещение 2 часа (Выходные дни)
212 Шмелев Владислав
213 Штраф за задержку в клубе
214 Посещение 2 часа (Выходные дни)
215 Посещение 3 часа (Выходные дни)
216 Агафонов Алексей Владимирович
217 Штраф за задержку в клубе
218 Посещение 1 час
219 Посещение 1 час (Выходные дни)
220 Посещение 2 часа
221 Афанасьев Николай Максимович
222 Штраф за задержку в клубе
223 Посещение 1 час
224 Посещение 1 час (Выходные дни)
225 Иванова Мария Александровна
226 Штраф за задержку в клубе
227 Посещение 1 час
228 Посещение 1 час (Выходные дни)
229 Посещение 2 часа

В общем и целом мне необходимо найти совпадения ФИО в двух фреймах данных. Датафреймы ничем не отличаются, только периодом времени.


Ответы (2 шт):

Автор решения: CrazyElf
  1. Работайте только с интересующим вас столбцом данных, вы наверняка мержите датафреймы, где много других столбцов, при этом сами эти столбцы вам не нужны на данном этапе. После получения нужного списка ФИО вы по нему сможете отобрать нужные строки из датафреймов.
  2. У вас там в столбце не только ФИО, но и какие-то служебные записи. Попробуйте отфильтровать лишние записи по ключевым словам, оставить таким образом только ФИО.
  3. Возьмите из столбца список уникальных значений через .unique(). Дальше, как вам уже посоветовали в комментариях, можете сделать из этого списка множество и в зависимости от ваших задач пересекать такие множества, складывать, вычитать...

Всё это позволит очень сильно сэкономить используемую память, если делать всё в правильном порядке.

Более конкретно с кодом вам или я или кто-то другой может ответить, если вы предоставите воспроизводимый пример данных, т.е. либо файлы с данными, либо код, который можно запустить и получить датафреймы, похожие на ваши по структуре.

→ Ссылка
Автор решения: Alexey Trukhanov

Я предполагаю, что проблема в следующем. У Вас в датафрейме, точнее в одной колонке, которую Вы пытаетесь мержить, содержаться одинаковые значения, в большом количестве (служебные строки), которые, судя по всему, содержаться и в первом и во втором датафрейме. В этом случае логика поведения pd.merge такова, что она добавляет эти повторяющиеся значения в результирующий датафрейм в количестве m*n, где m и n - количество повторений одного и того же значения в первом и втором датафрейме. В результате этого Ваш результирующий датафрейм разнесет до неимоверных размеров и он не влезет ни в какую память.

Поэтому, Вот шаги, которые можно предпринять, чтобы избавится от проблемы:

1. Очистить оба датафрейма от служебных строк:

df_only_names = df[~df['Отбор:'].str.contains('Штраф|Посещение', regex=True)]

Тут надо следить, чтобы нам не попался какой-нибудь Антон Петрович Штраф(-кин|-ков)

2.1 После этого применить merge так как Вы его и применяли.

или

2.2 Сделать из обеих колонок ['Отбор:'] множества и получить их пересечение:

names = set(df_1['Отбор:']) & set(df_2['Отбор:'])

3. Если же Ваш датасет настолько огромен, что очистка датафрейма все равно не поможет (а это будет существенная экономия памяти) и Вы все равно будете получать переполнение, то тогда останется разбивать все данные на срезы (в простом случае - только один из датафреймов, в сложном - оба) и сравнивать кусками в цикле(-ах).

Но все эти советы актуальны в том случае, если Вам нужен просто список ФИО, а не ФИО + служебная информация.

→ Ссылка