Как я могу сопоставить два фрейма данных и получить следующий результат? - PullRequest
1 голос
/ 21 февраля 2020

У меня есть следующий df_project:

df_project = pd.DataFrame({'Project':['A','B','C'],'Day':[1,5,10],'Cost':[100,200,300]})

Project Day Cost
A       1   100
B       5   200
C       10  300

У меня также есть следующий df_payment:

df_payment = pd.DataFrame({'Payment':['P1','P2','P3','P4','P5','P6'],'Day':[2,3,5,6,7,11],'Amount':[50,40,100,50,70,280]})

Payment Day Amount
P1      2   50
P2      3   40
P3      5   100
P4      6   50
P5      7   70
P6      11  280

Я хочу получить следующий результат:

df_result = pd.DataFrame({'Project':['A','A','A','B','B','B','np.Nan','C','C'],'Payment':['P1','P2',np.nan,'P3','P4','P5','P5','P6',np.nan],'Amount':[50,40,10,100,50,50,20,280,20]})

Project Payment Amount
A       P1      50.0
A       P2      40.0
A       NaN     10.0
B       P3      100.0
B       P4      50.0
B       P5      50.0
NaN     P5      20.0
C       P6      280.0
C       NaN     20.0

Логика c заключается в следующем: 1. Платеж должен совпадать с проектом, где день больше или равен

, поэтому мы можем видеть, что P1 и P2 соответствуют A, P3, P4, P5 соответствуют B и P6 соответствуют C

После сопоставления платежа с проектом у нас в основном есть следующий фрейм данных:
Project Payment 
A       P1      
A       P2      
B       P3      
B       P4      
B       P5      
C       P6      

, затем мы также сопоставляем df_payment ['Amount'] с df_project ['Cost']

Итак, (P1,50) и (P2,40) сопоставлены с A, но стоимость A равна 100, дефицит равен 10, поэтому для платежа установлено значение NaN

Затем для проекта B , (P3,100), (P4,50), (P5,70) имеют избыток 20, поэтому для проекта установлено значение NaN для дополнительных 20 остатков

Аналогично для проекта C (P6 , 280) имеет дефицит 20, поэтому результат будет таким:

Project Payment Amount
A       P1      50.0
A       P2      40.0
A       NaN     10.0
B       P3      100.0
B       P4      50.0
B       P5      50.0
NaN     P5      20.0
C       P6      280.0
C       NaN     20.0

Есть ли способ сделать это?

1 Ответ

1 голос
/ 21 февраля 2020

используйте merge_asof для объединения в ближайшие дни * Функция 1003 *

M = pd.merge_asof(df_payment,df_project,on='Day').drop('Day',axis=1)

помогает прикрепить разницу между стоимостью и суммой обратно к фрейму данных

def attach_difference(df):
    A = df.Amount.sum()
    B = df.Cost.max()
    C = df.shape[0]
    D = df.Payment.iloc[-1]
    df = df.reset_index(drop=True)
    if A-B < 0:
        df.loc[C]=  {'Payment':np.nan,
                     'Amount':abs(A-B), 
                     'Project':df.Project.unique()[0],
                     'Cost':np.nan}

    elif A - B > 0 : 
        df.loc[C-1,'Amount'] = df.loc[C-1,'Amount'] - (A-B)
        df.loc[C]=  {'Payment':D,
                     'Amount':A-B, 
                     'Project':np.nan,
                     'Cost':np.nan}


    return df


запустить понимание списка и передать функцию каждой группе

outcome = [group.pipe(attach_difference)
           .drop('Cost',axis=1)
           for name, group in M.groupby('Project')]

(pd.concat(outcome,ignore_index=True)
 .reindex(['Project','Payment','Amount'],
          axis=1)
 )



   Project  Payment Amount
0     A       P1    50
1     A       P2    40
2     A       NaN   10
3     B       P3    100
4     B       P4    50
5     B       P5    50
6     NaN     P5    20
7     C       P6    280
8     C       NaN   20
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...