Pandas groupby,在字符串变量上聚合并向上移动空单元格

Posted

技术标签:

【中文标题】Pandas groupby,在字符串变量上聚合并向上移动空单元格【英文标题】:Pandas groupby, aggregate on string variable and move up empty cells 【发布时间】:2018-09-14 04:19:58 【问题描述】:

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

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

这是我的数据

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

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

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

【问题讨论】:

【参考方案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  

解释

    set_indexstack 创建Series - NaNs 被删除 将新级别添加到 MultiIndex by cumcount 通过第一和第二级别 通过unstack 重塑最后两个级别,并使用sort_index 对列中的MultiIndex 进行排序 - 仅第一级 通过列表理解将 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  

解释

    dropna 聚合每一列并转换为list 在列表理解中创建 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 的回答,因为他更快。我希望我可以标记这两种解决方案。谢谢!

以上是关于Pandas groupby,在字符串变量上聚合并向上移动空单元格的主要内容,如果未能解决你的问题,请参考以下文章

如何在 pandas groupby 对象上调用不同的聚合操作

pandas使用groupby函数进行分组聚合并使用agg函数将每个分组特定变量对应的多个内容组合到一起输出(merging content within a specific column of g

pandas使用groupby函数基于指定分组变量对dataframe数据进行分组使用mean函数计算每个分组中的所有数值变量的聚合平均值

pandas使用groupby函数基于多个分组变量(多变量分组)对dataframe数据进行分组使用mean函数计算所有分组下数据变量的聚合平均值

pandas使用groupby函数基于多个分组变量(多变量分组)对dataframe数据进行分组使用mean函数计算所有分组下数据变量的聚合平均值

pandas使用groupby函数基于指定分组变量对dataframe数据进行分组使用sum函数计算每个分组中的所有数值变量的聚合加和值