#python #pandas #dataframe #merge
#python #панды #фрейм данных #объединить
Вопрос:
Входные данные: два фрейма данных, имеющих следующие значения:
df1:
| Employee Name | EmployeeID | workDate |
|---------------|------------|------------|
| John | 2,22 | 2020-11-01 |
| John | 2,22 | 2020-11-02 |
| Kim | 3 | 2020-11-01 |
df2:
| EmployeeID | workDate | Hours |
|------------|------------|-------|
| 2 | 2020-11-01 | 8 |
| 22 | 2020-11-02 | 2 |
| 3 | 2020-11-01 | 10 |
Необходимо объединить эти два фрейма данных в df2.EmployeeID в df1.EmployeeIDs И df2.workDate == df1.workDate.
Вывод:
| Employee Name | EmployeeID | workDate | Hours |
|---------------|------------|------------|-------|
| John | 2,22 | 2020-11-01 | 8 |
| John | 2,22 | 2020-11-02 | 2 |
| Kim | 3 | 2020-11-01 | 10 |
Комментарии:
1. df2 = pd.merge(df,df1,on = [‘EmployeeID’,’workDate’], how = ‘outer’)
2. не сработает. df1.EmployeeID — это разделенное запятыми поле с несколькими идентификаторами EmployeeID. df2.EmployeeID имеет только один из этих идентификаторов EmployeeID
Ответ №1:
Используйте DataFrame.explode
с разделенными значениями by ,
, затем используйте DataFrame.merge
с левым соединением и последним агрегированием обратно by GroupBy.agg
:
#converted to strings for match splitted values
df2['EmployeeID'] = df2['EmployeeID'].astype(str)
df1 = (df1.assign(EmployeeID = df1['EmployeeID'].str.split('s*,s*'))
.explode('EmployeeID')
.merge(df2, on=['EmployeeID','workDate'], how='left')
.groupby(['Employee Name','workDate'], as_index=False, sort=False)
.agg({'EmployeeID':','.join, 'Hours':'sum'}))
print (df1)
Employee Name workDate EmployeeID Hours
0 John 2020-11-01 2,22 8.0
1 John 2020-11-02 2,22 2.0
2 Kim 2020-11-01 3 10.0
Комментарии:
1. Я думаю, нам нужно разделить значения в EmployeeID, чтобы это стало чем-то вроде: df1.assign(EmployeeID = df1[«EmployeeID»].str.split(«,»).apply(лямбда-строка: [value.strip() для значения в строке]) верно?
2. @programming_ocd — Или более простое
df1['EmployeeID'].str.split(',')
изменение наdf1['EmployeeID'].str.split(' ,')
него означает','
изменение на' ,'
3. @programming_ocd — Ок, поэтому используйте регулярное выражение, как будто
's*,'
оно означает ноль или более пробелов и ,4. @programming_ocd — да, это то же самое.
5. конечный результат: df1.assign(EmployeeID = df1[«EmployeeID»].str.split(‘s *,s *’) — обслуживает начальные и конечные пробелы