【问题标题】:Retain empty lists when unnesting columns in pandas在熊猫中取消嵌套列时保留空列表
【发布时间】:2019-06-03 09:43:10
【问题描述】:

背景

我有以下数据框

import pandas as pd
df = pd.DataFrame({'Result' : [['pos', '+', 'pos', 'positive'], ['neg', 'neg'], [], ['pos']], 
                  'P_ID': [1,2,3,4], 
                  'Gene' : [['kras', 'kras', 'kras', 'egfr'], ['brca', 'brca'], [], ['cd133']],
                  'N_ID' : ['A1', 'A2', 'A3', 'A4']

                 })

#rearrange columns
df = df[['P_ID', 'N_ID', 'Gene', 'Result']]
df


  P_ID N_ID         Gene                         Result
0   1   A1  [kras, kras, kras, egfr]    [pos, +, pos, positive]
1   2   A2  [brca, brca]                [neg, neg]
2   3   A3  []                          []
3   4   A4  [cd133]                     [pos]

我使用以下代码取自unnest (explode) multiple list 2.0

df.set_index('P_ID').apply(lambda x: x.apply(pd.Series).stack()).ffill().reset_index().drop('level_1', 1)

问题

使用上面的代码,我接近了我想要的。但是,因为第三行2 中的GeneResult 列是空列表[],所以我得到它上面行的输出,如下所示:

 P_ID   N_ID Gene   Result
0   1   A1  kras    pos
1   1   A1  kras    +
2   1   A1  kras    pos
3   1   A1  egfr    positive
4   2   A2  brca    neg
5   2   A2  brca    neg
6   3   A3  brca    neg
7   4   A4  cd133   pos

相反,我想得到下面的输出,其中以下行 6 3 A3 [] [] 反映了原始数据框 df,其中包含空列表

期望的输出

   P_ID N_ID Gene   Result
0   1   A1  kras    pos
1   1   A1  kras    +
2   1   A1  kras    pos
3   1   A1  egfr    positive
4   2   A2  brca    neg
5   2   A2  brca    neg
6   3   A3  []      []
7   4   A4  cd133   pos

问题

如何获得所需的输出?

【问题讨论】:

    标签: python pandas dataframe


    【解决方案1】:

    让我们尝试一些堆叠和取消堆叠的魔法。这也会保留空列表。

    (df.set_index(['P_ID', 'N_ID'])
       .stack()
       .str.join(',')
       .str.split(',', expand=True)
       .stack()
       .unstack(-2)
       .reset_index(level=[0, 1])
       .reset_index(drop=True))
    
       P_ID N_ID    Result   Gene
    0  1     A1   pos       kras 
    1  1     A1   +         kras 
    2  1     A1   pos       kras 
    3  1     A1   positive  egfr 
    4  2     A2   neg       brca 
    5  2     A2   neg       brca 
    6  3     A3                  
    7  4     A4   pos       cd133
    

    详情

    首先,将不被触摸的列设置为索引。

    df.set_index(['P_ID', 'N_ID'])
    
                                Result                      Gene
    P_ID N_ID                                                   
    1    A1    [pos, +, pos, positive]  [kras, kras, kras, egfr]
    2    A2    [neg, neg]               [brca, brca]            
    3    A3    []                       []                      
    4    A4    [pos]                    [cd133]                 
    

    接下来,stack 行。

    _.stack()
    
    P_ID  N_ID        
    1     A1    Result    [pos, +, pos, positive] 
                Gene      [kras, kras, kras, egfr]
    2     A2    Result    [neg, neg]              
                Gene      [brca, brca]            
    3     A3    Result    []                      
                Gene      []                      
    4     A4    Result    [pos]                   
                Gene      [cd133]                 
    dtype: object
    

    我们现在有一个系列。我们需要将这些元素分解成单独的列。因此,首先加入列表,然后再次拆分。 假设您的列表元素本身不包含逗号,则此方法有效(如果没有,请找到另一个分隔符来加入和拆分)。

    _.str.join(',').str.split(',', expand=True)
    
                          0     1     2         3
    P_ID N_ID                                    
    1    A1   Result  pos    +     pos   positive
              Gene    kras   kras  kras  egfr    
    2    A2   Result  neg    neg   None  None    
              Gene    brca   brca  None  None    
    3    A3   Result         None  None  None    
              Gene           None  None  None    
    4    A4   Result  pos    None  None  None    
              Gene    cd133  None  None  None    
    

    我们需要去掉 NULL 值,所以再次调用stack

    _.stack()
    
    P_ID  N_ID           
    1     A1    Result  0    pos     
                        1    +       
                        2    pos     
                        3    positive
                Gene    0    kras    
                        1    kras    
                        2    kras    
                        3    egfr    
    2     A2    Result  0    neg     
                        1    neg     
                Gene    0    brca    
                        1    brca    
    3     A3    Result  0            
                Gene    0            
    4     A4    Result  0    pos     
                Gene    0    cd133   
    dtype: object
    

    我们快到了。现在我们希望索引的倒数第二级成为我们的列,因此使用unstack(-2)(倒数第二级上的unstack)取消堆叠

    _.unstack(-2)
    
                   Result   Gene
    P_ID N_ID                   
    1    A1   0  pos       kras 
              1  +         kras 
              2  pos       kras 
              3  positive  egfr 
    2    A2   0  neg       brca 
              1  neg       brca 
    3    A3   0                 
    4    A4   0  pos       cd133
    

    最后,为了获得我们的原始列,进行了一些整理工作。

    _.reset_index(-1, drop=True).reset_index()
    
       P_ID N_ID    Result   Gene
    0  1     A1   pos       kras 
    1  1     A1   +         kras 
    2  1     A1   pos       kras 
    3  1     A1   positive  egfr 
    4  2     A2   neg       brca 
    5  2     A2   neg       brca 
    6  3     A3                  
    7  4     A4   pos       cd133
    

    如果您希望空白实际上是列表,请使用applymap

    _.applymap(lambda x: x if x != '' else []))
    
       P_ID N_ID    Result   Gene
    0  1     A1   pos       kras 
    1  1     A1   +         kras 
    2  1     A1   pos       kras 
    3  1     A1   positive  egfr 
    4  2     A2   neg       brca 
    5  2     A2   neg       brca 
    6  3     A3   []        []   
    7  4     A4   pos       cd133
    

    【讨论】:

    • 谢谢你,非常有用,用 pandas unstack,它是 unstack 系列还是索引?我总是对此感到困惑
    • @Datanovice 它沿一个索引或一组索引展开系列。
    【解决方案2】:

    调整后unnesting 仍然可以正常工作

    df=df.applymap(lambda x : [''] if x==[] else x)
    unnesting(df,['Gene','Result'])
    Out[20]: 
        Gene    Result N_ID  P_ID
    0   kras       pos   A1     1
    0   kras         +   A1     1
    0   kras       pos   A1     1
    0   egfr  positive   A1     1
    1   brca       neg   A2     2
    1   brca       neg   A2     2
    2                    A3     3
    3  cd133       pos   A4     4
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-06-20
      • 2019-07-16
      • 1970-01-01
      • 1970-01-01
      • 2020-07-28
      • 2019-07-17
      • 1970-01-01
      相关资源
      最近更新 更多