首页 > 解决方案 > 从 Pandas DataFrame 中删除许多索引范围

问题描述

问题+ MWE

如何从具有(两级)多索引的 Pandas DataFrame 中删除/删除多个行范围,如下所示:

idx1    idx2  |  value(s)   ...
------------------------------------------
4       0     |  1.123456   ...
        1     |  2.234567   ...
        2     |  0.012345   ...
8       0     | -1.123456   ...
        1     | -0.973915   ...
        2     |  1.285553   ...
        3     | -0.194625   ...
        4     | -0.144112   ...
...     ...   | ...         ...

要删除/删除的范围当前位于如下列表中:

ranges = [[(4, 1), (4, 2)],          # range (4,1):(4,2)
          [(8, 0), (8, 3)],          # range (8,0):(8,3)
          [(8, 5), (8, 10)], ...]    # range (8,5):(8,10)

主要问题是,我发现的大多数方法都不支持多索引或切片或多个切片/范围。

最好/最快的方法是什么。

当前丑陋的解决方案

for range in ranges:
    df = df.drop(df.loc[range[0]:range[1]].index)

缓慢而丑陋,但它是我发现的唯一可行的解​​决方案,它结合了多索引、切片和多个范围(通过循环范围)。

方案比较

所有三个提议的解决方案都有效。他们都通过将切片列表转换为这些切片中所有单个元组的列表来解决问题。

切片以完成一组元组

最快的方法是@ALollz 解决方案:

idx = [(x, z) for (x, i), (_, j) in ranges for z in np.arange(i,j+1,1)]

表现

关于删除行,所有解决方案都有效,但性能存在很大差异(所有性能数据均基于我的数据集,包含约 10 个 Mio. 条目)

  1. @ALollz + @Ben。T 的组合解决方案~19 秒

    df.drop(pd.MultiIndex.from_tuples(idx))
    

    或不创建MultiIndex对象

    df.drop(idx)
    
  2. @ALollz 第一个解决方案~75 秒。

    df.loc[list(set(df.index.values) - set(idx))]
    
  3. @user3471881 的解决方案~95 秒

    df.loc[~df.index.isin(ranges)]
    
  4. 我丑陋的解决方案(〜350秒。

    see above
    

标签: pythonpandas

解决方案


您可以创建一个新的索引列表,正如 Ben.T 指出的那样,只需删除它们。

import numpy as np
import pandas as pd

idx = [(x, z) for (x, i), (_, j) in ranges for z in np.arange(i,j+1,1)]
df.drop(pd.MultiIndex.from_tuples(idx))

输出:

           value(s)
idx1 idx2          
4    0            4
8    4           11

推荐阅读