简体   繁体   中英

Combine dataframes to allocate lenders to borrowers, in pandas

I have two dataframes: lenders and borrowers. I want to combine values from lenders to borrowers, as below.

LenderDF = pd.DataFrame({
'LenderID':['Lender 1', 'Lender 2','Lender 3','Lender 4', 'Lender 5'],
'AmountHave': [300, 150, 500, 100, 200]
})
borrowerDF = pd.DataFrame({
'borrowerID': ['Borrower 1', 'Borrower 2','Borrower 3','Borrower 4'],
'AmountNeed': [100,200,150,300]
 })

print(LenderDF)
print(borrowerDF)

   LenderID  AmountHave
0  Lender 1         300
1  Lender 2         150
2  Lender 3         500
3  Lender 4         100
4  Lender 5         200

   borrowerID  AmountNeed
0  Borrower 1         100
1  Borrower 2         200
2  Borrower 3         150
3  Borrower 4         300

The final output I'm trying to get is:

   BorrowerID  AmountNeeded  LenderID  LenderHave(after lending amount)  RemainingAmount
0  Borrower 1           100  Lender 1                                     300              200
1  Borrower 2           200  Lender 1                                     200                0
2  Borrower 3           150  Lender 2                                     150                0
3  Borrower 4           300  Lender 3                                     500              200

Example:

  • First lender has 300 so they can lend money to (say) Borrower 1 and Borrower 2:
  • 300 ( firstLender ) >= 100 ( firstBorrower Amount needed )
  • So assign or set value of First lender "Lender 1" to the Borrower who took the money and set the remaining value 200 First value of AmountLenderHave will be 300 since this is the first time that person is lending amount.
  • 200(firstLender) >= 200 (secondBorrower amount needed)

Likeise, iterate on each lender row and so on, until no lender is remaining.

I don't think there's a good way to do this using pandas join functions, it's really a problem where you should iterate over a list of borrowers. The below does what you are after:

import pandas as pd

LenderDF = pd.DataFrame({
'LenderID':['Lender 1', 'Lender 2','Lender 3','Lender 4', 'Lender 5'],
'AmountHave': [300, 150, 500, 100, 200]
})
borrowerDF = pd.DataFrame({
'borrowerID': ['Borrower 1', 'Borrower 2','Borrower 3','Borrower 4'],
'AmountNeed': [100,200,150,300]
 })

lenders = LenderDF.to_dict(orient='records')
borrowers = borrowerDF.to_dict(orient='records')

for borrower in borrowers:
    # get next lender who can pay
    amount_needed = borrower['AmountNeed']
    lender = next(lender for lender in lenders if lender['AmountHave'] >= amount_needed)
    borrower['LenderID'] = lender['LenderID']
    borrower['LenderHave'] = lender['AmountHave']
    borrower['LenderRemaining'] = lender['AmountHave'] - amount_needed
    # Update lenders amount
    lender['AmountHave'] -= amount_needed


print(pd.DataFrame(borrowers))

   borrowerID  AmountNeed  LenderID  LenderHave  LenderRemaining
0  Borrower 1         100  Lender 1         300              200
1  Borrower 2         200  Lender 1         200                0
2  Borrower 3         150  Lender 2         150                0
3  Borrower 4         300  Lender 3         500              200

Here is my solution. I too convert the dataframe to lists. This code also takes care of the situation where a borrower has to borrow from multiple lenders, as in the example below:

import pandas as pd
lenderDF = pd.DataFrame({
'LenderID':['Lender 1', 'Lender 2','Lender 3','Lender 4', 'Lender 5'],
'AmountHave': [300, 150, 500, 100, 200]
})
borrowerDF = pd.DataFrame({
'borrowerID': ['Borrower 1', 'Borrower 2','Borrower 3','Borrower 4'],
'AmountNeed': [100,300,150,300]
 })

lender_have = lenderDF["AmountHave"].tolist()
borrower_need = borrowerDF["AmountNeed"].tolist()

borrowerID = []
lenderID = []
borrower_remaining_need = [borrower_need[0]]
lender_before = [lender_have[0]]
lender_after = []
l = 0
b = 0
while b < len(borrower_need):
    borrowerID.append(f'Borrower {b + 1}')
    lenderID.append(f'Lender {l + 1}')
    remaining_funds = lender_before[-1] - borrower_remaining_need[-1]

    if remaining_funds > 0:
        lender_after.append(remaining_funds)
        lender_before.append(remaining_funds)
        b += 1
        if b< len(borrower_need):
            borrower_remaining_need.append(borrower_need[b])

    elif remaining_funds < 0:
        lender_after.append(0)
        borrower_remaining_need.append(borrower_remaining_need[-1] - lender_before[-1])
        if l+1 < len(lender_have):
            lender_before.append(lender_have[l+1])
        l += 1

    elif remaining_funds == 0:
        lender_after.append(0)
        if l+1 < len(lender_have):
            lender_before.append(lender_have[l+1])
        if b+1 < len(borrower_need):
            borrower_remaining_need.append(borrower_need[b+1])
        b += 1
        l += 1

if len(lender_before) > len(borrowerID):
    lender_before.pop()

result_df = pd.DataFrame({"BorrowrID": borrowerID, "Amount Needed": borrower_remaining_need,
                          "LenderID": lenderID, "Lender Before": lender_before, "Lender After":lender_after},)

print(result_df)

    BorrowrID  Amount Needed  LenderID  Lender Before  Lender After
0  Borrower 1            100  Lender 1            300           200
1  Borrower 2            300  Lender 1            200             0
2  Borrower 2            100  Lender 2            150            50
3  Borrower 3            150  Lender 2             50             0
4  Borrower 3            100  Lender 3            500           400
5  Borrower 4            300  Lender 3            400           100

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM