Я изначально задал этот вопрос здесь, и я считаю, что он был неправильно обозначен как дубликат. Я сделаю все возможное, чтобы прояснить мой вопрос и как я считаю, что он уникален.
Учитывая следующий пример: 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
под капотом?
Я получил тот же результат, что и ваше примерное решение, выполнив следующие действия:
df.loc[df.xs('1', level=2)['Val2'] > 5]
Сравнивая производительность по времени, это на ~ 15 раз быстрее (на моей машине ваш пример занимает 36 мс, а это занимает 2 мс).