首页 > 解决方案 > 在 Pandas 中使用整数有效地切片非整数多级索引

问题描述

以下代码生成具有多级索引的示例 DataFrame。第一层是a string,第二层是a datetime

脚本

import pandas as pd
from datetime import datetime
import random

df = pd.DataFrame(columns=['network','time','active_clients','throughput','speed'])
networks = ['ALPHA','BETA','GAMMA']
times = pd.date_range(datetime.strptime('2021-01-01 00:00:00','%Y-%m-%d %H:%M:%S'),datetime.strptime('2021-01-01 12:00:00','%Y-%m-%d %H:%M:%S'),7).tolist()

for n in networks:
    for t in times:
        df = df.append({'network':n,'time':t,'active_clients':random.randint(10,30),'throughput':random.randint(1500,5000),'speed':random.randint(10000,12000)},ignore_index=True)

df.set_index(['network','time'],inplace=True)

print(df.to_string())

输出

                            active_clients throughput  speed
network time                                                
ALPHA   2021-01-01 00:00:00             16       4044  11023
        2021-01-01 02:00:00             17       2966  10933
        2021-01-01 04:00:00             10       4649  11981
        2021-01-01 06:00:00             23       3629  10113
        2021-01-01 08:00:00             30       2520  11159
        2021-01-01 10:00:00             10       4200  11309
        2021-01-01 12:00:00             16       3878  11366
BETA    2021-01-01 00:00:00             17       3073  11798
        2021-01-01 02:00:00             20       1941  10640
        2021-01-01 04:00:00             17       1980  11869
        2021-01-01 06:00:00             23       3346  10002
        2021-01-01 08:00:00             10       1952  10063
        2021-01-01 10:00:00             28       3788  11047
        2021-01-01 12:00:00             24       4993  10487
GAMMA   2021-01-01 00:00:00             21       4366  11587
        2021-01-01 02:00:00             22       3404  11669
        2021-01-01 04:00:00             20       1608  10344
        2021-01-01 06:00:00             28       1849  10278
        2021-01-01 08:00:00             14       3229  11925
        2021-01-01 10:00:00             21       3408  10411
        2021-01-01 12:00:00             12       1799  10492

对于第一级中的每个项目,我想选择第二级中的最后三个记录。问题是我不知道这些datetime值,所以我需要通过基于整数的索引位置来选择。对 DataFrame 进行切片以实现以下目标的最有效方法是什么。

期望的输出

                            active_clients throughput  speed
network time                                                
ALPHA   2021-01-01 08:00:00             30       2520  11159
        2021-01-01 10:00:00             10       4200  11309
        2021-01-01 12:00:00             16       3878  11366
BETA    2021-01-01 08:00:00             10       1952  10063
        2021-01-01 10:00:00             28       3788  11047
        2021-01-01 12:00:00             24       4993  10487
GAMMA   2021-01-01 08:00:00             14       3229  11925
        2021-01-01 10:00:00             21       3408  10411
        2021-01-01 12:00:00             12       1799  10492

我的尝试

返回完整的数据框:

df_sel = df.iloc[:,-3:]

引发错误,因为loc不支持在datetime对象上使用整数值:

df_sel = df.loc[:,-3:]

返回第二级的最后三个条目,但只返回第一级的最后一个条目:

df_sel = df.loc[:].iloc[-3:]

标签: pythonpandasdataframe

解决方案


我有两种方法可以解决这个问题:

方法 1:正如 Quang Hoang 的第一条评论中提到的,您可以使用 groupby 来执行此操作,我相信它的代码最短:

df.groupby(level=0).tail(3)

方法2:您也可以将网络中的每个切片然后连接它们:

pd.concat([df.loc[[i]][-3:] for i in networks])

这两种方法都会输出你想要的结果: 在此处输入图像描述


推荐阅读