【问题标题】:Drop Non-equivalent Multiindex Rows in Pandas Dataframe删除 Pandas Dataframe 中的非等效多索引行
【发布时间】:2021-03-07 23:26:23
【问题描述】:

目标

如果子列min等于子列max并且如果minmax子列在列的any中不相等(ao , his, cyp1a2s, cyp3a4s), 删除行。

示例

arrays = [np.array(['ao', 'ao', 'hia', 'hia', 'cyp1a2s', 'cyp1a2s', 'cyp3a4s', 'cyp3a4s']),
          np.array(['min', 'max', 'min', 'max', 'min', 'max', 'min', 'max'])]
tuples = list(zip(*arrays))
index = pd.MultiIndex.from_tuples(tuples, names=['',''])
df = pd.DataFrame(np.array([[1, 1, 0, 0, float('nan'), float('nan'), 0, 0], 
                            [1, 1, 0, 0, float('nan'), 1, 0, 0],
                            [0, 2, 0, 0, float('nan'), float('nan'), 1, 1],]), index=['1', '2', '3'], columns=index)
df

    ao      hia     cyp1a2s cyp3a4s
    min max min max min max min max
1   1.0 1.0 0.0 0.0 NaN NaN 0.0 0.0
2   1.0 1.0 0.0 0.0 NaN 1.0 0.0 0.0
3   0.0 2.0 0.0 0.0 NaN NaN 1.0 1.0

想要

df = pd.DataFrame(np.array([[1, 1, 0, 0, float('nan'), float('nan'), 0, 0]]), index=['1'], columns=index)
df

    ao      hia     cyp1a2s cyp3a4s
    min max min max min max min max
1   1.0 1.0 0.0 0.0 NaN NaN 0.0 0.0

尝试

df.apply(lambda x: x['min'].map(str) == x['max'].map(str), axis=1)

KeyError: ('min', 'occurred at index 1')

注意

实际的数据框有 50 多列。

【问题讨论】:

    标签: python pandas dataframe multi-index


    【解决方案1】:

    DataFrame.xs 用于DataFrame 的第二级MultiIndex,替换NaNs:

    df1 = df.xs('min', axis=1, level=1).fillna('nan')
    df2 = df.xs('max', axis=1, level=1).fillna('nan')
    

    或者将数据转成字符串:

    df1 = df.xs('min', axis=1, level=1).astype('str')
    df2 = df.xs('max', axis=1, level=1).astype('str')
    

    通过DataFrame.eq 比较数据帧,并通过DataFrame.all 测试是否所有Trues,并通过boolean indexing 测试最后一个过滤器:

    df = df[df1.eq(df2).all(axis=1)]
    print (df)
        ao       hia      cyp1a2s     cyp3a4s     
       min  max  min  max     min max     min  max
    1  1.0  1.0  0.0  0.0     NaN NaN     0.0  0.0
    

    【讨论】:

    • 对代码的解释非常友好(并带有有用的链接)!我想知道为什么df.apply 在这种情况下不起作用。
    【解决方案2】:

    df.apply() 不起作用的原因是您需要引用 2 级列。

    另外 .map(str) 对于从 float64 映射无效...使用了 .astype(str)

    >1 列的以下工作:

    eqCols = ['cyp1a2s','hia']
    neqCols = list(set(df.xs('min', level=1, axis=1).columns) - set(eqCols))
    EQ = lambda r,c : r[c]['min'].astype(str) == r[c]['max'].astype(str)
    df[df.apply(lambda r: ([EQ(r,c) for c in eqCols][0]) & ([(not EQ(r,c)) for c in neqCols][0]), axis=1)]
    

    【讨论】:

    • 嗨,我有 50 多列。对每一列重复会很耗时。
    • 查看最新变化...分为Equality列和NotEqual列;最终进行相同的比较次数.. 不确定 df.apply() 或 df.eq() 哪个更快?
    猜你喜欢
    • 1970-01-01
    • 2019-04-22
    • 2017-03-25
    • 2019-04-13
    • 2014-03-30
    • 2020-09-15
    • 2020-09-13
    • 2016-01-18
    • 2023-04-05
    相关资源
    最近更新 更多