Ловушка сэмлирования, приводящая к размножению повторных индексов
Рассмотрим пример проблемы, возникающей в результате неаккуратной работы с индексами 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]
Как видим, после этого оба подхода дают идентичный и ожидаемый результат.
Не пропустите ничего интересного и подписывайтесь на страницы канала в других социальных сетях: