【问题标题】:Pandas groupby, aggregate on string variable and move up empty cellsPandas groupby,在字符串变量上聚合并向上移动空单元格
【发布时间】:2023-04-06 07:00:01
【问题描述】:

我有一个带有重复标识符的字符串变量和很多空单元格的数据框。

我想按标识符分组并将所有值放在一行中。如果一列有多个条目或一个标识符,我需要一个带后缀的新行,以便稍后识别它。

这是我的数据

ID   name1  name2   name3   name4   name5   name6   name7   name8
Tom  sarah          mike                
Tom                                 john    john        
Gen  paul                           
Gen         sandra                      
Gen                 lara    lara    lara    lara        
Gen                                                 mike    mike
Lara bill   bill    bill                    
Lara                josh    josh            
Lara                kevin   kevin   kevin   mike    
Lara                                        devon   devon   devon

这是我迄今为止从here使用的代码:

grouped = df1.groupby('ID')
df1 = grouped.aggregate(lambda x: tuple(x))

这给了我以下结果:

                      name1                    name2                  name3  \
ID                                                                            
Gen   (paul, nan, nan, nan)  (nan, sandra, nan, nan)  (nan, nan, lara, nan)   
Lara  (bill, nan, nan, nan)    (bill, nan, nan, nan)  (bill, nan, nan, nan)   
Tom            (sarah, nan)               (nan, nan)             (nan, nan)   

                        name4                    name5  \
ID                                                       
Gen     (nan, nan, lara, nan)    (nan, nan, lara, nan)   
Lara  (nan, josh, kevin, nan)  (nan, josh, kevin, nan)   
Tom               (mike, nan)              (nan, john)   

                       name6                    name7                   name8  
ID                                                                             
Gen    (nan, nan, lara, nan)    (nan, nan, nan, mike)   (nan, nan, nan, mike)  
Lara  (nan, nan, kevin, nan)  (nan, nan, mike, devon)  (nan, nan, nan, devon)  
Tom              (nan, john)               (nan, nan)              (nan, nan) 

但这是我真正想要的,我只是不知道该怎么做:

ID   name1  name2   name3   name3_suffixA   name3_suffixB   name4   name4_suffixA   name5   name6   name6_suffixA   name7   name8
Tom  sarah          mike                                                            john    john            
Gen  paul   sandra  lara                                    lara                    lara    lara                    mike    mike
Lara bill   bill    bill    josh            kevin           josh    kevin           kevin   mike    devon           devon   devon

后缀的实际名称无关紧要,也无关紧要,如果附加条目出现在末尾或中间。

有一些类似的问题,我知道。但我无法处理任何案例/解决方案,我非常感谢一些帮助。

【问题讨论】:

    标签: python-3.x pandas aggregate pandas-groupby


    【解决方案1】:

    用途:

    s = df.set_index('ID').stack().to_frame('c')
    df = (s.set_index(s.groupby(level=[0,1]).cumcount().astype(str), append=True)['c']
           .unstack([1,2])
           .sort_index(level=0, axis=1))
    df.columns = ['{}_{}'.format(i,j) if j != '0' else '{}'.format(i) for i, j in df.columns]
    print (df)
          name1   name2 name3 name3_1 name3_2 name4 name4_1  name5 name6 name6_1  \
    ID                                                                             
    Gen    paul  sandra  lara    None    None  lara    None   lara  lara    None   
    Lara   bill    bill  bill    josh   kevin  josh   kevin  kevin  mike   devon   
    Tom   sarah    None  mike    None    None  None    None   john  john    None   
    
          name7  name8  
    ID                  
    Gen    mike   mike  
    Lara  devon  devon  
    Tom    None   None  
    

    解释

    1. set_indexstack 创建Series - NaNs 被删除
    2. 将新级别添加到 MultiIndex by cumcount 通过第一和第二级别
    3. 通过unstack 重塑最后两个级别,并使用sort_index 对列中的MultiIndex 进行排序 - 仅第一级
    4. 通过列表理解将 MultiIndex 展平,排除 0 用于第一列名称

    详情

    print (s)
                     c
    ID                
    Tom  name1   sarah
         name3    mike
         name5    john
         name6    john
    Gen  name1    paul
         name2  sandra
         name3    lara
         name4    lara
         name5    lara
         name6    lara
         name7    mike
         name8    mike
    Lara name1    bill
         name2    bill
         name3    bill
         name3    josh
         name4    josh
         name3   kevin
         name4   kevin
         name5   kevin
         name6    mike
         name6   devon
         name7   devon
         name8   devon
    

    另一种解决方案:

    df = df.groupby('ID').agg(lambda x: list(x.dropna()))
    
    L = ([pd.DataFrame(df[x].values.tolist(),
                      index=df.index,
                      columns = ['{}_{}'.format(x,i) if i != 0 
                                                     else '{}'.format(x) 
                                                     for i in range(df[x].str.len().max())]) for x in df])
    df = pd.concat(L, axis=1)
    print (df)
          name1   name2 name3 name3_1 name3_2 name4 name4_1  name5 name6 name6_1  \
    ID                                                                             
    Gen    paul  sandra  lara    None    None  lara    None   lara  lara    None   
    Lara   bill    bill  bill    josh   kevin  josh   kevin  kevin  mike   devon   
    Tom   sarah    None  mike    None    None  None    None   john  john    None   
    
          name7  name8  
    ID                  
    Gen    mike   mike  
    Lara  devon  devon  
    Tom    None   None  
    

    解释

    1. dropna 聚合每一列并转换为list
    2. 在列表理解中创建 DataFrame 与每一列和 concat 一起

    【讨论】:

    • 非常感谢您的帮助。第一个解决方案完美运行,而第二个解决方案在我的实际数据上花费的时间更长(只是让你知道)。谢谢!
    • @ChinChix - 很高兴能帮上忙!
    【解决方案2】:

    这比我想象的要复杂一些,我使用的是replace + stack + unstack

    s=df.replace('',np.nan).set_index('ID').stack().reset_index(level=1)
    
    #gourpby here is to create the suffix , like you mention in the question  you will need then all distinct value  
    
    s['suffix']=s['level_1']+'_'+s.groupby([s.index,s.level_1]).cumcount().astype(str)
    s.set_index('suffix',append=True)[0].unstack()
    
    
    suffix name1_0 name2_0 name3_0 name3_1 name3_2 name4_0 name4_1 name5_0  \
    ID                                                                       
    Gen       paul  sandra    lara    None    None    lara    None    lara   
    Lara      bill    bill    bill    josh   kevin    josh   kevin   kevin   
    Tom      sarah    None    mike    None    None    None    None    john   
    suffix name6_0 name6_1 name7_0 name8_0  
    ID                                      
    Gen       lara    None    mike    mike  
    Lara      mike   devon   devon   devon  
    Tom       john    None    None    None  
    

    【讨论】:

    • 也非常感谢您的解决方案。我得到了想要的结果。我赞成 jezrael 的回答,因为他更快。我希望我可以标记这两种解决方案。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2016-06-24
    • 1970-01-01
    • 2019-10-12
    • 2017-09-14
    • 2014-03-09
    • 1970-01-01
    • 2018-09-15
    • 1970-01-01
    相关资源
    最近更新 更多