Вы близки, прежде чем reset_index
используйте Series.unstack
:
df1 = (df.fillna('')
.groupby(['username', 'status'])['state'] \
.apply(lambda x: ','.join(set(x)))
.unstack(fill_value='')
.reset_index()
.rename_axis(None, axis=1))
print (df1)
username ADD REMOVE
0 a AZ,AR,CO NY
1 b CA
Или используйте DataFrame.pivot_table
с преобразованием индекса в столбец по reset_index
и удаление имени столбца с помощью DataFrame.rename_axis
:
df1 = (df.pivot_table(index='username',
columns='status',
values='state',
aggfunc=lambda x: ','.join(set(x)),
fill_value='')
.reset_index()
.rename_axis(None, axis=1))
print (df1)
username ADD REMOVE
0 a AZ,AR,CO NY
1 b CA
РЕДАКТИРОВАТЬ:
Возможно решение с удалением set
s, если использовать DataFrame.drop_duplicates
по 3 столбцам:
Изменены данные выборки для лучшего объяснения:
d = {'username': ['a', 'a', 'b', 'a', 'a', 'a'],
'state': ['AR', 'AZ', 'CA', 'CO', 'NY', 'NY'],
'status': ['ADD', 'ADD', 'REMOVE', 'ADD', 'REMOVE','REMOVE']}
df = pd.DataFrame(data=d)
print (df)
username state status
0 a AR ADD
1 a AZ ADD
2 b CA REMOVE
3 a CO ADD
4 a NY REMOVE
5 a NY REMOVE <- added row
df1 = (df.pivot_table(index='username',
columns='status',
values='state',
aggfunc=lambda x: ','.join(set(x)),
fill_value='')
.reset_index()
.rename_axis(None, axis=1))
print (df1)
username ADD REMOVE
0 a AZ,AR,CO NY
1 b CA
df1 = (df.drop_duplicates(['username','status','state'])
.pivot_table(index='username',
columns='status',
values='state',
aggfunc= ','.join,
fill_value='')
.reset_index()
.rename_axis(None, axis=1))
print (df1)
username ADD REMOVE
0 a AZ,AR,CO NY
1 b CA