2015-02-09 4 views
1

Я хочу сгруппировать DataFrame на ключ, в данном случае 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 в ClientID и затем извлечь эти строки ...

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's, которую я нашел, работает хорошо.

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') 

Терминатор линии можно изменить, если он используется в любой из данных столбца.

Смежные вопросы