Удалите индекс из фрейма данных MultiIndex, если у дочернего индекса есть критерий соответствия значения столбца

1

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

Учитывая следующий пример: MultiIndex:

import pandas as pd
import numpy as np

first = ['A', 'B', 'C']
second = ['a', 'b', 'c', 'd']
third = ['1', '2', '3']

indices = [first, second, third]

index = pd.MultiIndex.from_product(indices, names=['first', 'second', 'third'])

df = pd.DataFrame(np.random.randint(10, size=(len(first)*len(second)*len(third), 4)), index=index, columns=['Val1','Val2',' Val3', 'Val4'])

Цель: Я хотел бы сохранить определенный level=1 индекс (например, 'a'), если значение столбца 'Val2' соответствующее индексу 1 в level=2, больше 5 для этого level=1 индекс. Поэтому, если этот критерий не выполняется (т.е. столбец 'Val2' меньше или равен 5 для индекса 1 на level=2), то соответствующий level=1 индекс будет удален из кадра данных. Если все показатели level=1 не соответствуют критериям для заданного level=0, то этот level=0 также будет удален. Мой предыдущий пост содержит мой ожидаемый результат (я могу добавить его здесь, но я хотел, чтобы этот пост был максимально кратким для ясности).

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

grouped = df.groupby(level=0)

output = pd.concat([grouped.get_group(key).groupby(level=1).filter(lambda x: (x.loc[pd.IndexSlice[:, :, '1'], 'Val2']>5).any()) for key, group in grouped])

Это действительно дает мой желаемый результат, но для кадра данных с 100 000 строк производительность невысока. Есть ли что-то очевидное, чего я не вижу здесь, чтобы лучше использовать оптимизацию pandas под капотом?

Теги:
pandas
pandas-groupby
multi-index

1 ответ

1
Лучший ответ

Я получил тот же результат, что и ваше примерное решение, выполнив следующие действия:

df.loc[df.xs('1', level=2)['Val2'] > 5]

Сравнивая производительность по времени, это на ~ 15 раз быстрее (на моей машине ваш пример занимает 36 мс, а это занимает 2 мс).

  • 0
    Отличный ответ, именно то, что я искал. Спасибо!

Ещё вопросы

Сообщество Overcoder
Наверх
Меню