#pandas #dataframe #join #merge
Вопрос:
Я считываю данные из файла xlsx с помощью pandas — и создаю фрейм данных для каждой рабочей книги, найденной в файле xlsx, и содержащей, например, данные о рабочих местах людей, образовании людей и предыдущем опыте работы людей. таким образом, в конце я работаю примерно с 13 кадрами данных. все фреймы данных имеют общий столбец «talent_id», с помощью которого они могут быть объединены (объединены) в какой-то более поздний момент. проблема, с которой я в настоящее время сталкиваюсь, заключается в том, что в df1 идентификатор таланта уникален, в df2 «идентификатор таланта» не уникален из-за того, что в прошлом у людей могло быть несколько образований (поэтому каждая работа, которую они выполняли ранее, является наблюдением), то же самое с df3, который дает мне весь предыдущий опыт работы для каждого отдельного «идентификатора таланта».
Итак, чего я пытаюсь достичь, в конце концов, у меня есть один df, который содержит всю информацию из df1, df2 и df3 без дублированных строк «talent_id», а не по 1 строке на «talent_id» и столбцы для всех образовательных организаций и бывших работодателей в виде столбцов или функций.
Вот код для создания df — я возился с melt(), join(), merge (), давая мне не то, что я хотел.
Излишне говорить, что не у каждого talent_id одинаковое количество учебных заведений, некоторые посещали 2 школы, некоторые 2 школы и 3 колледжа и т. Д., Поэтому количество функций варьируется, равно как и количество предыдущего опыта работы.
data1 = [['001', '1975-01-01', 'mr', 'de', 'at', 40000], ['002', '1980-01-01', 'mrs', 'en', 'uk', 50000], ['003', '1985-01-01', 'mr', 'es', 'es', 45000]]
df1 = pd.DataFrame(data1, columns = ['talent_id', 'birthdate', 'salutation', 'nationality', 'country', 'salary'])
data2 = [['001', 'groundschool_a', 'NaN', 'basic', 'none', 'yes'], ['001', 'high_school', 'math', 'higher', 'none', 'no'], ['002', 'groundschool_b', 'NaN', 'basic', 'none', 'yes'],
['002', 'highschool', 'science', 'higher', 'yes', 'yes'], ['002', 'college', 'medicine', 'degree', 'MA', 'yes'], ['003', 'NA', 'none', 'dont know', 'none', 'NaN']]
df2 = pd.DataFrame(data2, columns = ['talent_id', 'schoolname', 'subject', 'type_of_education', 'degree', 'completed'])
data3 = [['001', 'company_a', 'supervisor', 'manufacturing'], ['001', 'company_b', 'editor', 'educational'], ['002', 'company_c', 'clerk', 'pos'],
['002', 'company_d', 'cleaning', 'steel'], ['002', 'company_e', 'ceo', 'sales'], ['003', 'company_f', 'it', 'retail']]
df3 = pd.DataFrame(data3, columns = ['talent_id', 'company', 'position', 'industry'])
В идеале приемлемый результат был бы примерно таким:
data4 = [['001', '1975-01-01', 'mr', 'de', 'at', 40000,
'groundschool_a', 'NaN', 'basic', 'none', 'yes', 'high_school', 'math', 'higher', 'none', 'no',
'company_a', 'supervisor', 'manufacturing', 'company_b', 'editor', 'educational', 'NA','NA','NA','NA','NA', 'NA', 'NA', 'NA'],
['002', '1980-01-01', 'mrs', 'en', 'uk', 50000,
'groundschool_b', 'NaN', 'basic', 'none', 'yes', 'highschool', 'science', 'higher', 'yes', 'yes', 'college', 'medicine', 'degree', 'MA', 'yes',
'company_c', 'clerk', 'pos', 'company_d', 'cleaning', 'steel', 'company_e', 'ceo', 'sales'],
['003', '1985-01-01', 'mr', 'es', 'es', 45000, 'NA', 'none', 'dont know', 'none', 'NaN',
'company_f', 'it', 'retail', 'NA','NA','NA','NA','NA','NA','NA','NA','NA','NA', 'NA', 'NA', 'NA', 'NA', 'NA', 'NA']]
df4 = pd.DataFrame(data4, columns = ['talent_id', 'birthdate', 'salutation', 'nationality', 'country', 'salary',
'schoolname_1', 'subject_1', 'type_of_education_1', 'degree_1', 'completed_1',
'schoolname_2', 'subject_2', 'type_of_education_2', 'degree_2', 'completed_2',
'schoolname_3', 'subject_3', 'type_of_education_3', 'degree_3', 'completed_3',
'company_1', 'position', 'industry',
'company_2', 'position', 'industry',
'company_2', 'position', 'industry'])
Я думал о том, чтобы проанализировать каждый df для определенного «talent_id», записать его в список и, в конце концов, сделать df из этого списка, но есть ли более разумный и эффективный способ сделать это ?
Ответ №1:
Сначала создайте небольшую вспомогательную функцию для обработки ваших фреймов данных 2 и 3:
def group_pivot(d):
d =(d.assign(group=d.groupby('talent_id').cumcount())
.pivot(index='talent_id', columns='group', values=d.columns[1:])
)
d.columns = ['_'.join(map(str, c)) for c in d.columns]
return d.reset_index()
пример на df3:
>>> group_pivot(df3)
talent_id company_0 company_1 company_2 position_0 position_1 position_2 industry_0 industry_1 industry_2
0 001 company_a company_b NaN supervisor editor NaN manufacturing educational NaN
1 002 company_c company_d company_e clerk cleaning ceo pos steel sales
2 003 company_f NaN NaN it NaN NaN retail NaN NaN
Затем объедините все преобразованные кадры данных в «talent_id».:
df1.merge(group_pivot(df2), on='talent_id').merge(group_pivot(df3), on='talent_id')
выход:
talent_id birthdate salutation nationality country salary schoolname_0 schoolname_1 schoolname_2 subject_0 subject_1 subject_2 type_of_education_0 type_of_education_1 type_of_education_2 degree_0 degree_1 degree_2 completed_0 completed_1 completed_2 company_0 company_1 company_2 position_0 position_1 position_2 industry_0 industry_1 industry_2
0 001 1975-01-01 mr de at 40000 groundschool_a high_school NaN NaN math NaN basic higher NaN none none NaN yes no NaN company_a company_b NaN supervisor editor NaN manufacturing educational NaN
1 002 1980-01-01 mrs en uk 50000 groundschool_b highschool college NaN science medicine basic higher degree none yes MA yes yes yes company_c company_d company_e clerk cleaning ceo pos steel sales
2 003 1985-01-01 mr es es 45000 NA NaN NaN none NaN NaN dont know NaN NaN none NaN NaN NaN NaN NaN company_f NaN NaN it NaN NaN retail NaN NaN
Комментарии:
1. Большое вам спасибо, я провел несколько тестов с помощью вспомогательной функции, которую вы придумали, — кажется, это хорошо работает — в настоящее время я запускаю это на образце набора данных с 500 строками, и это довольно быстро. производственный набор данных содержит примерно 40 тысяч строк — будем с нетерпением его ждать … ценю ваше время и усилия, чтобы помочь мне …
Ответ №2:
Вы можете использовать следующий groupby
метод agg
для создания списка из переменных, таких как образование в вашем примере. Например:
df2.groupby('talent_id').agg({
'education':list
})
Это сделает приложение talent_id
уникальным и сохранит все в виде списка, к которому вы можете присоединиться. Позже вы можете использовать соответствующие инструменты, такие как разложение его по столбцам, чтобы разложить их для вашего анализа или ожиданий.
Примечание: Метод groupby
создает talent_id
индекс, поэтому используйте соответствующие параметры в merge
методе для объединения ваших фреймов данных вместе.