July 16, 2022

Ловушка сэмлирования, приводящая к размножению повторных индексов

Рассмотрим пример проблемы, возникающей в результате неаккуратной работы с индексами Pandas объектов. Пусть имеются две взаимосвязанные колонки ser1, ser2. Допустим, нам надо сэмплировать несколько строк из первой серии и упорядочить строки второй серии в том же порядке:

import pandas as pd
ser1 = pd.Series([1,2,3,4,5], index=[1,2,3,4,5])
ser2 = pd.Series([11,22,33,44,55], index=[1,2,3,4,5])

ser1_resampled = ser1.sample(6, replace=True, random_state=123)
ser1_resampled
ser2_resampled = ser2[ser1_resampled.index]
ser2_resampled

Как и ожидалось, появились повторяющиеся индексы. Обратите внимание на интересное поведение при обращении по ним:

ser2_resampled[[3,3]]

То есть при обращении по повторяющемуся индексу вы получите кратное количество всех его вхождений.

Пусть теперь надо из ser1_resampled выбрать n строк в позициях с наибольшими значениями в ser2_resampled. На первый взгляд кажутся применимыми следующие два подхода:

  • отсортировать ser2_resampled, затем выбрать индексы n первых строк и сделать выборку по ним;
  • отсортировать ser2_resampled, проиндексировать ser1_resampled по индексам ser2_resampled и потом выбрать n первых элементов.

Однако из-за повторов в каждом из кейсов результат получится неожиданным:

n=6
idx = ser2_resampled.sort_values(ascending=False).index

ser1_resampled[idx[:n]]

То есть вместо ожидаемых 6 строк получили 12. А во втором случае получится так:

ser1_resampled[idx][:n]

Оба варианта являются неправильными, так как у нас появились строки, отсутствовавшие в первоисточнике (например, стольких дублей троек не было). А корректно было сделать то же самое, только предварительно сбросив индексы:

ser1_resampled = ser1_resampled.reset_index(drop=True)
ser2_resampled = ser2_resampled.reset_index(drop=True)

n=6
idx = ser2_resampled.sort_values(ascending=False).index

ser1_resampled[idx[:n]]
ser1_resampled[idx][:n]

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

Не пропустите ничего интересного и подписывайтесь на страницы канала в других социальных сетях:

Яндекс Дзен

Telegram