Объединить два фрейма данных по значению в столбце df1 в значениях, разделенных запятыми, в столбцах df2 И df1.Column2 = df2.Column2

#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 *’) — обслуживает начальные и конечные пробелы