簡體   English   中英

Pandas:根據復雜的邏輯刪除具有特定字符串的行和列

[英]Pandas: Remove rows and columns with a certain string based on a complex logic

以下是我的數據框:

df = pd.DataFrame({'A': ['a1', 'a1', 'a1', 'a1', 'a1', 'a1', 'a1', 'a1', 'a1', 'all', 'all', 'all', 'all', 'all', 'all', 'all', 'all', 'all'],
              'B': ['b1', 'b1', 'b1', 'b2', 'b2', 'b2', 'all', 'all', 'all', 'b1', 'b1', 'b1', 'b2', 'b2', 'b2', 'all', 'all', 'all'],
              'C': ['c1', 'c2', 'all', 'c1', 'c2', 'all', 'c1', 'c2', 'all', 'c1', 'c2', 'all', 'c1', 'c2', 'all', 'c1', 'c2', 'all'],
              'D': ['D1', 'D2', 'all', 'D1', 'D2', 'all', 'D1', 'D2', 'all', 'D1', 'D2', 'all', 'D1', 'D2', 'all', 'D1', 'D2', 'all'],
              'E': ['E1', 'E1', 'E1', 'E2', 'E2', 'E2', 'all', 'all', 'all', 'E1', 'E1', 'E1', 'E2', 'E2', 'E2', 'all', 'all', 'all'],
              'F': [1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9]})

pivot之后,以下是輸出:

In [226]: df.pivot(index=['A', 'B', 'C'], columns=['E', 'D'])
Out[226]: 
               F                          (NO)  (NO)           
E             E1   E1  E1    E2   E2  E2   all  all  all      
D             D1   D2  all   D1   D2  all   D1   D2  all
A   B   C                                               
a1  all all  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  9.0 
a1  all c1   NaN  NaN  NaN  NaN  NaN  NaN  7.0  NaN  NaN  -> (NO)
a1  all c2   NaN  NaN  NaN  NaN  NaN  NaN  NaN  8.0  NaN  -> (NO)
a1  b1  all  NaN  NaN  3.0  NaN  NaN  NaN  NaN  NaN  NaN
a1  b1  c1   1.0  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN
a1  b1  c2   NaN  2.0  NaN  NaN  NaN  NaN  NaN  NaN  NaN
a1  b2  all  NaN  NaN  NaN  NaN  NaN  6.0  NaN  NaN  NaN
a1  b2  c1   NaN  NaN  NaN  4.0  NaN  NaN  NaN  NaN  NaN
a1  b2  c2   NaN  NaN  NaN  NaN  5.0  NaN  NaN  NaN  NaN
all all all  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  9.0
all all c1   NaN  NaN  NaN  NaN  NaN  NaN  7.0  NaN  NaN  -> (NO)
all all c2   NaN  NaN  NaN  NaN  NaN  NaN  NaN  8.0  NaN  -> (NO)
all b1  all  NaN  NaN  3.0  NaN  NaN  NaN  NaN  NaN  NaN  -> (NO)
all b1  c1   1.0  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  -> (NO)
all b1  c2   NaN  2.0  NaN  NaN  NaN  NaN  NaN  NaN  NaN  -> (NO)
all b2  all  NaN  NaN  NaN  NaN  NaN  6.0  NaN  NaN  NaN  -> (NO)
all b2  c1   NaN  NaN  NaN  4.0  NaN  NaN  NaN  NaN  NaN  -> (NO)
all b2  c2   NaN  NaN  NaN  NaN  5.0  NaN  NaN  NaN  NaN  -> (NO)

我需要刪除(NO)指出的行和列。

邏輯是:從最內部的索引,即C ,我需要保留all以向后方式出現的行和列。 因此,保留索引為a1 all alla1 b1 alla1 b2 allall all all因為all都以反向方式發生。

需要刪除索引為a1 all c1a1 all c2all all c1all b1 all等的行,因為從C向后的all行都沒有連續性。

同樣的邏輯也適用於列。 D開始,需要刪除索引為D1 allD2 all ,其余都很好。

預期輸出:

In [227]: result_df
Out[227]: 
               F                          
E             E1   E1  E1    E2   E2  E2   all      
D             D1   D2  all   D1   D2  all  all
A   B   C                                     
a1  all all  NaN  NaN  NaN  NaN  NaN  NaN  9.0 
a1  b1  all  NaN  NaN  3.0  NaN  NaN  NaN  NaN
a1  b1  c1   1.0  NaN  NaN  NaN  NaN  NaN  NaN
a1  b1  c2   NaN  2.0  NaN  NaN  NaN  NaN  NaN
a1  b2  all  NaN  NaN  NaN  NaN  NaN  6.0  NaN
a1  b2  c1   NaN  NaN  NaN  4.0  NaN  NaN  NaN
a1  b2  c2   NaN  NaN  NaN  NaN  5.0  NaN  NaN
all all all  NaN  NaN  NaN  NaN  NaN  NaN  9.0

用新數據更新:

df = pd.DataFrame({'A': ['a1', 'a1', 'a1', 'a1', 'a1', 'a1', 'a1', 'a1', 'a1', 'all', 'all', 'all', 'all', 'all',
                                 'all::1::2', 'all::2', 'all', 'all'],
                           'B': ['b1', 'b1', 'b1', 'b2', 'b2', 'b2', 'all', 'all::3::4', 'all', 'b1', 'b1', 'b1', 'b2', 'b2',
                                 'b2', 'all', 'all', 'all'],
                           'C': ['c1', 'c2', 'all', 'c1', 'c2', 'all', 'c1', 'c2', 'all', 'c1', 'c2', 'all', 'c1', 'c2',
                                 'all', 'c1', 'c2', 'all::5::all'],
                           'D': ['D1', 'D2', 'all', 'D1', 'D2', 'all::3::2', 'D1', 'D2', 'all', 'D1', 'D2', 'all', 'D1', 'D2',
                                 'all', 'D1', 'D2', 'all'],
                           'E': ['E1', 'E1', 'E1', 'E2', 'E2', 'E2', 'all', 'all', 'all', 'E1', 'E1', 'E1', 'E2', 'E2',
                                 'E2', 'all::1::2', 'all', 'all'],
                           'measure_F': [1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9]})

pivot

In [334]: df
Out[334]: 
                                measure_F                                (NO) (NO)                (NO)         
E                                      E1             E2                 all             E2 all::1::2
D                                      D1   D2  all   D1   D2 all::3::2   D1   D2  all  all        D1
A         B         C                                                                                
a1        all       all               NaN  NaN  NaN  NaN  NaN       NaN  NaN  NaN  9.0  NaN       NaN
                    c1                NaN  NaN  NaN  NaN  NaN       NaN  7.0  NaN  NaN  NaN       NaN  -> (NO)
          all::3::4 c2                NaN  NaN  NaN  NaN  NaN       NaN  NaN  8.0  NaN  NaN       NaN  -> (NO)
          b1        all               NaN  NaN  3.0  NaN  NaN       NaN  NaN  NaN  NaN  NaN       NaN
                    c1                1.0  NaN  NaN  NaN  NaN       NaN  NaN  NaN  NaN  NaN       NaN
                    c2                NaN  2.0  NaN  NaN  NaN       NaN  NaN  NaN  NaN  NaN       NaN
          b2        all               NaN  NaN  NaN  NaN  NaN       6.0  NaN  NaN  NaN  NaN       NaN
                    c1                NaN  NaN  NaN  4.0  NaN       NaN  NaN  NaN  NaN  NaN       NaN
                    c2                NaN  NaN  NaN  NaN  5.0       NaN  NaN  NaN  NaN  NaN       NaN
all       all       all::5::all       NaN  NaN  NaN  NaN  NaN       NaN  NaN  NaN  9.0  NaN       NaN
                    c2                NaN  NaN  NaN  NaN  NaN       NaN  NaN  8.0  NaN  NaN       NaN  -> (NO)
          b1        all               NaN  NaN  3.0  NaN  NaN       NaN  NaN  NaN  NaN  NaN       NaN  -> (NO)
                    c1                1.0  NaN  NaN  NaN  NaN       NaN  NaN  NaN  NaN  NaN       NaN  -> (NO)
                    c2                NaN  2.0  NaN  NaN  NaN       NaN  NaN  NaN  NaN  NaN       NaN  -> (NO)
          b2        c1                NaN  NaN  NaN  4.0  NaN       NaN  NaN  NaN  NaN  NaN       NaN  -> (NO)
                    c2                NaN  NaN  NaN  NaN  5.0       NaN  NaN  NaN  NaN  NaN       NaN  -> (NO)
all::1::2 b2        all               NaN  NaN  NaN  NaN  NaN       NaN  NaN  NaN  NaN  6.0       NaN  -> (NO)
all::2    all       c1                NaN  NaN  NaN  NaN  NaN       NaN  NaN  NaN  NaN  NaN       7.0  -> (NO)

更新 2:

df = pd.DataFrame({'A':['test', 'test', 'test', 'test', 'test'], 'B':['a', 'b', 'c', 'd', 'e'], 'C':['x', 'x', 'all_group', 'y', 'y'], 'D':['abc', 'all_group::1::all_group', 'all_group::1::all_group', 'abc', 'abc'], 'E':[13, 36, 26, 39,40]})

In [599]: df.pivot(index=['A', 'B'], columns=['C', 'D'])
Out[599]: 
           E                                                      
C          x                                       all_group     y
D        abc all_group::1::all_group all_group::1::all_group   abc
A    B                                                            
test a  13.0                     NaN                     NaN   NaN
     b   NaN                    36.0                     NaN   NaN
     c   NaN                     NaN                    26.0   NaN
     d   NaN                     NaN                     NaN  39.0
     e   NaN                     NaN                     NaN  40.0

使用輔助DataFrame最后一次傳遞到DataFrame.locindexcolumns創建掩碼:

df1 = df.index.to_frame()
m1 = df1.where(df1=='all').bfill(axis=1).count(axis=1).isin([0, df.index.nlevels])
df2 = df.columns.to_frame()
m2 = df2.where(df2=='all').bfill(axis=1).count(axis=1).isin([0, df.columns.nlevels])

df = df.loc[m1, m2]
print (df)    
                F                              
E             E1             E2            all
D             D1   D2  all   D1   D2  all  all
A   B   C                                     
a1  all all  NaN  NaN  NaN  NaN  NaN  NaN  9.0
    b1  all  NaN  NaN  3.0  NaN  NaN  NaN  NaN
        c1   1.0  NaN  NaN  NaN  NaN  NaN  NaN
        c2   NaN  2.0  NaN  NaN  NaN  NaN  NaN
    b2  all  NaN  NaN  NaN  NaN  NaN  6.0  NaN
        c1   NaN  NaN  NaN  4.0  NaN  NaN  NaN
        c2   NaN  NaN  NaN  NaN  5.0  NaN  NaN
all all all  NaN  NaN  NaN  NaN  NaN  NaN  9.0
    b1  all  NaN  NaN  3.0  NaN  NaN  NaN  NaN
    b2  all  NaN  NaN  NaN  NaN  NaN  6.0  NaN
 

詳情

MultiIndex.to_frame用於DataFrame

print (df.index.to_frame())    

               A    B    C
A   B   C                 
a1  all all   a1  all  all
        c1    a1  all   c1
        c2    a1  all   c2
    b1  all   a1   b1  all
        c1    a1   b1   c1
        c2    a1   b1   c2
    b2  all   a1   b2  all
        c1    a1   b2   c1
        c2    a1   b2   c2
all all all  all  all  all
        c1   all  all   c1
        c2   all  all   c2
    b1  all  all   b1  all
        c1   all   b1   c1
        c2   all   b1   c2
    b2  all  all   b2  all
        c1   all   b2   c1
        c2   all   b2   c2

然后通過DataFrame.where將非all替換為缺失值:

print (df1.where(df1=='all'))
               A    B    C
A   B   C                 
a1  all all  NaN  all  all
        c1   NaN  all  NaN
        c2   NaN  all  NaN
    b1  all  NaN  NaN  all
        c1   NaN  NaN  NaN
        c2   NaN  NaN  NaN
    b2  all  NaN  NaN  all
        c1   NaN  NaN  NaN
        c2   NaN  NaN  NaN
all all all  all  all  all
        c1   all  all  NaN
        c2   all  all  NaN
    b1  all  all  NaN  all
        c1   all  NaN  NaN
        c2   all  NaN  NaN
    b2  all  all  NaN  all
        c1   all  NaN  NaN
        c2   all  NaN  NaN

回填不丟失,這里all ,由bfill

print (df1.where(df1=='all').bfill(axis=1))
               A    B    C
A   B   C                 
a1  all all  all  all  all
        c1   all  all  NaN
        c2   all  all  NaN
    b1  all  all  all  all
        c1   NaN  NaN  NaN
        c2   NaN  NaN  NaN
    b2  all  all  all  all
        c1   NaN  NaN  NaN
        c2   NaN  NaN  NaN
all all all  all  all  all
        c1   all  all  NaN
        c2   all  all  NaN
    b1  all  all  all  all
        c1   all  NaN  NaN
        c2   all  NaN  NaN
    b2  all  all  all  all
        c1   all  NaN  NaN
        c2   all  NaN  NaN

通過DataFrame.count計算非缺失值:

print (df1.where(df1=='all').bfill(axis=1).count(axis=1))
A    B    C  
a1   all  all    3
          c1     2
          c2     2
     b1   all    3
          c1     0
          c2     0
     b2   all    3
          c1     0
          c2     0
all  all  all    3
          c1     2
          c2     2
     b1   all    3
          c1     1
          c2     1
     b2   all    3
          c1     1
          c2     1

測試是否為0 - 這意味着MultiIndex.nlevels行/列,如果所有NaN匹配MultiIndex.nlevels的級別MultiIndex.nlevels

print (df1.where(df1=='all').bfill(axis=1).count(axis=1).isin([0, df.index.nlevels]))
 A    B    C  
a1   all  all     True
          c1     False
          c2     False
     b1   all     True
          c1      True
          c2      True
     b2   all     True
          c1      True
          c2      True
all  all  all     True
          c1     False
          c2     False
     b1   all     True
          c1     False
          c2     False
     b2   all     True
          c1     False
          c2     False
dtype: bool

編輯:這里是比較子字符串,然后是由np.triu創建的輔助數組的所有掩碼值,僅與False s 行鏈接:

f = lambda x: x.str.contains('all')
arr1 = np.triu(np.ones((df.index.nlevels,df.index.nlevels), dtype=bool), False)
arr2 = np.triu(np.ones((df.columns.nlevels,df.columns.nlevels), dtype=bool), False)
print (arr1)
[[ True  True  True]
 [False  True  True]
 [False False  True]]

arr11 = df.index.to_frame().astype(str).apply(f).to_numpy()
arr22 = df.columns.to_frame().astype(str).apply(f).to_numpy()

#https://stackoverflow.com/a/51352806/2901002
m1 = (arr11[:, None] == arr1).all(-1).any(axis=1) | ~arr11.any(axis=1)
m2 = (arr22[:, None] == arr2).all(-1).any(axis=1) | ~arr22.any(axis=1)

df = df.loc[m1, m2]
print (df) 
                    measure_F                                       
E                          E1             E2                 all  E2
D                          D1   D2  all   D1   D2 all::3::2  all all
A   B   C                                                           
a1  all all               NaN  NaN  NaN  NaN  NaN       NaN  9.0 NaN
    b1  all               NaN  NaN  3.0  NaN  NaN       NaN  NaN NaN
        c1                1.0  NaN  NaN  NaN  NaN       NaN  NaN NaN
        c2                NaN  2.0  NaN  NaN  NaN       NaN  NaN NaN
    b2  all               NaN  NaN  NaN  NaN  NaN       6.0  NaN NaN
        c1                NaN  NaN  NaN  4.0  NaN       NaN  NaN NaN
        c2                NaN  NaN  NaN  NaN  5.0       NaN  NaN NaN
all all all::5::all       NaN  NaN  NaN  NaN  NaN       NaN  9.0 NaN

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM