Build a Sales Data Analyzer with Python
Load, clean, and visualize CSV sales data using pandas and matplotlib.
Introduction
30 Second Summary
Every business generates mountains of data, from daily sales to customer orders. The challenge is turning that raw data into insights that actually help people make decisions.
In this project, you will build a Python script that loads a messy sales dataset, cleans it up, calculates business metrics, and generates visual charts you can share with anyone.
What You'll Build
A command-line sales data analyzer that reads a CSV file, cleans data quality issues, computes revenue metrics, and saves visualizations as PNG image files.
By the end of this project, you'll have:
- A working Python script that loads, cleans, and analyzes a CSV sales dataset.
- Two data visualizations (a bar chart and a line chart) saved as PNG image files.
- Hands-on experience with the exact Python data stack used in ML engineering: NumPy, pandas, and matplotlib.
- Secret Mission: identify the top 3 customers by total spend and generate a customer leaderboard chart.
Are there any prerequisites?
None. This project includes full setup instructions for Python, VS Code, and all required libraries. You do not need any prior programming experience.
Before We Start
Before We Start...
Install Python and Set Up Your Environment
Before you can write any Python code, you need the right tools on your machine. Python is the programming language, and VS Code is the editor where you will write and run your scripts.
In this step, you will install Python, set up a code editor, and create an isolated project environment. This isolation keeps your project's libraries separate from everything else on your computer.
In this step, get ready to:
- Install Python 3.14 and verify it in Terminal.
- Set up VS Code and create a project folder.
- Create a virtual environment and install data science libraries.
Download and install Python 3.14
Python is the programming language you will use for the entire project. You need version 3.14 or higher because the data libraries we will install require it.
- Open Terminal by pressing Cmd+Space (macOS) or the Windows key (Windows) to open your search bar.
- Type Terminal and press Enter to open it.
- Check if Python is already installed by running this command:
python3 --version
Look at the output in your terminal and pick the tab below that matches what you see.
✔️ I see version 3.14 or higher
You see something like Python 3.14.5 printed in the terminal. Python is ready to go.
- Skip ahead to the next substep (Install VS Code).
ⓧ I see an older version
Your terminal shows a version number below 3.14 (for example, Python 3.9.6). macOS ships with an older Python by default, so you need to install the latest version alongside it.
- Open your browser and go to python.org/downloads.
- Click the big yellow Download Python 3.14.5 button.
- Open the downloaded python-3.14.5-macos11.pkg file.
- Follow the installer prompts, clicking Continue and Agree until the install completes.
- After the installer finishes, a Finder window opens showing /Applications/Python 3.14/. Double-click Install Certificates.command in that folder to install SSL certificates.
- Wait until you see Successfully installed certifi and update complete in the Terminal window that opens, then close it.
- Back in your original Terminal window, verify the new version by running:
python3 --version
You should now see Python 3.14.5 (or higher).
Still seeing the old version?
Close your Terminal completely and reopen it. The python.org installer updates your PATH, but the change only takes effect in a new Terminal session.
If it still shows an old version, try running python3.14 --version instead. If that works, use python3.14 in place of python3 for the rest of this project.
Help me troubleshoot my Python version
ⓧ Command not found
Your terminal shows an error because Python is not installed yet. You will download it from the official Python website.
- Open your browser and go to python.org/downloads.
- Click the big yellow Download Python 3.14.5 button.
- Open the downloaded python-3.14.5-macos11.pkg file.
- Follow the installer prompts, clicking Continue and Agree until the install completes.
- After the installer finishes, a Finder window opens showing /Applications/Python 3.14/. Double-click Install Certificates.command in that folder to install SSL certificates.
- Wait until you see Successfully installed certifi and update complete in the Terminal window that opens, then close it.
- Back in your original Terminal window, verify the installation by running:
python3 --version
You should see Python 3.14.5 printed.
Command still not found?
Close your Terminal completely and reopen it. The installer updates your PATH, but you need a fresh Terminal session for it to take effect.
Help me troubleshoot my Python installation
Install VS Code and create your project folder
VS Code is a free code editor where you will write your Python scripts. It highlights your syntax, catches typos, and has a built-in terminal.
- Press Cmd+Space (macOS) or the Windows key (Windows) to open your search bar.
- Type Visual Studio Code and press Enter.
✔️ VS Code opened
VS Code is already installed. Continue to the next instruction below.
ⓧ I don't have VS Code
- Open your browser and go to code.visualstudio.com/download.
- Click the Mac download button (Universal build works on all Macs).
- Open the downloaded .dmg file.
- Drag Visual Studio Code.app into your Applications folder.
- Open VS Code from your Applications folder by double-clicking the icon.
macOS blocking the app?
If you see a message saying the app cannot be opened because it is from an unidentified developer, right-click the VS Code icon, select Open, then click Open again in the dialog.
Help me open VS Code on macOS
Now you will create a dedicated folder for this project on your Desktop.
- In VS Code, open the integrated terminal by pressing Ctrl+` (backtick key, top-left of your keyboard).
- Move to your Desktop by running this command:
cd ~/Desktop
- Create your project folder and move into it by running these commands:
mkdir sales-analyzer
cd sales-analyzer
- Open this folder as a VS Code workspace by running:
code .
What does code . do?
The code . command tells VS Code to open the current directory as a project workspace. The dot (.) means "this folder."
- If VS Code prompts you with a dialog asking if you trust the authors of the files, click Yes, I trust the authors.
- Confirm the folder opened by checking the Explorer sidebar on the left. It should show SALES-ANALYZER as the workspace name.
code command not found?
On macOS, you need to install the code command manually. Open VS Code from your Applications folder, press Cmd+Shift+P to open the Command Palette, type Shell Command: Install 'code' command in PATH, and select it.
After that, close and reopen your Terminal, then run code . again.
Help me set up the code command on macOS
Create a virtual environment and install libraries
A virtual environment is an isolated space on your computer where Python libraries live. It keeps this project's packages separate from other projects and from your system Python.
- In the VS Code terminal (press Ctrl+` if it is not visible), create the virtual environment by running:
python3 -m venv venv
What does this command do?
python3 -m venv venv tells Python to run its built-in venv module and create a new virtual environment in a folder called venv.
The first venv is the module name. The second venv is the folder name you are creating. This is the standard naming convention.
- Activate the virtual environment by running:
source venv/bin/activate
You should see (venv) appear at the beginning of your terminal prompt. This confirms you are now working inside the virtual environment.
- Install the three data science libraries by running:
pip install numpy pandas matplotlib
What are these libraries?
- NumPy provides fast numerical arrays and math operations.
- pandas gives you DataFrames for loading, cleaning, and transforming tabular data.
- matplotlib creates charts and visualizations from your data.
These three libraries are the standard toolkit for data work in Python. ML engineers use them every day.
Wait for the installation to finish. You should see Successfully installed followed by the package names near the end of the output.
- Verify the libraries installed correctly by running:
python3 -c "import pandas; print(pandas.__version__)"
You should see a version number like 3.0.3 printed. This confirms pandas (and its dependency NumPy) installed successfully.
Seeing a ModuleNotFoundError?
Make sure you see (venv) in your terminal prompt. If you do not, run source venv/bin/activate again before running the import check.
If the activation worked but the import still fails, re-run pip install numpy pandas matplotlib and check for error messages during the install.
Help me fix my library installation
Your environment is ready. Next up, you will create a sample sales dataset and load it into Python to see your first DataFrame.
Create the Sales Dataset and Load It
Your environment is set up and ready to process data. Now it's time to create a realistic dataset and write the Python that reads it.
Every data analysis starts with raw data. In this step, you'll create a CSV file containing sales records with intentional quality issues (missing values, duplicates), then write your first Python function to load that data into a pandas DataFrame.
In this step, get ready to:
- Create a CSV file with sample sales data including intentional data quality issues.
- Write a Python script that loads the CSV into a DataFrame.
- Run the script and verify the data loads correctly.
Create the sample sales dataset
Real-world datasets are messy. To practice cleaning data later, you'll build a CSV that mimics common issues: a missing date, a missing price, and a duplicate row.
- In VS Code, hover over the SALES-ANALYZER heading in the Explorer sidebar (left panel).
- Click the New File icon (a page with a plus sign).
- Type sales_data.csv and press Enter.
- Paste the following data into the new file:
Order ID,Date,Product,Category,Quantity,Unit Price,Customer
1001,2024-01-15,Laptop,Electronics,2,999.99,Alice
1002,2024-01-20,Headphones,Electronics,5,79.99,Bob
1003,2024-02-01,Desk Chair,Furniture,1,299.99,Charlie
1004,2024-02-14,Laptop,Electronics,1,999.99,Alice
1005,2024-02-28,Monitor,Electronics,3,349.99,Diana
1006,2024-03-05,Desk Chair,Furniture,2,299.99,Bob
1007,2024-03-12,Keyboard,Electronics,10,49.99,Charlie
1008,2024-03-20,Laptop,Electronics,1,999.99,Diana
1009,2024-04-01,Headphones,Electronics,3,79.99,Alice
1010,2024-04-15,Monitor,Electronics,2,349.99,Bob
1011,2024-05-01,Desk Chair,Furniture,4,299.99,Charlie
1012,2024-05-10,Keyboard,Electronics,6,49.99,Diana
1013,,Laptop,Electronics,1,999.99,Alice
1014,2024-06-01,Headphones,Electronics,2,,Bob
1015,2024-06-15,Monitor,Electronics,1,349.99,Charlie
1015,2024-06-15,Monitor,Electronics,1,349.99,Charlie
What is in this dataset?
This CSV has 7 columns tracking product sales: Order ID, Date, Product, Category, Quantity, Unit Price, and Customer. There are 16 rows total.
Three intentional problems are baked in for you to clean later:
- Row 13 (Order ID 1013) has a missing Date.
- Row 14 (Order ID 1014) has a missing Unit Price.
- The last two rows are identical (Order ID 1015 is duplicated).
- Save sales_data.csv with Cmd+S (macOS) or Ctrl+S (Windows).
- Confirm the file appears in the Explorer sidebar under your sales-analyzer folder.
Don't see the file in the sidebar?
Make sure you typed the filename with the .csv extension. If the file ended up inside the venv folder by mistake, drag it up to the top level of sales-analyzer in the Explorer.
help me fix my file location in VS Code
Write the data loading script
Now you'll write your first Python script. It imports the three libraries you installed and defines a function that loads the CSV into a pandas DataFrame.
- Create another new file in the Explorer sidebar the same way you created the CSV.
- Name it analyze_sales.py.
- Paste the following code to import your libraries and define the load_data() function:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
def load_data(filepath):
"""Load CSV data into a pandas DataFrame."""
df = pd.read_csv(filepath)
print("=== Raw Data (first 5 rows) ===")
print(df.head())
print(f"\nShape: {df.shape[0]} rows, {df.shape[1]} columns")
return df
What does this code do?
The first three lines import pandas (for DataFrames), NumPy (for numerical operations), and matplotlib (for charts). The aliases pd, np, and plt are standard conventions you'll see in every data science project.
The load_data() function takes a file path, reads the CSV into a DataFrame using pd.read_csv(), prints the first 5 rows with df.head(), and reports the shape (rows and columns). It then returns the DataFrame so other functions can use it.
- Below the load_data() function, add the entry point that calls it:
def main():
"""Run the complete sales analysis pipeline."""
# Load
df = load_data("sales_data.csv")
if __name__ == "__main__":
main()
What is the if __name__ block?
The main() function is the entry point for your analysis pipeline. Right now it only calls load_data(), but you'll add more steps here later.
The if __name__ == "__main__" block ensures main() only runs when you execute the script directly. This is a standard Python pattern for organizing code into reusable functions.
- Save analyze_sales.py with Cmd+S (macOS) or Ctrl+S (Windows).
Seeing red squiggles under the imports?
This usually means VS Code is using the wrong Python interpreter. Make sure your virtual environment is active in the terminal (you should see (venv) at the start of the prompt). If the squiggles persist, click the Python version in the bottom-left status bar and select the interpreter inside your venv folder.
help me fix Python import errors in VS Code
✔️ Awesome, I've got everything!
Great. Double check you've saved your file before moving on.
ⓧ I'd like to double check the full code
Here is the complete analyze_sales.py so far:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
def load_data(filepath):
"""Load CSV data into a pandas DataFrame."""
df = pd.read_csv(filepath)
print("=== Raw Data (first 5 rows) ===")
print(df.head())
print(f"\nShape: {df.shape[0]} rows, {df.shape[1]} columns")
return df
def main():
"""Run the complete sales analysis pipeline."""
# Load
df = load_data("sales_data.csv")
if __name__ == "__main__":
main()
Run the script and verify the output
Time to see your data loading in action. Running the script will read the CSV and print the first 5 rows as a formatted table.
- In your terminal (with (venv) active), run the script by entering this command:
python3 analyze_sales.py
You should see a neatly formatted table showing the first 5 rows of your sales data, followed by the shape (16 rows, 7 columns).
What is a DataFrame?
A DataFrame is the core data structure in pandas. Think of it as a spreadsheet in code: it has rows and columns, each column can hold a different data type, and you can filter, sort, and aggregate it with simple function calls.
The df.head() method shows the first 5 rows so you can quickly verify the data loaded without flooding your terminal.
Seeing FileNotFoundError?
This means Python cannot find sales_data.csv. Make sure both files (analyze_sales.py and sales_data.csv) are in the same folder, and that your terminal is inside the sales-analyzer directory.
help me fix a FileNotFoundError in my Python script
Your data is loaded and you can see it structured as a table. Next, you'll inspect that data for quality issues and write a function to clean them up.
Clean the Data
Real-world data is messy. Missing values, duplicate entries, and inconsistent formats are problems every data professional deals with before any useful analysis can happen.
In this step, you'll build functions to inspect your sales data for quality issues and then clean them up. This is the exact workflow ML engineers follow: understand the mess first, then fix it systematically.
In this step, get ready to:
- Add data inspection code that reveals data types, missing values, and duplicates.
- Write a clean_data() function that fixes all three quality issues.
- Run the cleaning pipeline and verify the issues are resolved.
Inspect the data for quality issues
Before fixing data problems, you need to see them. A quick inspection reveals the data types of each column, how many values are missing, and whether any rows are duplicated.
- In analyze_sales.py, add the inspect_data() function below the load_data() function by copying the following code:
def inspect_data(df):
"""Print data quality information."""
print("\n=== Data Inspection ===")
print("\nData types:")
print(df.dtypes)
print("\nMissing values:")
print(df.isnull().sum())
print(f"\nDuplicate rows: {df.duplicated().sum()}")
What does this code do?
- df.dtypes shows the data type of each column (integer, float, string). This tells you whether pandas interpreted the data correctly.
- df.isnull().sum() counts how many values are missing in each column. A missing value is a blank cell in the CSV.
- df.duplicated().sum() counts rows that are exact copies of another row. Duplicates distort any calculations you run on the data.
Now you need to call this function from main() so it actually runs when you execute the script.
- Scroll down to your main() function.
- Find this line:
df = load_data("sales_data.csv")
- Add this line directly below it:
inspect_data(df)
- Save analyze_sales.py.
- Run the script in your terminal by running this command:
python3 analyze_sales.py
You should see a new === Data Inspection === section in the output. Look for the missing values count showing 1 for Date and 1 for Unit Price, and the duplicate rows count showing 1.
Not seeing the inspection output?
- Make sure inspect_data(df) is indented inside the main() function, not outside it.
- Check that the inspect_data function definition is placed between load_data and main in the file. Python reads top to bottom, so functions must be defined before they are called.
- Confirm your virtual environment is still active. You should see (venv) at the start of your terminal prompt.
Help me debug my inspect_data function
Write a function to clean the data
Your inspection revealed three problems: one duplicate row, one missing date, and one missing unit price. The clean_data() function will handle each of these systematically.
- In analyze_sales.py, add the clean_data() function below inspect_data() by copying the following code:
def clean_data(df):
"""Clean the DataFrame: remove duplicates, handle missing values, fix types."""
# Remove duplicate rows
df = df.drop_duplicates()
# Drop rows where Date is missing (can't analyze without a date)
df = df.dropna(subset=["Date"])
# Fill missing numeric values with column median
df["Unit Price"] = df["Unit Price"].fillna(df["Unit Price"].median())
# Convert Date to datetime
df["Date"] = pd.to_datetime(df["Date"])
# Reset index after cleaning
df = df.reset_index(drop=True)
print("\n=== After Cleaning ===")
print(f"Shape: {df.shape[0]} rows, {df.shape[1]} columns")
print(f"Missing values: {df.isnull().sum().sum()}")
return df
What does this code do?
- drop_duplicates() removes rows that are exact copies of another row. Your CSV has one duplicate entry for Order 1015.
- dropna(subset=["Date"]) removes rows where the Date column is empty. Without a date, you cannot place a sale in time.
- fillna(df["Unit Price"].median()) fills blank prices with the middle value of all existing prices. This is safer than using the average, which can be skewed by outliers.
- pd.to_datetime() converts date strings into proper datetime objects. This lets pandas do time-based grouping later.
- reset_index(drop=True) renumbers the rows from 0 so there are no gaps after removing rows.
What is a function in Python?
A function is a named block of code that takes an input (a parameter like df), does something with it, and returns an output. You define one with def and send back the result with return.
Functions let you organize code into reusable pieces. Instead of writing the same cleaning logic every time, you call clean_data(df) and get a cleaned DataFrame back.
Seeing an indentation error?
- Make sure every line inside the function is indented with exactly 4 spaces. Mixing tabs and spaces causes Python errors.
- Check that there is a blank line between the end of inspect_data() and the start of clean_data(). Python uses blank lines to separate function definitions.
Help me fix my indentation error
Run the cleaning pipeline and verify
With both functions written, you need to wire them into main() and run the full pipeline to confirm the data is cleaned properly.
- In your main() function, find this line:
inspect_data(df)
- Add this line directly below it:
df = clean_data(df)
Why df = clean_data(df)?
The clean_data() function returns a new, cleaned DataFrame. By writing df = clean_data(df), you replace the old messy data with the cleaned version. All code that runs after this point works with clean data.
- Save analyze_sales.py.
- Run the script again by running this command:
python3 analyze_sales.py
You should see a new === After Cleaning === section at the bottom of the output showing Shape: 13 rows, 7 columns and Missing values: 0. The original 16 rows have been reduced to 13 because you removed 1 duplicate, 1 row with a missing date, and 1 row that was both duplicate and missing data.
Seeing a different row count?
- If you see more than 13 rows, check that drop_duplicates() and dropna(subset=["Date"]) are both present in your clean_data() function.
- Verify that each cleaning step reassigns the result back to df. Writing df.drop_duplicates() without df = in front does nothing.
- Make sure your sales_data.csv has exactly 16 rows (including the header). If you accidentally edited the CSV, re-copy it from the previous step.
Help me debug my clean_data function
✔️ Awesome, I've got everything!
Great. Double check you've saved your file before moving on.
ⓧ I'd like to double check the full code
Here is the full analyze_sales.py file as it should look at the end of this step:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
def load_data(filepath):
"""Load CSV data into a pandas DataFrame."""
df = pd.read_csv(filepath)
print("=== Raw Data (first 5 rows) ===")
print(df.head())
print(f"\nShape: {df.shape[0]} rows, {df.shape[1]} columns")
return df
def inspect_data(df):
"""Print data quality information."""
print("\n=== Data Inspection ===")
print("\nData types:")
print(df.dtypes)
print("\nMissing values:")
print(df.isnull().sum())
print(f"\nDuplicate rows: {df.duplicated().sum()}")
def clean_data(df):
"""Clean the DataFrame: remove duplicates, handle missing values, fix types."""
df = df.drop_duplicates()
df = df.dropna(subset=["Date"])
df["Unit Price"] = df["Unit Price"].fillna(df["Unit Price"].median())
df["Date"] = pd.to_datetime(df["Date"])
df = df.reset_index(drop=True)
print("\n=== After Cleaning ===")
print(f"Shape: {df.shape[0]} rows, {df.shape[1]} columns")
print(f"Missing values: {df.isnull().sum().sum()}")
return df
def main():
"""Run the complete sales analysis pipeline."""
df = load_data("sales_data.csv")
inspect_data(df)
df = clean_data(df)
if __name__ == "__main__":
main()
Your data is now clean and ready for analysis. Next up, you'll calculate revenue metrics and generate visualizations that turn raw numbers into charts you can actually read.
Analyze Revenue and Generate Visualizations
Your data is clean and structured. Now it's time to extract business insights from it.
In this step, you'll calculate revenue metrics using pandas aggregation methods and turn numbers into visual charts with matplotlib. This is the core of every data analysis pipeline: transforming raw rows into answers that someone can act on.
In this step, get ready to:
- Calculate revenue per product using groupby aggregation.
- Generate a horizontal bar chart of product revenue.
- Plot a monthly revenue trend line and save both charts as PNG files.
Create a revenue column and calculate metrics
The CSV has Quantity and Unit Price as separate columns, but you need total revenue per order to answer business questions. You'll create a computed column and then use groupby() to aggregate revenue by product.
- In analyze_sales.py, find the clean_data() function. Add the following analyze_revenue() function directly below it:
def analyze_revenue(df):
"""Calculate revenue and print summary metrics."""
# Create Revenue column
df["Revenue"] = df["Quantity"] * df["Unit Price"]
# Revenue by product
revenue_by_product = (
df.groupby("Product")["Revenue"]
.sum()
.sort_values(ascending=False)
)
print("\n=== Revenue by Product ===")
print(revenue_by_product)
# Summary stats
total_revenue = df["Revenue"].sum()
total_orders = len(df)
top_product = revenue_by_product.index[0]
print(f"\n=== Summary ===")
print(f"Total Revenue: ${total_revenue:,.2f}")
print(f"Total Orders: {total_orders}")
print(f"Top Product: {top_product}")
return df
What does this code do?
df["Revenue"] = df["Quantity"] * df["Unit Price"] creates a new column by multiplying two existing columns together. Pandas handles the row-by-row math automatically.
df.groupby("Product")["Revenue"].sum() groups all rows by product name, then sums their revenue. This is the pandas equivalent of a SQL GROUP BY clause.
The function returns df so the Revenue column is available to later functions that need it for charting.
- In the main() function, find this line:
df = clean_data(df)
- Add this line directly below it:
df = analyze_revenue(df)
- Save analyze_sales.py.
- Run the script to verify revenue calculations by running:
python3 analyze_sales.py
- You should see a "Revenue by Product" table with Laptop at the top, followed by a Summary section showing Total Revenue, Total Orders, and Top Product.
Seeing a KeyError or unexpected output?
- Make sure the column names in your code match the CSV headers exactly, including capitalization. "Revenue", "Quantity", and "Unit Price" all need capital letters.
- Check that analyze_revenue(df) is called AFTER clean_data(df) in main(). The cleaning step fills missing values that the revenue calculation depends on.
- help me debug my analyze_revenue function
Create a revenue bar chart
Numbers in a terminal are useful, but a chart makes the comparison between products instantly obvious. You'll use matplotlib to create a horizontal bar chart and save it as a PNG file.
- In analyze_sales.py, add the following function below analyze_revenue():
def plot_revenue_by_product(df):
"""Create a horizontal bar chart of revenue by product."""
revenue_by_product = (
df.groupby("Product")["Revenue"]
.sum()
.sort_values(ascending=True)
)
plt.figure(figsize=(10, 6))
plt.barh(revenue_by_product.index, revenue_by_product.values, color="steelblue")
plt.xlabel("Revenue ($)")
plt.title("Total Revenue by Product")
plt.tight_layout()
plt.savefig("revenue_by_product.png", dpi=150)
plt.close()
print("\nSaved: revenue_by_product.png")
What does this code do?
plt.figure(figsize=(10, 6)) creates a blank canvas 10 inches wide and 6 inches tall. plt.barh() draws horizontal bars where each bar's length represents that product's total revenue.
plt.savefig("revenue_by_product.png", dpi=150) writes the chart to a PNG file at 150 dots per inch. plt.close() frees the memory used by the figure so it doesn't accumulate if you generate multiple charts.
Notice the sort uses ascending=True here (opposite to the terminal output). This puts the highest-revenue product at the top of the horizontal bar chart, which reads more naturally.
- In main(), find this line:
df = analyze_revenue(df)
- Add this line directly below it:
plot_revenue_by_product(df)
- Save analyze_sales.py and run the script again:
python3 analyze_sales.py
- You should see "Saved: revenue_by_product.png" in the terminal output.
- Confirm the file exists by running:
ls *.png
- You should see revenue_by_product.png in the output. Open it from Finder or VS Code's Explorer sidebar to see your bar chart.
Don't see the PNG file?
- Make sure you added plot_revenue_by_product(df) to main(). Defining the function alone does not run it.
- Check that plot_revenue_by_product(df) comes AFTER df = analyze_revenue(df) in main(). The Revenue column must exist before you can chart it.
- help me figure out why my chart didn't save
Create a monthly trend line chart
A bar chart shows totals, but it hides when the revenue came in. A line chart over time reveals whether sales are growing, shrinking, or seasonal. You'll resample the data by month to create this view.
- In analyze_sales.py, add the following function below plot_revenue_by_product():
def plot_monthly_trend(df):
"""Create a line chart of monthly revenue."""
monthly_revenue = (
df.set_index("Date")
.resample("ME")["Revenue"]
.sum()
)
plt.figure(figsize=(10, 6))
plt.plot(monthly_revenue.index, monthly_revenue.values, marker="o", color="steelblue")
plt.xlabel("Month")
plt.ylabel("Revenue ($)")
plt.title("Monthly Revenue Trend")
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig("monthly_trend.png", dpi=150)
plt.close()
print("Saved: monthly_trend.png")
What does this code do?
df.set_index("Date").resample("ME")["Revenue"].sum() sets the Date column as the index, then groups all orders into calendar months. "ME" stands for "month-end" frequency in pandas.
marker="o" adds a dot at each data point so individual months are visible. plt.grid(True, alpha=0.3) adds faint gridlines to make values easier to read.
- Now update main() to call the new function and print a completion message. Find this line:
plot_revenue_by_product(df)
- Add these two lines directly below it:
plot_monthly_trend(df)
print("\nAnalysis complete!")
- Save analyze_sales.py and run the full pipeline:
python3 analyze_sales.py
- You should see the full output: raw data, inspection, cleaning, revenue by product, the summary, and two "Saved:" confirmation messages ending with "Analysis complete!".
- Confirm both chart files exist by running:
ls *.png
- You should see revenue_by_product.png and monthly_trend.png listed. Open monthly_trend.png to see your line chart with monthly data points connected.
Script errors out or monthly_trend.png is missing?
- If you see an error about "Revenue" not being found in plot_monthly_trend(), make sure analyze_revenue(df) is called before both plot functions in main(). That function creates the Revenue column the charts depend on.
- Check that you used "ME" (uppercase M and E) in the resample() call. This is the month-end frequency alias in pandas.
- help me debug my monthly trend chart
✔️ Awesome, I've got everything!
Great. Double check you've saved your file, and that both PNG charts are visible in your sales-analyzer folder.
ⓧ I'd like to double check the full code
Here is the complete analyze_sales.py at the end of this step. Compare your file against it:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
def load_data(filepath):
"""Load CSV data into a pandas DataFrame."""
df = pd.read_csv(filepath)
print("=== Raw Data (first 5 rows) ===")
print(df.head())
print(f"\nShape: {df.shape[0]} rows, {df.shape[1]} columns")
return df
def inspect_data(df):
"""Print data quality information."""
print("\n=== Data Inspection ===")
print("\nData types:")
print(df.dtypes)
print("\nMissing values:")
print(df.isnull().sum())
print(f"\nDuplicate rows: {df.duplicated().sum()}")
def clean_data(df):
"""Clean the DataFrame: remove duplicates, handle missing values, fix types."""
df = df.drop_duplicates()
df = df.dropna(subset=["Date"])
df["Unit Price"] = df["Unit Price"].fillna(df["Unit Price"].median())
df["Date"] = pd.to_datetime(df["Date"])
df = df.reset_index(drop=True)
print("\n=== After Cleaning ===")
print(f"Shape: {df.shape[0]} rows, {df.shape[1]} columns")
print(f"Missing values: {df.isnull().sum().sum()}")
return df
def analyze_revenue(df):
"""Calculate revenue and print summary metrics."""
df["Revenue"] = df["Quantity"] * df["Unit Price"]
revenue_by_product = (
df.groupby("Product")["Revenue"]
.sum()
.sort_values(ascending=False)
)
print("\n=== Revenue by Product ===")
print(revenue_by_product)
total_revenue = df["Revenue"].sum()
total_orders = len(df)
top_product = revenue_by_product.index[0]
print(f"\n=== Summary ===")
print(f"Total Revenue: ${total_revenue:,.2f}")
print(f"Total Orders: {total_orders}")
print(f"Top Product: {top_product}")
return df
def plot_revenue_by_product(df):
"""Create a horizontal bar chart of revenue by product."""
revenue_by_product = (
df.groupby("Product")["Revenue"]
.sum()
.sort_values(ascending=True)
)
plt.figure(figsize=(10, 6))
plt.barh(revenue_by_product.index, revenue_by_product.values, color="steelblue")
plt.xlabel("Revenue ($)")
plt.title("Total Revenue by Product")
plt.tight_layout()
plt.savefig("revenue_by_product.png", dpi=150)
plt.close()
print("\nSaved: revenue_by_product.png")
def plot_monthly_trend(df):
"""Create a line chart of monthly revenue."""
monthly_revenue = (
df.set_index("Date")
.resample("ME")["Revenue"]
.sum()
)
plt.figure(figsize=(10, 6))
plt.plot(monthly_revenue.index, monthly_revenue.values, marker="o", color="steelblue")
plt.xlabel("Month")
plt.ylabel("Revenue ($)")
plt.title("Monthly Revenue Trend")
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig("monthly_trend.png", dpi=150)
plt.close()
print("Saved: monthly_trend.png")
def main():
"""Run the complete sales analysis pipeline."""
df = load_data("sales_data.csv")
inspect_data(df)
df = clean_data(df)
df = analyze_revenue(df)
plot_revenue_by_product(df)
plot_monthly_trend(df)
print("\nAnalysis complete!")
if __name__ == "__main__":
main()
Secret mission
Add a Customer Analysis Feature
Who are your best customers? Add a customer analysis feature that identifies the top spenders, generates a leaderboard chart, and prints a formatted ranking to the terminal.
Clean Up Your Resources
Clean Up Your Resources
Decide whether to keep your resources running, pause them to come back later, or delete them entirely. This project runs entirely locally, so there are no ongoing costs.
Resources you used:
- The sales-analyzer project folder on your Desktop (contains analyze_sales.py, sales_data.csv, generated PNG charts, and the venv virtual environment).
- Python 3.14 installed via the python.org macOS installer.
- VS Code installed as a macOS application.
Keep everything running
No action needed. Choose this if you're still actively building or want to experiment further with the sales analyzer.
- Your sales-analyzer folder stays on your Desktop with all scripts, data, and charts intact.
- Python 3.14 and VS Code remain installed and ready for your next project.
- Your virtual environment stays inside the project folder for whenever you return.
Pause - I'll come back to this later
Shut down the virtual environment to free up your terminal session. Your files stay safe on disk.
- Deactivate the virtual environment by running this in your terminal:
deactivate
- Close VS Code if you want to free up memory.
- When you come back, open the sales-analyzer folder in VS Code and reactivate with source venv/bin/activate.
Delete - I don't want to use this again
Remove all project resources and installed tools. This is irreversible.
- Deactivate the virtual environment first:
deactivate
- Delete the entire project folder by running:
rm -rf ~/Desktop/sales-analyzer
- Confirm the folder is gone by running:
ls ~/Desktop/sales-analyzer
You should see a "No such file or directory" message.
- To remove Python 3.14, delete the framework and application directories:
sudo rm -rf /Library/Frameworks/Python.framework/Versions/3.14
rm -rf "/Applications/Python 3.14/"
- To remove VS Code, move it to the Trash:
rm -rf /Applications/Visual\ Studio\ Code.app
All project resources are now removed from your machine.
Nice Work!
Nice Work!
You just built your first data analysis pipeline in Python. From raw CSV data to cleaned DataFrames to publication-quality charts, you practiced the exact workflow ML engineers use every day.
You've learned how to:
- Build a complete data analysis script from scratch using Python fundamentals: variables, functions, loops, and data structures.
- Load, clean, and transform messy real-world data using pandas (handling duplicates, missing values, and type conversions).
- Generate bar charts and line charts with matplotlib and save them as PNG image files.
- Built a customer analytics feature with parameterized functions and edge case handling (Secret Mission).
Ready to quiz yourself?