Я пытаюсь сгенерировать особенно структурированный фрейм данных, но я не могу "складывать" данные. Мой пример необработанных данных:
# raw data
df = pd.DataFrame({'Name':['name1', 'name2', 'name3', 'name1', 'name2', 'name3', 'name1', 'name2', 'name3' ],
'Year':['freshman','sophomore','freshman', 'freshman','sophomore','freshman', 'freshman','sophomore','freshman'],
'Rotation':['ERJD','PEDI','MAM','PEDI', 'ERJD','PEDI','MAM','ERJD','ABD'],
'Week1':[1,1,1,0,0,0,0,0,0],
'Week2':[0,0,0,1,1,1,0,0,0],
'Week3':[0,0,0,0,0,0,1,1,1],
'Week4':[1,0,0,0,0,0,0,1,1]
})
df = df[['Name','Year','Rotation','Week1','Week2','Week3','Week4']]
Что выглядит так:
Name Year Rotation Week1 Week2 Week3 Week4
0 name1 freshman ERJD 1 0 0 1
1 name2 sophomore PEDI 1 0 0 0
2 name3 freshman MAM 1 0 0 0
3 name1 freshman PEDI 0 1 0 0
4 name2 sophomore ERJD 0 1 0 0
5 name3 freshman PEDI 0 1 0 0
6 name1 freshman MAM 0 0 1 0
7 name2 sophomore ERJD 0 0 1 1
8 name3 freshman ABD 0 0 1 1
Я изменяю структуру данных:
#Reshape Table + Filtering
df = pd.melt(df,
id_vars=['Name','Year','Rotation'],
value_vars=list(df.columns[3:]),
var_name='Week',
value_name='Sum of Value')
df = df.loc[df['Sum of Value'] == 1].reset_index()
df.pop('index')
Что генерирует:
Name Year Rotation Week Sum of Value
0 name1 freshman ERJD Week1 1
1 name2 sophomore PEDI Week1 1
2 name3 freshman MAM Week1 1
3 name1 freshman PEDI Week2 1
4 name2 sophomore ERJD Week2 1
5 name3 freshman PEDI Week2 1
6 name1 freshman MAM Week3 1
7 name2 sophomore ERJD Week3 1
8 name3 freshman ABD Week3 1
9 name1 freshman ERJD Week4 1
10 name2 sophomore ERJD Week4 1
11 name3 freshman ABD Week4 1
Я создаю сводную таблицу:
#Create Pivot
pivot = df.pivot_table(index=['Rotation','Year'], columns='Week', values='Name', aggfunc=lambda x: ' '.join(x))
pivot = pivot.reindex(weeks, axis=1) # Change order of Columns
pivot
Что генерирует:
Week1 Week2 Week3 Week4
Rotation Year
ABD freshman None None name3 name3
ERJD freshman name1 None None name1
sophomore None name2 name2 name2
MAM freshman name3 None name1 None
PEDI freshman None name1 name3 None None
sophomore name2 None None None
Я хотел бы разместить имена в таблице, например, PEDI на неделе2 имеет name1
и name3
рядом. Как я могу поместить имена в разные строки? Есть ли лучший способ сделать это вместо использования сводной таблицы? Шаг pd.melt
вообще необходим?
Желаемая структура:
Week1 Week2 Week3 Week4
Rotation Year
ABD freshman None None name3 name3
ERJD freshman name1 None None name1
sophomore None name2 name2 name2
MAM freshman name3 None name1 None
PEDI freshman None name1 None None
name3
sophomore name2 None None None
Заранее спасибо за помощь!
РЕШЕНИЕ:
После pd.melt
сделайте следующее:
df['aggval'] = df['Week'].map(str) + df['Rotation']
df['aggval'] = df.groupby(['aggval']).cumcount()+1
pivot = df.pivot_table(index=['Rotation','aggval'], columns='Week', values='Name', aggfunc=lambda x: ' '.join(x)).fillna('')
pivot = pivot.reindex(weeks, axis=1)
3 ответа
После pd.melt сделайте следующее:
df['aggval'] = df['Week'].map(str) + df['Rotation']
df['aggval'] = df.groupby(['aggval']).cumcount()+1
pivot = df.pivot_table(index=['Rotation','aggval'], columns='Week', values='Name', aggfunc=lambda x: ' '.join(x)).fillna('')
pivot = pivot.reindex(weeks, axis=1)
Вы можете сделать это используя set_index
и mul
:
df1 = df.set_index(['Rotation','Year'])
df1.filter(like='Week').mul(df1['Name'], axis=0)\
.replace('',np.nan)\
.sort_index()
Выход:
Week1 Week2 Week3 Week4
Rotation Year
ABD freshman NaN NaN name3 name3
ERJD freshman name1 NaN NaN name1
sophomore NaN name2 NaN NaN
sophomore NaN NaN name2 name2
MAM freshman name3 NaN NaN NaN
freshman NaN NaN name1 NaN
PEDI freshman NaN name1 NaN NaN
freshman NaN name3 NaN NaN
sophomore name2 NaN NaN NaN
Вы можете просмотреть интересующие вас недели и условно заполнить свой фрейм данных, например:
for week in ['Week1','Week2','Week3','Week4']:
df[week] = np.where(df[week]==1, df['Name'], df[week])
Это дает:
Name Year Rotation Week1 Week2 Week3 Week4
0 name1 freshman ERJD name1 0 0 name1
1 name2 sophmore PEDI name2 0 0 0
2 name3 freshman MAM name3 0 0 0
3 name1 freshman PEDI 0 name1 0 0
4 name2 sophmore ERJD 0 name2 0 0
5 name3 freshman PEDI 0 name3 0 0
6 name1 freshman MAM 0 0 name1 0
7 name2 sophmore ERJD 0 0 name2 name2
8 name3 freshman ABD 0 0 name3 name3
Затем вы можете сгруппировать ваш фрейм данных и сохранить записи строкового типа в списках:
grouped = df.drop('Name', axis=1).groupby(['Rotation','Year']).agg(lambda x: [i for i in x if type(i)==str])
Который дает:
Week1 Week2 Week3 Week4
Rotation Year
ABD freshman [] [] [name3] [name3]
ERJD freshman [name1] [] [] [name1]
sophmore [] [name2] [name2] [name2]
MAM freshman [name3] [] [name1] []
PEDI freshman [] [name1, name3] [] []
sophmore [name2] [] [] []
Обратите внимание, что в вашем операторе есть ошибка в желаемом выводе. Нет ('MAM','sophmore')
группы. Также обратите внимание, что 'sophmore'
пишется 'sophomore'
, просто для ясности.
Похожие вопросы
Новые вопросы
python
Python - это многопарадигмальный, динамически типизированный, многоцелевой язык программирования. Он разработан для быстрого изучения, понимания и использования, а также для обеспечения чистого и единообразного синтаксиса. Обратите внимание, что Python 2 официально не поддерживается с 01.01.2020. Тем не менее, для вопросов о Python, связанных с версией, добавьте тег [python-2.7] или [python-3.x]. При использовании варианта Python (например, Jython, PyPy) или библиотеки (например, Pandas и NumPy) включите его в теги.