Вопрос + MWE
Как я могу удалить / удалить несколько диапазонов строк из Pandas DataFrame с многоуровневым (двухуровневым) индексом, похожим на это:
idx1 idx2 | value(s) ...
------------------------------------------
4 0 | 1.123456 ...
1 | 2.234567 ...
2 | 0.012345 ...
8 0 | -1.123456 ...
1 | -0.973915 ...
2 | 1.285553 ...
3 | -0.194625 ...
4 | -0.144112 ...
... ... | ... ...
Диапазоны дляdrop / remove в настоящее время находятся в списке, подобном следующему:
ranges = [[(4, 1), (4, 2)], # range (4,1):(4,2)
[(8, 0), (8, 3)], # range (8,0):(8,3)
[(8, 5), (8, 10)], ...] # range (8,5):(8,10)
Основная проблема заключается в том, что большинство методов, которые я обнаружил, не поддерживают ни мультииндексацию, ни секцию, ни несколько секций / диапазонов.
Какой самый лучший / быстрый способ сделать это.
Текущее уродливое решение
for range in ranges:
df = df.drop(df.loc[range[0]:range[1]].index)
Медленно и некрасиво, но это единственное работоспособное решение, которое я нашел, объединяющее мультииндексацию,нарезка и в некотором смысле несколько диапазонов (путем циклического перебора диапазонов).
Сравнение решений
Все три предложенных решения работают.Все они решают проблему путем преобразования списка срезов в список всех отдельных кортежей в этом срезе.
Срезы для полного набора кортежей
Самый быстрый способ сделать это - решение @ALollz:
idx = [(x, z) for (x, i), (_, j) in ranges for z in np.arange(i,j+1,1)]
Производительность
Что касается удаления строк, все решения работают, но есть большая разница в производительности (все данные о производительности основаны на моем наборе данных с ~ 10 млн записей)
@ ALollz + @Ben.Объединенное решение T ( ~ 19 сек. )
df.drop(pd.MultiIndex.from_tuples(idx))
или без создания MultiIndex
объекта
df.drop(idx)
@ Первое решение ALollz ( ~ 75 сек. )
df.loc[list(set(df.index.values) - set(idx))]
@ решение user3471881 (~ 95 сек. )
df.loc[~df.index.isin(ranges)]
мой уродливый раствор ( ~ 350 сек. )
see above