And here’s a simpler way, in case it’s OK to have missing
instead of 0
values for accounts that are not touched by a transaction:
using DataFrames
accounts = DataFrame()
journal = DataFrame()
function transaction!(date, debit_account, debit_amount, credit_account, credit_amount)
if debit_amount != credit_amount
error("Debit ($debit_amount) and credit ($credit_amount) must match")
end
push!(accounts, cols=:union, Dict(debit_account*"_debit" => debit_amount,
credit_account*"_credit" => credit_amount))
push!(journal, (; date, debit_account, credit_account, debit_amount, credit_amount))
end
transaction!("Jan 1, 2019", "Wages", 1000, "Chequing", 1000)
transaction!("Jan 2, 2019", "Personal", 300, "Rent", 300)
julia> accounts
2×4 DataFrame
Row │ Chequing_credit Wages_debit Rent_credit Personal_debit
│ Int64? Int64? Int64? Int64?
─────┼───────────────────────────────────────────────────────────
1 │ 1000 1000 missing missing
2 │ missing missing 300 300
julia> journal
2×5 DataFrame
Row │ date debit_account credit_account debit_amount credit_amount
│ String String String Int64 Int64
─────┼─────────────────────────────────────────────────────────────────────────
1 │ Jan 1, 2019 Wages Chequing 1000 1000
2 │ Jan 2, 2019 Personal Rent 300 300
For the journal, columns are created implicitly when the first row is added. For accounts
, columns are added as required every time a row is pushed that uses new accounts. With the keyword argument cols=:union
we don’t need to give default values for the row: unspecified values are set to missing
.