Create an app that tracking income and expense and can visualize as line chart, bar chart or pie chart
To upload files, please first save the app
import streamlit as st
import pandas as pd
from datetime import datetime
from sqlalchemy import create_engine, Column, Integer, Float, String, Date
from sqlalchemy.orm import DeclarativeBase, Session
import plotly.express as px
# Database setup
class Base(DeclarativeBase):
pass
class Transaction(Base):
__tablename__ = 'transactions'
id = Column(Integer, primary_key=True)
date = Column(Date, nullable=False)
type = Column(String, nullable=False) # 'income' or 'expense'
category = Column(String, nullable=False)
amount = Column(Float, nullable=False)
description = Column(String)
# Create database engine
engine = create_engine('sqlite:///finance.db')
Base.metadata.create_all(engine)
# Page config
st.set_page_config(page_title="Finance Tracker", layout="wide")
st.title("💰 Finance Tracker")
# Sidebar
with st.sidebar:
st.header("Add New Transaction")
# Input form
with st.form("transaction_form"):
date = st.date_input("Date", datetime.now())
trans_type = st.selectbox("Type", ["Income", "Expense"])
# Different categories based on transaction type
if trans_type == "Income":
categories = ["Salary", "Investment", "Business", "Other"]
else:
categories = ["Food", "Transportation", "Housing", "Entertainment", "Shopping", "Healthcare", "Other"]
category = st.selectbox("Category", categories)
amount = st.number_input("Amount", min_value=0.0, format="%.2f")
description = st.text_input("Description (optional)")
submit = st.form_submit_button("Add Transaction")
if submit:
with Session(engine) as session:
transaction = Transaction(
date=date,
type=trans_type.lower(),
category=category,
amount=amount,
description=description
)
session.add(transaction)
session.commit()
st.success("Transaction added successfully!")
# Main content
col1, col2 = st.columns([2, 1])
with col1:
# Chart type selector
chart_type = st.selectbox("Select Chart Type", ["Line", "Bar", "Pie"])
# Get data from database
with Session(engine) as session:
query = session.query(Transaction)
df = pd.read_sql(query.statement, engine)
if not df.empty:
df['date'] = pd.to_datetime(df['date'])
if chart_type == "Line":
# Create daily totals for income and expenses
daily_totals = df.pivot_table(
index='date',
columns='type',
values='amount',
aggfunc='sum'
).fillna(0)
fig = px.line(daily_totals, title="Income vs Expenses Over Time")
st.plotly_chart(fig, use_container_width=True)
elif chart_type == "Bar":
monthly_totals = df.groupby(['type', 'category'])['amount'].sum().reset_index()
fig = px.bar(monthly_totals, x='category', y='amount', color='type',
title="Total by Category and Type",
labels={'amount': 'Total Amount', 'category': 'Category'})
st.plotly_chart(fig, use_container_width=True)
else: # Pie chart
fig = px.pie(df, values='amount', names='category',
title="Distribution by Category")
st.plotly_chart(fig, use_container_width=True)
else:
st.info("No transactions recorded yet. Add some transactions to see the charts!")
with col2:
st.subheader("Recent Transactions")
if not df.empty:
# Show recent transactions
recent = df.sort_values('date', ascending=False).head(5)
for _, row in recent.iterrows():
with st.container():
st.write(f"**{row['date'].strftime('%Y-%m-%d')}**")
st.write(f"Type: {row['type'].title()}")
st.write(f"Category: {row['category']}")
st.write(f"Amount: ${row['amount']:.2f}")
if row['description']:
st.write(f"Description: {row['description']}")
st.divider()
else:
st.info("No transactions to display")
Hi! I can help you with any questions about Streamlit and Python. What would you like to know?