Pandas:有条件地删除基于 MultiIndex 数据帧中整个列的相同值的列

扎眼的阳光 python 232

原文标题Pandas: Conditionally dropping columns based on same values throughout the column in MultiIndex dataframe

我有一个数据框如下:

data = {('5105', 'Open'): [1.99,1.98,1.99,2.05,2.15],
        ('5105', 'Adj Close'): [1.92,1.92,1.96,2.07,2.08],
        ('5229', 'Open'): [0.01]*5,
        ('5229', 'Adj Close'): [0.02]*5,
        ('7076', 'Open'): [1.02,1.01,1.01,1.06,1.06],
        ('7076', 'Adj Close'): [0.90,0.92,0.94,0.94,0.95]}

df = pd.DataFrame(data)

   5105            5229            7076          
   Open Adj Close  Open Adj Close  Open Adj Close
0  1.99      1.92  0.01      0.02  1.02      0.90
1  1.98      1.92  0.01      0.02  1.01      0.92
2  1.99      1.96  0.01      0.02  1.01      0.94
3  2.05      2.07  0.01      0.02  1.06      0.94
4  2.15      2.08  0.01      0.02  1.06      0.95

如上面的数据框,我们可以看到df['5229']的两列OpenAdj Close在整个列中分别具有相同的值。所以,我打算放弃它,因为它在我的分析中没有用。

我有两个疑问:

  1. 如果列的子列在整个列中分别具有相同的值,如何将列删除到级别 0(即第一列)?
  2. 另一方面,如果只有一个子列在整个列中具有相同的值,我该如何删除它?

由于这是基于条件的丢弃,我想知道df.drop在这种情况下是否仍然有效?

根据我的第一个和第二个查询,在我上面的例子中,由于OpenAdj Close在整个列中具有相同的值,我想完全删除它。

预期的输出是:

   5105            7076          
   Open Adj Close  Open Adj Close
0  1.99      1.92  1.02      0.90
1  1.98      1.92  1.01      0.92
2  1.99      1.96  1.01      0.94
3  2.05      2.07  1.06      0.94
4  2.15      2.08  1.06      0.95

编辑

真的很感谢那些回答问题的人。为了更简洁,我试图从具有超过 200 列的数据框中删除列,条件是该特定列中的所有值都相同。

原文链接:https://stackoverflow.com//questions/71685851/pandas-conditionally-dropping-columns-based-on-same-values-throughout-the-colum

回复

我来回复
  • Caio Lopes的头像
    Caio Lopes 评论

    你可以试试这个:

    for a, b in df.columns:
        if df[a][b].duplicated(keep=False).sum() == df[a][b].size:
            df.drop((a, b), axis=1, inplace=True)
    

    结果:

       5105            7076          
       Open Adj Close  Open Adj Close
    0  1.99      1.92  1.02      0.90
    1  1.98      1.92  1.01      0.92
    2  1.99      1.96  1.01      0.94
    3  2.05      2.07  1.06      0.94
    4  2.15      2.08  1.06      0.95
    
    2年前 0条评论
  • enke的头像
    enke 评论

    我们可以使用unstack+groupby+nunique来获取每列中唯一值的数量。然后用loc只选择值大于 1 的列:

    out = df[df.unstack().groupby(level=[0,1]).nunique().loc[lambda x: x!=1].index]
    

    输出:

           5105            7076      
      Adj Close  Open Adj Close  Open
    0      1.92  1.99      0.90  1.02
    1      1.92  1.98      0.92  1.01
    2      1.96  1.99      0.94  1.01
    3      2.07  2.05      0.94  1.06
    4      2.08  2.15      0.95  1.06
    
    2年前 0条评论
  • rhug123的头像
    rhug123 评论

    尝试这个:

    df.drop('5229',level=0,axis=1)
    

    输出:

       5105            7076          
       Open Adj Close  Open Adj Close
    0  1.99      1.92  1.02      0.90
    1  1.98      1.92  1.01      0.92
    2  1.99      1.96  1.01      0.94
    3  2.05      2.07  1.06      0.94
    4  2.15      2.08  1.06      0.95
    
    2年前 0条评论
  • BENY的头像
    BENY 评论

    试试nunique

    df = df.loc[:,~(df.nunique()==1).values]
    Out[125]: 
       5105            7076          
       Open Adj Close  Open Adj Close
    0  1.99      1.92  1.02      0.90
    1  1.98      1.92  1.01      0.92
    2  1.99      1.96  1.01      0.94
    3  2.05      2.07  1.06      0.94
    4  2.15      2.08  1.06      0.95
    
    2年前 0条评论