2015-02-09 168 views
1

我想将一个数据帧分组在一个键上,在这种情况下是clientid。并将每个键的所有列组合成一个长行。python pandas groupby多列到一行

例如

clientid, name, age, company 
1,  tom, 31, awesome 
1,  jen, 26, argos 
2,  bob, 18, hmv 
3,  ted, 12, mcdonalds 
4,  sarah,30, MnS 
4,  mike, 52, Mns 
4,  luke, 75, argos 

通缉的结果

clientid, name, age, company, name, age, company, name, age, company 
1,  tom, 31, awesome, jen, 26, argos, 
2,  bob, 18, hmv, 
3,  ted, 12, mcdonadls, 
4,  sarah,30, MnS,  mike, 52, MnS,  luke, 75, argos, 

类似的问题和解决方案被赋予

df_info = df1.groupby('clientid')['info'].unique().apply(pd.Series).reset_index() 
info_len = len([col for col in df_info if str(col).isdigit()]) 
df_info.columns = ['clientid'] + ['info'] * info_len 
df_info 

但我找不到如何将此应用到多个列

回答

0

这种带有一个健康警告,因为你留下的结构允许你分组,因此你正在失去大部分熊猫的力量pby,强大的性能,强大而干净的语法(所以从某种意义上讲,这是一个你不能轻易做到的功能!),而且它不是非常可爱。

所以我强烈建议不这样做,因为几乎可以肯定是一个更好的办法做到不管它是你正在做的...


我认为你需要GROUPBY的客户端ID,然后提取这些字符串...

In [11]: df1 = df.set_index('clientid') 

In [12]: df1 
Out[12]: 
      name age company 
clientid 
1   tom 31 awesome 
1   jen 26  argos 
2   bob 18  hmv 
3   ted 12 mcdonalds 
4   sarah 30  MnS 
4   mike 52  Mns 
4   luke 75  argos 

In [13]: g = df1.groupby(df1.index) 

我可能会考虑使用to_csv在每个组:

In [14]: g.apply(lambda x: x.to_csv(header=False, index=False, line_terminator=',')) 
Out[14]: 
clientid 
1      tom,31,awesome,jen,26,argos, 
2          bob,18,hmv, 
3         ted,12,mcdonalds, 
4   sarah,30,MnS,mike,52,Mns,luke,75,argos, 
dtype: object 

另一种方法是适用于:

In [15]: g.apply(lambda x: pd.concat([row for _, row in x.iterrows()]).values) 
Out[15]: 
clientid 
1       [tom, 31, awesome, jen, 26, argos] 
2            [bob, 18, hmv] 
3          [ted, 12, mcdonalds] 
4   [sarah, 30, MnS, mike, 52, Mns, luke, 75, argos] 
dtype: object 

你必须破解这一点,以获得正确的标题:

In [16]: list(df1.columns) * g.apply(len).max() 
Out[16]: ['name', 'age', 'company', 'name', 'age', 'company', 'name', 'age', 'company'] 

所以,你可以这样做以下:

In [21]: s = g.apply(lambda x: pd.concat([row for _, row in x.iterrows()]).values).apply(lambda row: ','.join([str(x) for x in row])) 

In [22]: s.name = ','.join(list(df1.columns) * g.apply(len).max()) 

In [23]: s.to_frame().to_csv(quotechar=" ")  # Note: this is a hack since quoting=0 seems to be ignored 
Out[23]: 'clientid, name,age,company,name,age,company,name,age,company \n1, tom,31,awesome,jen,26,argos \n2, bob,18,hmv \n3, ted,12,mcdonalds \n4, sarah,30,MnS,mike,52,Mns,luke,75,argos \n' 
0

我已经尝试了几种方法,并拿出了我发现的Andy的改进版本,效果很好。

grouped = df1.groupby('clientid') 
flattenedSeries = grouped.apply(lambda x: x.to_csv(header=False, index=False, line_terminator=',')) 
flattenedSeries = pd.DataFrame(flattenedSeries, columns=['data']) 
ready = flattenedSeries['data'].apply(lambda x: pd.Series(x.split(','))) 

创建新的列标题

newcolumns = list(df1.columns) * grouped.apply(len).max() 

添加神秘柱,以配合在pd.Series(x.split( ''))

newcolumns = newcolumns + ['extra'] 
ready.columns = newcolumns 

给索引创建的空白键入以帮助未来合并

ready.index= ready.index.astype('int64') 

如果行终止符用于列的任何数据中,则可以更改它。