-1

小さなローン ショップに関するデータセットがあり、そのローンが担保付証券でどの程度カバーされているかを知りたいとします。問題は、私は 1 つのローンに対して複数の証券を差し入れており、複数のローンに対して 1 つの証券を差し入れているということです。

cAID cID cLoan sID sAmount
1   10  50   200 100    1100
2   11  50  1000 100    1100
3   12  60  1000 110     900
4   12  60  1000 120     300
5   14  80  1000 140    1200
6   15  90  1000 150     900

ローンに割り当てられた担保の額はローンを超えてはならず、担保がローンよりも高く、その担保に裏打ちされた別のローンがある場合は、残りをそれに割り当てる必要があります。

理想的には、次のように終了することを望みます。

cAIDa cIDa cLoanA sIDa sAmountA asignedSAmountA CoverageRatio
1    10   50    200  100     1100             200           1.0
2    11   50   1000  100     1100             900           0.9
3    12   60   1000  110      900            1000           1.0
4    12   60   1000  120      300            1000           1.0
5    14   80   1000  140     1200            1000           1.0
6    15   90   1000  150      900             900           0.9

これらの他の 2 つの列を R または Excel で生成するにはどうすればよいですか? 基本的に、最終的には、一意のクライアント アカウント ID と、証券を過大にしないで割り当てられた証券の合計が必要です。最初の生のローンは 200 (cLoanA) で、保証金 (sAmountA) は 1100 であるため、割り当てられた保証金はローンの最大値 (assignedSAmountA) であるため 200 ですが、次のローンには同じセキュリティが使用され (同じ sIDa に注意してください)、1100 でした。最初のローンの 200 を差し引くと、2 行目の cLoanA が 1000 であるため、残りは 900 になります。したがって、保証金の全額を使用し、レシオは 0.9 であり、これは一部が無担保であることを意味します。これは、assignedSAmountA と Coverage ratio の最初の数を導き出す方法です。

R での私のコード: `

#example client AccountID
cAIDa <- c(10, 11, 12, 12, 14, 15)
#example client AccountID
cAIDa <- c(10, 11, 12, 12, 14, 15)
#example client ID
cIDa <- c(50, 50, 60, 60, 80, 90)
#example loan amount
cLoanA <- c(200, 1000, 1000, 1000, 1000, 1000)
#example security pledged ID
sIDa <- c(100, 100, 110, 120, 140, 150)
#example security pledged Amount
sAmountA <- c(1100,1100,900,300,1200, 900)

# generate initial data.frame 
portfolioOne <- data.frame(cAIDa,cIDa,cLoanA,sIDa,sAmountA)
portfolioOne

#assign security sum by unique account id
asignedSAmountA <- c(200, 900, 1200, 1200, 1000, 900)
portfolioTwo <- data.frame(cAIDa,cIDa,cLoanA,sIDa,sAmountA, asignedSAmountA)
ratio1 <- asignedSAmountA/portfolioOne$cLoanA
portfolioTwo$CoverageRatio <- ratio1
portfolioTwo
4

2 に答える 2

4

OK、これであなたが何を望んでいるのか理解できました。

元のデータから得た結果は次のとおりです。

    cAIDa  cIDa cLoanA  sIDa sAmountA asignedSAmountA  CoverageRatio
    10      50    200   100    1100         200             1.0
    11      50   1000   100    1100         900             0.9
    12      60   1000   110     900        1000             1.0
    12      60   1000   120     300        1000             1.0
    14      80   1000   140    1200        1000             1.0
    15      90   1000   150     900         900             0.9

これを取得するために実行した VBA マクロは次のとおりです。

Option Explicit
Sub AllocateSecurity()
    Dim colSec As Collection
    Dim dSec() As Double
    Dim dSecIndex() As Double
    Dim colLoan As Collection
    Dim dLoan() As Double
    Dim dLoanIndex() As Double
    Dim rSrc As Range, vSrc As Variant
    Dim vRes() As Variant
    Dim i As Long, j As Long, d As Double, v As Variant
    Dim rDest As Range

Set rDest = Range("J1")

'Get Original Data
Set rSrc = Range("A1", Cells(Rows.Count, "A").End(xlUp)) _
    .Resize(columnsize:=5)
vSrc = rSrc

'Securities
Set colSec = New Collection
On Error Resume Next
For i = 2 To UBound(vSrc)
    colSec.Add Item:=vSrc(i, 4), Key:=CStr(vSrc(i, 4))
Next i
On Error GoTo 0
ReDim dSec(1 To colSec.Count, 0 To 1)
ReDim dSecIndex(1 To colSec.Count)
For i = 1 To colSec.Count
    dSec(i, 0) = colSec(i)
    dSecIndex(i) = colSec(i)
    dSec(i, 1) = WorksheetFunction.VLookup(colSec(i), _
        Range(rSrc.Columns(4), rSrc.Columns(5)), 2, False)
Next i

'Loans
Set colLoan = New Collection
On Error Resume Next
For i = 2 To UBound(vSrc)
    colLoan.Add Item:=vSrc(i, 1), Key:=CStr(vSrc(i, 1))
Next i
On Error GoTo 0
ReDim dLoan(1 To colLoan.Count, 0 To 1)
ReDim dLoanIndex(1 To colLoan.Count)
For i = 1 To colLoan.Count
    dLoan(i, 0) = colLoan(i)
    dLoanIndex(i) = colLoan(i)
    'covered amt
    dLoan(i, 1) = WorksheetFunction.VLookup(colLoan(i), _
        rSrc, 3, False)
Next i


'Set up Results Array
ReDim vRes(1 To UBound(vSrc), 1 To UBound(vSrc, 2) + 2)

'Headers
v = Array("cAIDa", "cIDa", "cLoanA", "sIDa", "sAmountA", "asignedSAmountA", "CoverageRatio")
For i = 0 To UBound(v)
    vRes(1, i + 1) = v(i)
Next i

With WorksheetFunction
For i = 2 To UBound(vSrc)
    For j = 1 To UBound(vSrc, 2)
        vRes(i, j) = vSrc(i, j)
    Next j
    'LOAN = VSRC(I,1)
    'LOANAMT = DLOAN(.MATCH(LOAN,DLOANINDEX,0),1)
    'SEC = VSRC(I,4)
    'SECAMT = DSEC(.MATCH(SEC,DSECINDEX,0),1)
        'assSecamt
        vRes(i, 6) = .Min(dSec(.Match(vSrc(i, 4), dSecIndex, 0), 1), dLoan(.Match(vSrc(i, 1), dLoanIndex, 0), 1))
        'reduce loan and sec
        dLoan(.Match(vSrc(i, 1), dLoanIndex, 0), 1) = dLoan(.Match(vSrc(i, 1), dLoanIndex, 0), 1) - vRes(i, 6)
        dSec(.Match(vSrc(i, 4), dSecIndex, 0), 1) = dSec(.Match(vSrc(i, 4), dSecIndex, 0), 1) - vRes(i, 6)
Next i
End With

'coverage ratio:  1 - (uncovered amt/ orig amt)
'adjust assigned amt
With WorksheetFunction
For i = 2 To UBound(vRes)
    vRes(i, 7) = 1 - (dLoan(.Match(vRes(i, 1), dLoanIndex, 0), 1) / vRes(i, 3))
    vRes(i, 6) = vRes(i, 3) * vRes(i, 7)
Next i
End With

Set rDest = rDest.Resize(rowsize:=UBound(vRes), columnsize:=UBound(vRes, 2))

    Application.ScreenUpdating = False
rDest.EntireColumn.Clear
rDest = vRes
rDest.Columns(7).NumberFormat = "0.0"
rDest.EntireColumn.AutoFit
    Application.ScreenUpdating = True

End Sub
于 2013-10-12T20:48:39.147 に答える
1

サンプル データセットの読み取り:

portfolioOne <- read.table(text="
  cAID cID cLoan sID sAmount
1   10  50   200 100    1100
2   11  50  1000 100    1100
3   12  60  1000 110     900
4   12  60  1000 120     300
5   14  80  1000 140    1200
6   15  90  1000 150     900
")

あなたの例から、ローンがどの特定の保証金からカバーされているかは気にしないようです。それでは、アカウントの保証金の合計を詳述する列を作成してみましょうcID。次に、ローンを累積的に合計して実行中の残高を取得し、どのローンがカバーされているか、またはカバーされていないかを確認できます。

duplicated関数を使用して冗長な行を見つけることで、金額の二重カウントを回避したことに注意してください。保証金については、サブセットごとに除外しました。ローンについては、累積合計が適切な長さになるように、冗長エントリを 0 に設定しました。

data.table解決策:

library(data.table)
dat <- data.table(portfolioOne)
dat[, sTotal := sum(sAmount[!duplicated(sID)]), by = cID]
dat[, cLoanCum := cumsum({x <- cLoan; x[duplicated(cAID)] <- 0; x}), by = cID]
dat[, balance := sTotal - cLoanCum, by = cID]
dat[, assignedAmount := ifelse(balance >= 0, cLoan, pmax(0,cLoan + balance))]
dat[, CoverageRatio := assignedAmount / cLoan]

## delete intermediate columns if desired
dat[, c("sTotal","cLoanCum","balance") := NULL]
dat
   # cAID cID cLoan sID sAmount assignedAmount CoverageRatio
# 1:   10  50   200 100    1100            200           1.0
# 2:   11  50  1000 100    1100            900           0.9
# 3:   12  60  1000 110     900           1000           1.0
# 4:   12  60  1000 120     300           1000           1.0
# 5:   14  80  1000 140    1200           1000           1.0
# 6:   15  90  1000 150     900            900           0.9

plyr解決策:

library(plyr)
dat <- portfolioOne
dat <- ddply(dat, .(cID), mutate, 
    sTotal = sum(sAmount[!duplicated(sID)]),
    cLoanCum = cumsum({x <- cLoan; x[duplicated(cAID)] <- 0; x}),
    balance = sTotal - cLoanCum,
    assignedAmount = ifelse(balance >= 0, cLoan, pmax(0,cLoan + balance)),
    CoverageRatio = assignedAmount / cLoan
)
dat <- dat[,!(names(dat) %in% c("sTotal","cLoanCum","balance"))]

ベースRを使用したソリューション:

dat <- split(portfolioOne, portfolioOne$cID)
dat <- lapply(dat, within, {
    sTotal = sum(sAmount[!duplicated(sID)])
    cLoanCum = cumsum({x <- cLoan; x[duplicated(cAID)] <- 0; x})
    balance = sTotal - cLoanCum
    assignedAmount = ifelse(balance >= 0, cLoan, pmax(0,cLoan + balance))
    CoverageRatio = assignedAmount / cLoan
})
dat <- do.call(rbind, dat)
dat <- dat[,c(names(portfolioOne),"assignedAmount","CoverageRatio")]
于 2013-10-13T09:17:14.120 に答える