2015-02-09 81 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') 

如果行終止符用於列的任何數據中,則可以更改它。