【问题标题】:Dropping list of rows from multi-level pandas dataframe without a loop从没有循环的多级熊猫数据框中删除行列表
【发布时间】:2019-06-20 22:07:35
【问题描述】:

不借助 for 循环,无法弄清楚如何从具有超过 3 个级别的 pandas 数据框中删除多级行列表。

当明确定义索引中的所有值时,这很好用,回答如下: Pandas Multiindex dataframe remove rows

例如

mask = dfmi.index.isin(( ('A0','B0', 'C0'), ('A2','B3', 'C4') ))
dfmi.loc[~mask,:]

但是当一个人想要接受所有可能的第三级时:

dfmi.index.isin(( ('A0','B0', slice(None)), ('A2','B3', slice(None)) ))

结果 TypeError: unhashable type: 'slice'

目前我正在使用以下代码实现此目的:

import numpy as np
import pandas as pd
def mklbl(prefix, n):
     return ["%s%s" % (prefix, i) for i in range(n)]

miindex = pd.MultiIndex.from_product([mklbl('A', 4),
                                   mklbl('B', 4),
                                   mklbl('C', 10)])

dfmi = pd.DataFrame(np.arange(len(miindex) * 2)
               .reshape((len(miindex), 2)),
                index=miindex).sort_index().sort_index(axis=1)

As = ['A0', 'A2']
Bs = ['B1', 'B3']

for a,b in zip(As, Bs):
    dfmi_drop_idx = dfmi.loc[(a, b, slice(None)), :].index
    dfmi.drop(dfmi_drop_idx, inplace=True, errors='ignore')

【问题讨论】:

  • 您是要删除所有具有这些特定索引值的行,还是只删除与(A0, B1, :)(A2, B3, :) 对应的行?因为你的问题有点不清楚。
  • 我希望只删除行 (A0, B1, :) 和 (A2, B3, :) 的唯一组合。显然,我的完整行组合列表非常大,因此需要避免循环。

标签: python pandas


【解决方案1】:

创建MultiIndex 索引然后删除它

dfmi.drop(pd.MultiIndex.from_arrays([As,Bs]))

【讨论】:

    【解决方案2】:

    drop 在元组列表上应该可以解决问题

    dfmi.drop([*zip(As, Bs)])
    

    为了验证,这是您的代码的修改版本。我们将输出与断言器相等性进行比较。

    from functools import reduce
    didx = reduce(
        pd.MultiIndex.union,
        [dfmi.loc[pd.IndexSlice[a, b, :], :].index
         for a, b in zip(As, Bs)]
    )
    
    assert dfmi.drop(didx).equals(dfmi.drop([*zip(As, Bs)]))
    

    【讨论】:

    • 我可能误解了这个问题。
    猜你喜欢
    • 2019-03-05
    • 2019-10-10
    • 1970-01-01
    • 2018-12-18
    • 2017-06-08
    • 2019-05-22
    • 1970-01-01
    • 2021-11-03
    相关资源
    最近更新 更多