【发布时间】:2019-11-15 04:25:48
【问题描述】:
我有一个 3 级 MultiIndex 数据框,我想对其进行切片,以便保留满足某个条件之前的所有值。举个例子,我有以下数据框:
Col1 Col2
Date Range Label
'2018-08-01' 1 A 900 815
B 850 820
C 800 820
D 950 840
2 A 900 820
B 750 850
C 850 820
D 850 800
我想选择所有值,直到 Col1 变得小于 Col2。一旦我有一个 Col1
Col1 Col2
Date Range Label
'2018-08-01' 1 A 900 815
B 850 820
2 A 900 820
我尝试了几个选项,但我还没有找到一个好的解决方案。我可以轻松地保留 Col1 > Col2 的所有数据:
df_new=df[df['Col1']>df['Col2']]
但这不是我需要的。我也一直在考虑循环遍历 1 级索引并使用 pd.IndexSlice 对数据帧进行切片:
idx = pd.IndexSlice
idx_lev1=df.index.get_level_values(1).unique()
for j in (idx_lev1):
df_lev1=df.loc[idx[:,j,:],:]
idxs=df_lev1.index.get_level_values(2)[np.where(df_lev1['Col1']<df_lev1['Col2'])[0][0]-1]
df_sliced= df_lev1.loc[idx[:,:,:idxs],:]
然后连接各种数据帧。 但是,这效率不高(我的数据框有超过 300 万个条目,所以这也是我必须考虑的问题)而且我的问题是范围索引在不同的日期重复,所以我可能不得不嵌套 2 个周期或类似的东西。
我确信一定有一个简单且更 Python 的解决方案,但我无法找到解决此问题的方法。
如果您想生成上面的数据框进行测试,您可以使用:
from io import StringIO
s="""
Date Range Label Col1 Col2
'2018-08-01' 1 A 900 815
'2018-08-01' 1 B 850 820
'2018-08-01' 1 C 800 820
'2018-08-01' 1 D 950 840
'2018-08-01' 2 A 900 820
'2018-08-01' 2 B 750 850
'2018-08-01' 2 C 850 820
'2018-08-01' 2 D 850 800
"""
df2 = pd.read_csv(StringIO(s),
sep='\s+',
index_col=['Date','Range','Label'])
更新:
我尝试实现 Adam.Er8 和 Alexandre B. 的解决方案,它们与我为 SO 创建的测试数据框工作正常,但不适用于真实数据。
问题是可能存在 Col1 值总是大于 Col2 的实例,在这种情况下,我只想保留所有数据。目前提出的解决方案都不能真正解决这个问题。
对于更真实的测试用例,您可以使用以下示例:
s="""
Date Range Label Col1 Col2
'2018-08-01' 1 1 900 815
'2018-08-01' 1 2 950 820
'2018-08-01' 1 3 900 820
'2018-08-01' 1 4 950 840
'2018-08-01' 2 1 900 820
'2018-08-01' 2 2 750 850
'2018-08-01' 2 3 850 820
'2018-08-01' 2 4 850 800
'2018-08-02' 1 1 900 815
'2018-08-02' 1 2 850 820
'2018-08-02' 1 3 800 820
'2018-08-02' 1 4 950 840
'2018-08-02' 2 1 900 820
'2018-08-02' 2 2 750 850
'2018-08-02' 2 3 850 820
'2018-08-02' 2 4 850 800
"""
或者,您可以从here 下载 hdf 文件。这是我真正使用的数据框的一个子集。
【问题讨论】:
标签: python pandas slice multi-index