Выбор 2-го уровня MultiIndex Pandas DataFrame в качестве индексатора - PullRequest
1 голос
/ 20 февраля 2020

У меня есть pandas DataFrame с мультииндексом, где я хочу выбрать все строки с 11:00 до 13:00.

import pandas as pd

data = [
    ('Jack', '2020-01-01 10:00:00', 12),
    ('Jack', '2020-01-01 11:00:00', 13),
    ('Jack', '2020-01-01 12:00:00', 14),
    ('Jack', '2020-01-01 13:00:00', 15),
    ('Jack', '2020-01-01 14:00:00', 16),
    ('Ryan', '2020-01-01 10:00:00', 34),
    ('Ryan', '2020-01-01 11:00:00', 35),
    ('Ryan', '2020-01-01 12:00:00', 36),
    ('Ryan', '2020-01-01 13:00:00', 37),
    ('Ryan', '2020-01-01 14:00:00', 38),
]
df = pd.DataFrame(data, columns=['name', 'datetime', 'score']).set_index(['name','datetime'])
#                           score
# name datetime                  
# Jack 2020-01-01 10:00:00     12
#      2020-01-01 11:00:00     13
#      2020-01-01 12:00:00     14
#      2020-01-01 13:00:00     15
#      2020-01-01 14:00:00     16
# Ryan 2020-01-01 10:00:00     34
#      2020-01-01 11:00:00     35
#      2020-01-01 12:00:00     36
#      2020-01-01 13:00:00     37
#      2020-01-01 14:00:00     38

Мое текущее решение требует преобразования всех мультииндексов в обычные столбцы, преобразования datetime столбец для индексатора, который затем используется для выбора нужных строк. Затем мультииндекс перестраивается.

df = df.reset_index()
indexer = pd.DatetimeIndex(df['datetime'])
df = df.loc[indexer.indexer_between_time('11:00', '13:00')].set_index(['name', 'datetime'])
#                           score
# name datetime                  
# Jack 2020-01-01 11:00:00     13
#      2020-01-01 12:00:00     14
#      2020-01-01 13:00:00     15
# Ryan 2020-01-01 11:00:00     35
#      2020-01-01 12:00:00     36
#      2020-01-01 13:00:00     37

Вопрос: Можно ли напрямую использовать 2-й уровень мультииндекса в качестве индексатора, избегая при этом необходимости reset_index и set_index?

Или есть ли еще лучший способ добиться фильтрации строк между 2 разными периодами?

Я использую Python 3.7.4 и pandas 0.25.1. Готовы перейти на более новые версии, если они допускают лучшие решения

Ответы [ 2 ]

2 голосов
/ 20 февраля 2020

Вы можете использовать индекс напрямую с get_level_values и pd.IndexSlice:

indexer = (pd.DatetimeIndex(df.index.get_level_values('datetime'))
           .indexer_between_time('11:00', '13:00'))
df.loc[pd.IndexSlice[:, df.index.get_level_values('datetime')[indexer]], :]     

                          score
name datetime                  
Jack 2020-01-01 11:00:00     13
     2020-01-01 12:00:00     14
     2020-01-01 13:00:00     15
Ryan 2020-01-01 11:00:00     35
     2020-01-01 12:00:00     36
     2020-01-01 13:00:00     37
0 голосов
/ 20 февраля 2020
df.loc[(slice(None),slice('2020-01-01 11:00:00','2020-01-01 13:00:00')),:]

вывод:

                          score
name datetime                  
Jack 2020-01-01 11:00:00     13
     2020-01-01 12:00:00     14
     2020-01-01 13:00:00     15
Ryan 2020-01-01 11:00:00     35
     2020-01-01 12:00:00     36
     2020-01-01 13:00:00     37
...