Recording Expenses
Part of the Logic & Flow section of Coddy's R journey. Lesson 57 of 64.
In this project you build an expense tracker that reads commands, one per line. Over five steps it learns to record expenses, report the total, group spending by category, list the biggest expenses and summarize a month. Every step extends the same tracker(commands) function.
ADD 2024-05-01 food 12.50
ADD 2024-05-02 rent 500
TOTAL
CATEGORY
TOP 2
MONTH 2024-05The expenses live in a data frame with one row per expense. It starts with three empty columns of the right types, and rbind() adds a row for each valid ADD:
expenses <- data.frame(date = character(0), category = character(0), amount = numeric(0))
expenses <- rbind(expenses, data.frame(date = "2024-05-01", category = "food", amount = 12.5))
print(nrow(expenses))
print(expenses$amount)Output:
[1] 1
[1] 12.5An ADD line must have four parts and a positive amount. Convert the amount with suppressWarnings(as.numeric()) so a bad value gives NA instead of a warning, then check it before adding the row:
parts <- strsplit("ADD 2024-05-01 food abc", " ")[[1]]
amount <- suppressWarnings(as.numeric(parts[4]))
print(length(parts) == 4 && !is.na(amount) && amount > 0)Output:
[1] FALSEChallenge
EasyComplete tracker(commands) for the first command:
ADD <date> <category> <amount>: if the line has exactly four parts and the amount is a number above 0, add the expense and replyadded <category> <amount>with the amount to two decimals, such asadded food 12.50. Otherwise replyinvalid:followed by the whole command.
The supplied code passes every input line to tracker() as one command and prints each returned reply on its own line. Dates are written YYYY-MM-DD, categories are lower-case words, and the input holds only the commands described so far.
Try it yourself
tracker <- function(commands) {
expenses <- data.frame(date = character(0), category = character(0), amount = numeric(0))
replies <- c()
for (cmd in commands) {
parts <- strsplit(cmd, " ")[[1]]
# Write your code here
}
replies
}
# Supplied input/output code: keep it as it is
input <- suppressWarnings(readLines(file("stdin")))
cat(tracker(input), sep = "\n")
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Logic & Flow
1Strings In Depth
Substrings with substr()Formatting with sprintf()Splitting and JoiningSearching StringsReplacing TextRecap - Username Builder4Matrices
Creating MatricesIndexing MatricesRow and Column SummariesMatrix ArithmeticRecap - Seating Chart2Key-Value Lookups
Named Vector LookupsChecking KeysAdding and Removing KeysLooping Over NamesRecap - Stock Desk3Sets and Counting
Unique ValuesSet OperationsMembership TestsCounting with table()Recap - Event Guests6Functions as Values
Anonymous FunctionsPassing FunctionsReturning FunctionsClosures with StateRecap - Discount Rules9Data Frames
Creating Data FramesColumns and RowsFiltering RowsAdding and SortingRecap - Sales Report12Project - Expense Tracker
Recording ExpensesTotal SpendingPractice on your own: Online R compiler