budget/pfbudget/graph.py
2021-04-24 01:03:52 +01:00

243 lines
7.8 KiB
Python

import matplotlib.pyplot as plt
from .categories import (
get_income_categories,
get_fixed_expenses,
get_required_expenses,
get_health_expenses,
get_discretionary_expenses,
)
from .transactions import load_transactions, daterange, by_month_and_category
def monthly(state, start, end):
transactions = load_transactions(state.data_dir)
if not start:
start = transactions[0].date
if not end:
end = transactions[-1].date
income, fixed, required, health, discretionary = [], [], [], [], []
monthly_transactions_by_categories = by_month_and_category(transactions, start, end)
for _, transactions_by_category in monthly_transactions_by_categories.items():
income.append(
sum(
float(t.value)
for category, transactions in transactions_by_category.items()
if transactions and category in get_income_categories()
for t in transactions
)
)
fixed.append(
sum(
-float(t.value)
for category, transactions in transactions_by_category.items()
if transactions and category in get_fixed_expenses()
for t in transactions
)
)
required.append(
sum(
-float(t.value)
for category, transactions in transactions_by_category.items()
if transactions and category in get_required_expenses()
for t in transactions
)
)
health.append(
sum(
-float(t.value)
for category, transactions in transactions_by_category.items()
if transactions and category in get_health_expenses()
for t in transactions
)
)
discretionary.append(
sum(
-float(t.value)
for category, transactions in transactions_by_category.items()
if transactions and category in get_discretionary_expenses()
for t in transactions
)
)
plt.figure(figsize=(30, 10))
plt.plot(daterange(start, end, "month"), income, label="Income")
plt.stackplot(
daterange(start, end, "month"),
fixed,
required,
health,
discretionary,
labels=["Fixed", "Required", "Health", "Discretionary"],
)
plt.legend(loc="upper left")
plt.tight_layout()
plt.savefig("graph.png")
def discrete(state, start, end):
transactions = load_transactions(state.data_dir)
if not start:
start = transactions[0].date
if not end:
end = transactions[-1].date
income, fixed, required, health, discretionary = [], [], [], [], []
monthly_transactions_by_categories = by_month_and_category(transactions, start, end)
for _, transactions_by_category in monthly_transactions_by_categories.items():
income.append(
sum(
float(t.value)
for category, transactions in transactions_by_category.items()
if transactions and category in get_income_categories()
for t in transactions
)
)
fixed.append(
sum(
-float(t.value)
for category, transactions in transactions_by_category.items()
if transactions and category in get_fixed_expenses()
for t in transactions
)
)
required.append(
sum(
-float(t.value)
for category, transactions in transactions_by_category.items()
if transactions and category in get_required_expenses()
for t in transactions
)
)
health.append(
sum(
-float(t.value)
for category, transactions in transactions_by_category.items()
if transactions and category in get_health_expenses()
for t in transactions
)
)
d = []
for category, transactions in transactions_by_category.items():
if category in get_discretionary_expenses():
try:
d.append(sum(-float(t.value) for t in transactions))
except TypeError:
d.append(0)
discretionary.append(d)
# transposing discretionary
discretionary = list(map(list, zip(*discretionary)))
plt.figure(figsize=(30, 10))
plt.plot(daterange(start, end, "month"), income, label="Income")
plt.stackplot(
daterange(start, end, "month"),
fixed,
required,
health,
*discretionary,
labels=["Fixed", "Required", "Health", *get_discretionary_expenses()],
)
plt.legend(loc="upper left")
plt.grid()
plt.tight_layout()
plt.savefig("graph.png")
def average(state, start, end):
transactions = load_transactions(state.data_dir)
income, fixed, required, health, discretionary = [], [], [], [], []
monthly_transactions_by_categories = by_month_and_category(transactions, start, end)
for _, transactions_by_category in monthly_transactions_by_categories.items():
income.append(
sum(
float(t.value)
for category, transactions in transactions_by_category.items()
if transactions and category in get_income_categories()
for t in transactions
)
)
fixed.append(
sum(
-float(t.value)
for category, transactions in transactions_by_category.items()
if transactions and category in get_fixed_expenses()
for t in transactions
)
)
required.append(
sum(
-float(t.value)
for category, transactions in transactions_by_category.items()
if transactions and category in get_required_expenses()
for t in transactions
)
)
health.append(
sum(
-float(t.value)
for category, transactions in transactions_by_category.items()
if transactions and category in get_health_expenses()
for t in transactions
)
)
d = []
for category, transactions in transactions_by_category.items():
if category in get_discretionary_expenses():
try:
d.append(sum(-float(t.value) for t in transactions))
except TypeError:
d.append(0)
discretionary.append(d)
# transposing discretionary
discretionary = list(map(list, zip(*discretionary)))
print(discretionary)
n = len(daterange(start, end, "month"))
avg_income = sum(income) / n
l_avg_income = [avg_income] * n
avg_fixed = [sum(fixed) / n] * n
avg_required = [sum(required) / n] * n
avg_health = [sum(health) / n] * n
avg_discretionary = [[sum(d) / n] * n for d in discretionary]
print(avg_discretionary)
plt.figure(figsize=(30, 10))
plt.plot(daterange(start, end, "month"), l_avg_income, label=f"Income {avg_income}")
plt.stackplot(
daterange(start, end, "month"),
avg_fixed,
avg_required,
avg_health,
*avg_discretionary,
labels=[
f"Fixed {avg_fixed[0]/avg_income * 100}%",
f"Required {avg_required[0]/avg_income * 100}%",
f"Health {avg_health[0]/avg_income * 100}%",
*[
f"{e} {avg_discretionary[i][0]/avg_income * 100}%"
for i, e in enumerate(get_discretionary_expenses())
],
],
)
plt.legend(bbox_to_anchor=(1, 1), loc="upper left")
plt.tight_layout()
plt.savefig(
"graph.png",
dpi=600,
)