【发布时间】:2019-04-22 01:38:49
【问题描述】:
问题 + 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. 条目)
-
@ALollz + @Ben. T's combined solution(~19 秒)
df.drop(pd.MultiIndex.from_tuples(idx))或者不创建
MultiIndex对象df.drop(idx) -
@ALollz first solution(~75 秒)
df.loc[list(set(df.index.values) - set(idx))] -
@user3471881's solution(~95 秒)
df.loc[~df.index.isin(ranges)] -
我的丑陋解决方案(~350 秒)
see above
【问题讨论】:
-
使用
loc有用吗?喜欢this question -
它有效,它是我目前工作的丑陋解决方案的一部分,但它一次只适用于一个范围,如下所示:
df.drop(df.loc[(4,1):(4,2)].index)我还没有找到一种方法来获取多个范围,并且它也很慢......我还将我目前的丑陋解决方案添加到帖子中。 -
你有没有联系过
pd.slice,或者更好的是indexslice? -
是的,它们只是为切片提供了一个更好的界面,并且某些功能要求切片采用
(4, slice(1,2))而不是(4,1):(4,2)的形式,但它们无法让我规避多范围问题. -
您如何构建您的范围列表,它是否需要包含元组列表(成为可切片“范围”的对)或者您是否以这种方式设计它以便使用
loc?