取消嵌套熊猫列时保留空列表

时间:2019-06-03 00:58:47

标签: python pandas dataframe

背景

我有以下数据框

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)

问题

使用上面的代码,我接近想要的东西。但是,由于第三行Gene中的Result2列是空列表[],因此我得到了该行上方的输出,如下所示:

 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

问题

如何获得所需的输出?

2 个答案:

答案 0 :(得分:2)

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

(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

答案 1 :(得分: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
相关问题