如何删除双层索引DataFrame中每个外层索引对应的首行?
如何删除多层索引DataFrame中每个外层索引对应的首行
我来帮你解决这个多层索引DataFrame的行删除问题!首先先明确你的需求:你有一个双层索引的DataFrame,外层索引是names列表中的字符串,内层是datetime类型,想要删除每个外层索引分组下的第一行。
先重现你的示例场景
先构造出你提到的初始DataFrame:
import pandas as pd # 构造示例数据 data = { 'val1': [2.3, 3.6, 5.7, 7.2], 'val2': [5.4, 8.2, 1.3, 3.8], 'name': ['Tom', 'Tom', 'Jerry', 'Jerry'], 'date': ['2018-01-01', '2018-01-02', '2018-02-18', '2018-02-19'] } df = pd.DataFrame(data).set_index(['name', 'date']) print(df)
输出结果:
val1 val2 name date Tom 2018-01-01 2.3 5.4 2018-01-02 3.6 8.2 Jerry 2018-02-18 5.7 1.3 2018-02-19 7.2 3.8
你的目标是得到每个外层索引去掉首行后的结果:
val1 val2 name date Tom 2018-01-02 3.6 8.2 Jerry 2018-02-19 7.2 3.8
分析你原来代码的问题
你尝试用循环遍历names,然后对df.loc[name]执行drop并设置inplace=True,但这里df.loc[name]返回的是原DataFrame的副本(或视图,取决于数据结构),修改这个副本不会影响原DataFrame,所以原数据不会有变化。
推荐的解决方案
这里给你三种可行的方法,按需选择:
方法1:用groupby.tail()(最简洁高效)
利用groupby按外层索引分组,然后用tail(1)获取每个组的最后一行(也就是去掉第一行),这个方法性能最优,代码最简洁:
df = df.groupby(level='name').tail(1)
方法2:用groupby.apply()(更灵活)
如果你的分组可能有不同行数(比如有的组有3行,想保留后面所有行),可以用apply结合iloc[1:]跳过第一行:
df = df.groupby(level='name').apply(lambda x: x.iloc[1:]).reset_index(level=0, drop=True)
这里reset_index(level=0, drop=True)是为了去掉apply后额外添加的外层索引层级,让结构回到原来的双层索引。
方法3:修正你的循环方法
如果你还是想用循环,可以直接在原DataFrame上删除对应的双层索引行:
names = ['Tom', 'Jerry'] for name in names: # 获取当前name对应的第一个内层索引 first_inner_idx = df.loc[name].index[0] # 从原DataFrame中删除这个双层索引对应的行 df = df.drop((name, first_inner_idx))
这个方法更直观,适合需要对每个组做自定义处理的场景,但如果数据量很大,性能不如前两种方法。
验证结果
不管用哪种方法,最终输出的DataFrame都会是你想要的目标结果。
内容的提问来源于stack exchange,提问作者KOB
相关产品推荐
相关产品推荐

