Analyze Superstore Sales with Python
Load, clean, and visualize retail sales data to find profit insights.
Introduction
30 Second Summary
Every business generates mountains of sales data. The real skill is knowing how to turn those numbers into answers that drive decisions.
In this project, you will analyze a real retail dataset of nearly 10,000 orders using Python. You'll clean the data, uncover which products and regions are profitable, and create visualizations that tell the story.
What You'll Build
When you're done, you'll have a complete analysis notebook that answers the question "Where are we making money, and where are we losing it?" with data-backed charts you could present to a stakeholder.
By the end of this project, you'll have:
- A regional sales breakdown showing at a glance which of four US regions generates the most revenue and profit.
- A sub-category profit analysis that identifies which products are actively losing money for the store.
- A monthly sales trend chart revealing seasonal patterns and spikes across four years of transactions.
- Secret Mission: Investigate whether the store's discount strategy is destroying its profits.
Are there any prerequisites?
None. All you need is a Google account. This project uses Google Colab, a free browser-based coding environment with pandas and matplotlib pre-installed. No downloads or installations required.
Before We Start
Before we dive in, let's lock in what you're about to build and why it matters.
Taking a moment to articulate your goal now means every step that follows has a clear purpose.
Set Up Google Colab and Load the Dataset
You are about to analyze a real retail dataset to find where a superstore makes money and where it bleeds cash. Before any analysis can happen, you need two things: somewhere to write and run Python code, and the data itself.
Google Colab is a free, browser-based notebook that comes with pandas and matplotlib pre-installed. In this step, you will open Colab, upload the Superstore dataset, and load it into Python so you can start exploring.
In this step, get ready to:
- Open Google Colab and create a new notebook.
- Download and upload the Superstore dataset.
- Load the data into a pandas DataFrame and confirm it worked.
Open Google Colab and create a notebook
Google Colab is a hosted Jupyter Notebook service that requires no setup to use. It gives you free access to computing resources with Python and data science libraries already installed.
- Open a new browser tab and navigate to colab.research.google.com.
- Sign in with your Google account if prompted.
- Click New notebook in the bottom right of the dialog that appears.
- Click the notebook title at the top left (it defaults to something like Untitled0.ipynb).
- Rename it to Superstore Sales Analysis and press Enter.
You should see your notebook title update to Superstore Sales Analysis at the top of the page with an empty code cell ready for input.
What is Google Colab?
Google Colab is a free cloud notebook that runs Python in your browser. You do not need to install Python, pandas, or matplotlib on your computer. Everything runs on Google's servers.
Download and upload the dataset
The Superstore dataset contains about 9,994 retail transactions from a fictional US store. You will download it from a free hosting site and upload it into your Colab session.
- Open a new browser tab and go to https://csvbase.com/djkoogy/Sample-Superstore.
- Click Download as near the top of the page.
- Select .csv (2.5 MB) from the dropdown to save the file to your computer.
- Find the downloaded file on your computer and rename it to Sample - Superstore.csv (with spaces around the dash).
- Switch back to your Colab tab.
- Click the folder icon in the left sidebar to open the Files panel.
- Click the upload button (the file icon with an upward arrow) at the top of the Files panel.
- Select your renamed Sample - Superstore.csv file and upload it.
Once the upload finishes, you should see Sample - Superstore.csv listed in the Files panel on the left.
Why rename the file?
The download from csvbase saves as Sample-Superstore.csv (no spaces). The code you will write references Sample - Superstore.csv (with spaces), matching the original Kaggle dataset name. Renaming now prevents a FileNotFoundError later.
Colab session storage is temporary
Uploaded files disappear when your Colab session disconnects (after ~90 minutes of inactivity). If that happens, just re-upload the file.
Load the data into pandas
With the file uploaded, you can now write Python code to load it into a DataFrame and confirm everything is working.
- Click the empty code cell in your notebook and type the following code:
# Import the libraries you'll use throughout this project
import pandas as pd
import matplotlib.pyplot as plt
# Load the CSV file into a DataFrame
df = pd.read_csv('Sample - Superstore.csv', encoding='latin-1')
print(f"Dataset shape: {df.shape}")
df.head()
What does this code do?
- import pandas as pd loads the pandas library for working with tabular data.
- import matplotlib.pyplot as plt loads the plotting library you will use for charts later.
- pd.read_csv(...) reads the CSV file into a DataFrame (a table of rows and columns in memory).
- encoding='latin-1' tells pandas how to decode special characters in the file that would fail with the default encoding.
- df.head() displays the first 5 rows so you can quickly verify the data loaded correctly.
Before you run this, what do you expect to see? Think about what df.shape might print given a dataset with about 10,000 rows.
- Run the cell by pressing Shift+Enter on your keyboard.
You should see two things printed below the cell: Dataset shape: (9994, 21) and a table showing the first 5 rows with columns like Order ID, Ship Mode, Customer Name, Sales, and Profit.
Seeing a FileNotFoundError?
- Make sure the filename in your code exactly matches what you see in the Files panel (including spaces and capitalization).
- If your Files panel shows Sample-Superstore.csv (no spaces), either rename it on your computer and re-upload, or update the filename in your code to match.
- If the Files panel is empty, your session may have disconnected. Re-upload the CSV file using the upload button.
Still stuck? Help me fix my FileNotFoundError in Google Colab.
✔️ Awesome, I've got everything!
Great. Double check you have saved your notebook (Colab auto-saves, but you can press Ctrl+S or Cmd+S to be sure).
ⓧ I'd like to double check the full code
Here is everything your notebook should contain so far:
# Cell 1: Import libraries
import pandas as pd
import matplotlib.pyplot as plt
# Cell 2: Load the dataset
df = pd.read_csv('Sample - Superstore.csv', encoding='latin-1')
print(f"Dataset shape: {df.shape}")
df.head()
Your data is loaded and you have confirmed 9,994 rows across 21 columns. Next up, you will explore this dataset to understand its structure and spot issues that need fixing before analysis.
Explore Your Data
Your data is loaded and you can see 9,994 rows across 21 columns. But what exactly is in those columns, and is the data ready for analysis?
Before cleaning or analyzing anything, you need to understand what you are working with. This first look reveals the dataset's structure and immediately shows you what needs fixing before you can ask business questions.
In this step, get ready to:
- Inspect your DataFrame's structure, data types, and summary statistics.
- Check for duplicate rows and missing values.
- Attempt a time-based analysis and discover why it fails.
Inspect the structure
You already know the dataset has 9,994 rows and 21 columns from Step 1. Now you need to dig deeper into what type of data each column holds.
- Create a new code cell in your Colab notebook by clicking the + Code button at the top.
- Run df.info() to see every column's data type by pasting this code:
# Cell 3: Explore the structure
df.info()
What does this output tell you?
df.info() prints each column's name, how many non-null values it has, and its data type.
Look at the Order Date and Ship Date columns. They show object as their type, meaning pandas loaded them as plain text strings instead of proper dates.
You should see a table listing all 21 columns. Notice that most numeric columns show float64 or int64, but Order Date and Ship Date both show object.
- Create another new code cell and run df.describe() to see summary statistics for numeric columns:
# Cell 4: Summary statistics
df.describe()
What does df.describe() show?
This prints the count, mean, min, max, and percentiles for every numeric column. You can immediately see that Sales ranges from about $0.44 to over $22,000, and Discount goes from 0 to 0.8 (80%).
Most importantly, the Profit column has a negative minimum value. Some orders are actively losing money.
You should see a statistics table with rows for count, mean, std, min, 25%, 50%, 75%, and max.
Not seeing any output?
Make sure you clicked the play button (or pressed Shift+Enter) to run each cell. In Google Colab, code cells only execute when you explicitly run them.
help me debug why my Colab cell isn't producing output
Check for data quality issues
Two common problems can silently corrupt analysis results: duplicate rows that inflate counts, and missing values that cause calculations to fail.
- Create a new code cell and check for both issues by running:
# Cell 5: Check data quality
print(f"Duplicate rows: {df.duplicated().sum()}")
print(f"\nMissing values per column:")
print(df.isna().sum())
What does this code do?
- df.duplicated().sum() counts how many rows are exact copies of another row.
- df.isna().sum() counts missing values in every column.
A dataset with no duplicates and no missing values means less cleaning work for you.
You should see Duplicate rows: 0 and all zeros in the missing values list. This dataset is unusually clean.
The only issue you have found so far is the date columns stored as text. But does that actually matter?
Attempt monthly analysis to see the problem
A key question for any retail business is: which months have the highest sales? To answer that, you need to extract the month from each order's date.
- Create a new code cell.
- Type this code (do not run it yet):
# Cell 6: Attempt monthly analysis (this will fail!)
df['Order Date'].dt.month
Before you run this, what do you think will happen? The .dt accessor is how pandas extracts parts of a date (month, year, day). Will it work on the Order Date column?
- Press Shift+Enter to run the cell now.
You get an error: AttributeError: Can only use .dt accessor with datetimelike values.
Why did this fail?
Remember that df.info() showed Order Date as object type. pandas treats it as a plain text string like "1/3/2016", not as an actual date.
The .dt accessor only works on columns that pandas recognizes as datetime objects. You need to explicitly convert those text strings into proper dates before any time-based analysis will work.
- Comment out the failing line so your notebook runs cleanly. Update the cell to look like this:
# Cell 6: Attempt monthly analysis (this will fail!)
# df['Order Date'].dt.month # Uncomment to see the error
Keep failed experiments as comments
Commenting out code that broke (instead of deleting it) documents your thought process. It shows you tried something, learned why it failed, and moved on.
✔️ Awesome, I've got everything!
Great. Make sure all six cells are saved in your notebook.
ⓧ I'd like to double check the full code
Here is what your complete notebook should look like so far. Each comment starting with # Cell marks the beginning of a separate Colab cell.
# Cell 1: Import libraries
import pandas as pd
import matplotlib.pyplot as plt
# Cell 2: Load the dataset
df = pd.read_csv('Sample - Superstore.csv', encoding='latin-1')
print(f"Dataset shape: {df.shape}")
df.head()
# Cell 3: Explore the structure
df.info()
# Cell 4: Summary statistics
df.describe()
# Cell 5: Check data quality
print(f"Duplicate rows: {df.duplicated().sum()}")
print(f"\nMissing values per column:")
print(df.isna().sum())
# Cell 6: Attempt monthly analysis (this will fail!)
# df['Order Date'].dt.month # Uncomment to see the error
You now know exactly what is wrong with this dataset: the dates are trapped as text. In the next step, you will fix this by converting them to proper datetime objects, unlocking time-based analysis.
Clean Your Data
In the previous step, you discovered that the Order Date column is stored as plain text. When you tried to extract the month, pandas threw an error because it cannot perform date operations on strings.
This step fixes that problem by converting the date columns into proper datetime objects. Once the conversion is done, you can ask questions like "what month had the highest sales?" without hitting errors.
In this step, get ready to:
- Convert date columns from text strings to proper datetime objects.
- Create helper columns for year and month to enable trend analysis.
Convert date columns to datetime
The pd.to_datetime() function takes a column of text strings and converts them into datetime objects that pandas can do math on. After conversion, the .dt accessor unlocks operations like extracting the month, year, or day of the week.
- Create a new code cell in your notebook and add the following code to convert both date columns and verify the fix:
# Cell 7: Clean - convert dates to datetime
df['Order Date'] = pd.to_datetime(df['Order Date'])
df['Ship Date'] = pd.to_datetime(df['Ship Date'])
# Verify the fix works
print(f"Order Date type: {df['Order Date'].dtype}")
print(f"\nSample months: {df['Order Date'].dt.month.head().tolist()}")
What does this code do?
pd.to_datetime() parses the text strings in each date column and converts them into datetime64 objects. This is the fix for the AttributeError: Can only use .dt accessor with datetimelike values error you hit in the previous step.
The print statements confirm the conversion worked by showing the new data type and extracting sample month numbers using the same .dt.month accessor that previously failed.
- Run the cell by pressing Shift+Enter.
- You should see Order Date type: datetime64[ns] followed by a list of integers like [1, 1, 6, 2, 2] representing months.
Seeing a NameError or KeyError?
- Make sure you ran all previous cells (Cells 1 through 6) before running Cell 7. Colab cells must run in order because each one depends on the variables created above it.
- If you see KeyError: 'Order Date', check that your CSV file is still uploaded in the left sidebar. Colab deletes uploaded files when the runtime disconnects.
Why is my date conversion not working?
Create time-based helper columns
With the dates properly converted, you can now extract individual components like the year and month into their own columns. These helper columns make it easy to group sales data by time period in the next step.
- Create a new code cell and add the following code to extract year and month columns:
# Cell 8: Create helper columns
df['Order Year'] = df['Order Date'].dt.year
df['Order Month'] = df['Order Date'].dt.month
What does this code do?
The .dt.year accessor pulls the four-digit year (like 2014, 2015) from each date. The .dt.month accessor pulls the month number (1 for January through 12 for December).
Storing these in dedicated columns means you can group sales by year or month without repeating the extraction logic every time.
- Run the cell by pressing Shift+Enter.
Before you check the result, what do you expect df.info() to show now compared to the last time you ran it?
- Verify your cleaning worked by scrolling up to your Cell 3 (df.info()) and running it again.
- Confirm that Order Date now shows datetime64[ns] instead of object.
- Confirm that two new columns appear at the bottom: Order Year and Order Month.
Don't see the new columns?
- Make sure you ran Cell 8 before re-running Cell 3. The columns only exist after Cell 8 executes.
- If Order Date still shows object, Cell 7 may not have run successfully. Re-run Cell 7, then Cell 8, then Cell 3 again.
Help me verify that my data cleaning worked correctly.
✔️ Awesome, I've got everything!
Great. Double check you have Cell 7 and Cell 8 in your notebook, and that running df.info() shows datetime64[ns] for both date columns.
ⓧ I'd like to double check the full code
Scroll through your notebook and confirm these cells are present in order:
- Cell 1: imports (pandas and matplotlib).
- Cell 2: load dataset with pd.read_csv().
- Cell 3: df.info().
- Cell 4: df.describe().
- Cell 5: duplicate and missing value checks.
- Cell 6: the commented-out .dt.month attempt.
- Cell 7: pd.to_datetime() conversion with verification prints.
- Cell 8: Order Year and Order Month helper columns.
Your data is clean and ready for analysis. Next up, you will group the data by region and product category to find out where the store makes money and where it loses it.
Analyze Sales Performance
Your data is clean and ready to answer real business questions. Now you can ask: which region brings in the most revenue? Which product categories are profitable, and which are quietly losing money?
Groupby aggregations in pandas let you split your data by a category (like Region or Sub-Category), then calculate totals for each group. The answers might surprise you.
In this step, get ready to:
- Group sales data by Region to find the top-performing area.
- Break down profit by Category and Sub-Category to find money-losing products.
- Aggregate monthly sales to reveal seasonal patterns across 2014-2017.
Group sales data by Region
The Superstore dataset covers four US regions: West, East, Central, and South. Your first question is straightforward: which region generates the most revenue and profit?
- Create a new code cell in your notebook and enter this code to group sales and profit by Region:
# Cell 9: Sales and Profit by Region
region_summary = df.groupby('Region')[['Sales', 'Profit']].sum().sort_values('Sales', ascending=False)
print("Sales and Profit by Region:")
print(region_summary)
What does this code do?
- `df.groupby('Region')` splits the 9,994 rows into four groups (one per region).
- `[['Sales', 'Profit']].sum()` calculates the total Sales and total Profit for each region.
- `sort_values('Sales', ascending=False)` puts the highest-revenue region at the top.
- Run the cell by pressing Shift+Enter.
- You should see a table with four rows showing Sales and Profit columns, with the West region at the top.
Seeing a NameError?
- Make sure you ran all your earlier cells first (Cells 1 through 8). Colab does not remember variables from a previous session unless you re-run the cells.
- Check that df is spelled exactly as shown.
Why is my groupby cell throwing a NameError?
Break down profit by Category and Sub-Category
Regions tell you where sales come from, but categories tell you what sells. The store has three product categories: Furniture, Office Supplies, and Technology.
- Create a new code cell and enter this code to see profit by Category:
# Cell 10: Profit by Category
category_profit = df.groupby('Category')['Profit'].sum().sort_values(ascending=False)
print("\nProfit by Category:")
print(category_profit)
What does this code do?
- `df.groupby('Category')['Profit'].sum()` sums up total profit for each of the three product categories.
- `sort_values(ascending=False)` puts the most profitable category at the top.
- Run the cell.
- You should see three rows showing Technology, Office Supplies, and Furniture in order of total profit.
Getting unexpected results?
- Make sure you typed 'Profit' with a capital P. Column names are case-sensitive.
- Confirm that 'Category' has a capital C.
Why doesn't my groupby find the column?
Categories are broad. To find the real money-losers, you need to dig into the 17 sub-categories.
Before you run the next cell, think about this: do you expect every sub-category to be profitable?
- Create a new code cell and enter this code to rank sub-categories by profit:
# Cell 11: Profit by Sub-Category (find the losers)
subcat_profit = df.groupby('Sub-Category')['Profit'].sum().sort_values()
print("\nBottom 5 Sub-Categories by Profit:")
print(subcat_profit.head(5))
print("\nTop 5 Sub-Categories by Profit:")
print(subcat_profit.tail(5))
- Run the cell.
You should see negative profit values for Tables and Bookcases at the top of the bottom 5 list. These sub-categories are actively losing money for the store.
What does this code do?
- `sort_values()` with no arguments defaults to ascending order, which puts the worst performers (negative profit) at the top.
- `subcat_profit.head(5)` shows the bottom 5 (most unprofitable) sub-categories.
- `subcat_profit.tail(5)` shows the top 5 (most profitable) sub-categories for comparison.
Not seeing negative values?
- Make sure you used sort_values() with no ascending=False argument. The default ascending order is what surfaces the negative values first.
- Confirm you are summing 'Profit', not 'Sales'. Sales is always positive. Profit can be negative.
Help me understand why my sub-category results look wrong.
Calculate monthly sales totals
Your final analysis question is about time. Does the store sell evenly throughout the year, or are there seasonal spikes?
- Create a new code cell and enter this code to calculate monthly sales across the full 2014-2017 period:
# Cell 12: Monthly sales trend
monthly_sales = df.groupby(['Order Year', 'Order Month'])['Sales'].sum().reset_index()
monthly_sales['Date'] = pd.to_datetime(
monthly_sales['Order Year'].astype(str) + '-' + monthly_sales['Order Month'].astype(str) + '-01'
)
monthly_sales = monthly_sales.sort_values('Date')
What does this code do?
- `groupby(['Order Year', 'Order Month'])` groups orders by year and month, giving you one total per month.
- `reset_index()` turns the grouped result back into a regular DataFrame with columns you can work with.
- The Date column combines year and month into a proper datetime so you can plot a continuous timeline.
- `sort_values('Date')` arranges the rows chronologically from January 2014 to December 2017.
- Run the cell. It completes without printed output because this cell prepares the monthly data for the trend chart you will build next.
- Confirm no error appears. Your monthly_sales DataFrame now contains 48 rows (one per month across 4 years).
Seeing a KeyError for Order Year or Order Month?
- These columns were created in Cell 8. If you restarted your notebook session without re-running all cells, they will not exist yet.
- Use Runtime > Run all from the Colab menu to re-run every cell from the top.
Why is my monthly sales groupby failing?
✔️ Awesome, I've got everything!
Great. Double check you have saved your notebook (Colab auto-saves, but you can press Ctrl+S or Cmd+S to be sure).
ⓧ I'd like to double check the full code
Your notebook should have the following cells in order. Scroll through your notebook and confirm each is present:
- Cell 1: Import libraries (pandas and matplotlib).
- Cell 2: Load the dataset with read_csv.
- Cell 3: df.info() to explore structure.
- Cell 4: df.describe() for summary statistics.
- Cell 5: Check data quality (duplicates and missing values).
- Cell 6: Commented-out monthly analysis attempt.
- Cell 7: Convert dates to datetime.
- Cell 8: Create Order Year and Order Month helper columns.
- Cell 9: Sales and Profit by Region (region_summary).
- Cell 10: Profit by Category (category_profit).
- Cell 11: Profit by Sub-Category (subcat_profit) showing bottom and top 5.
- Cell 12: Monthly sales trend (monthly_sales) with a Date column.
You now have hard numbers proving that some sub-categories lose money and that sales spike seasonally. Next up, you will turn these findings into charts that make the patterns instantly obvious.
Visualize Your Findings
In the previous step, you uncovered hard numbers: the West region leads in sales, Tables and Bookcases are losing money, and November brings a seasonal spike every year. Those findings are buried in tables of text that take effort to read.
Visualizations make patterns instantly obvious. A chart communicates in one glance what a table takes minutes to parse. In this step, you will turn your analysis into three publication-quality charts that you could present to any stakeholder.
In this step, get ready to:
- Create a vertical bar chart showing total sales by region.
- Create a horizontal bar chart highlighting profitable and unprofitable sub-categories.
- Create a line chart revealing monthly sales trends from 2014 to 2017.
Create a bar chart of sales by region
Your first chart will compare total sales across the four US regions. A vertical bar chart is the simplest way to show magnitude differences between categories.
- Create a new code cell in your notebook (Cell 13) and paste the following code:
# Cell 13: Visualization 1 - Sales by Region
plt.figure(figsize=(8, 5))
region_sales = df.groupby('Region')['Sales'].sum().sort_values(ascending=False)
plt.bar(region_sales.index, region_sales.values, color='steelblue')
plt.title('Total Sales by Region')
plt.ylabel('Sales ($)')
plt.xlabel('Region')
plt.tight_layout()
plt.show()
What does this code do?
- plt.figure(figsize=(8, 5)) creates a new figure canvas that is 8 inches wide and 5 inches tall.
- region_sales groups the full DataFrame by Region and sums the Sales column, sorted from highest to lowest.
- plt.bar() draws vertical bars using the region names as x-axis labels and the summed sales as bar heights.
- plt.tight_layout() adjusts spacing so labels do not get cut off at the edges.
- Run the cell by pressing the play button or Shift+Enter.
You should see a bar chart with four steelblue bars. The West region is clearly the tallest, confirming it leads in total sales.
Don't see a chart?
- Make sure all the plotting code is in the same cell. If plt.figure() and plt.show() are in different cells, the chart will not render.
- Check that you ran the earlier cells first. If df does not exist yet, you will get a NameError. Go to Runtime then Run all to re-execute every cell in order.
- Help me debug my bar chart in Google Colab.
Create a horizontal bar chart of profit by sub-category
This chart is the most revealing in the entire analysis. By coloring bars red for negative profit and green for positive profit, you can instantly spot which sub-categories are money pits.
- Create a new code cell (Cell 14) and paste the following code:
# Cell 14: Visualization 2 - Profit by Sub-Category
plt.figure(figsize=(10, 7))
colors = ['red' if x < 0 else 'green' for x in subcat_profit.values]
plt.barh(subcat_profit.index, subcat_profit.values, color=colors)
plt.title('Profit by Sub-Category')
plt.xlabel('Profit ($)')
plt.axvline(x=0, color='black', linewidth=0.5)
plt.tight_layout()
plt.show()
What does this code do?
- The list comprehension assigns 'red' to any sub-category with negative profit and 'green' to positive ones.
- plt.barh() draws horizontal bars, which work better than vertical bars when you have many category labels (17 sub-categories).
- plt.axvline(x=0) draws a thin vertical line at zero so you can clearly see which bars cross into negative territory.
- Run the cell.
You should see a horizontal bar chart with 17 bars. The bars on the left side of the zero line are red. Tables, Bookcases, and Supplies are clearly unprofitable.
Bars all showing as one color?
- Confirm you ran Cell 11 earlier, which creates subcat_profit sorted by ascending profit. If that variable does not exist, the color logic has nothing to evaluate.
- Check that the list comprehension uses subcat_profit.values (not subcat_profit alone).
- Help me fix the color logic in my horizontal bar chart.
Create a line chart of monthly sales trend
Your final chart plots monthly total sales across the full four-year period. A line chart is ideal for showing trends over time because it connects consecutive data points, making seasonal spikes jump out visually.
Before you run this cell, take a moment to predict: based on what you saw in the monthly data table, which months do you expect to show the highest spikes?
- Create a new code cell (Cell 15) and paste the following code:
# Cell 15: Visualization 3 - Monthly Sales Trend
plt.figure(figsize=(12, 4))
plt.plot(monthly_sales['Date'], monthly_sales['Sales'], color='steelblue', linewidth=1)
plt.title('Monthly Sales Trend (2014-2017)')
plt.ylabel('Sales ($)')
plt.xlabel('Month')
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()
What does this code do?
- plt.plot() connects the monthly data points with a continuous line, making the overall trend and seasonal pattern visible.
- figsize=(12, 4) makes the chart wide and short, which is the standard shape for time series data because it gives horizontal space to spread out the dates.
- plt.xticks(rotation=45) angles the date labels so they do not overlap each other.
- Run the cell.
You should see a line chart with clear seasonal spikes every November and December. The pattern repeats across all four years, confirming a predictable holiday sales surge.
Seeing a jumbled or flat line?
- Make sure you ran Cell 12 earlier, which creates the monthly_sales DataFrame with the Date column and sorts it chronologically.
- If dates appear out of order, confirm that monthly_sales = monthly_sales.sort_values('Date') is present at the end of Cell 12.
- Help me fix my monthly sales trend line chart.
✔️ Awesome, I've got everything!
Great. Double check you have saved your notebook (Ctrl+S or Cmd+S). Colab auto-saves, but it is good practice to save manually after each major section.
ⓧ I'd like to double check the full code
Scroll up through your notebook and confirm these three visualization cells are present, in order:
- Cell 13: Visualization 1 - Sales by Region (vertical bar chart with plt.bar).
- Cell 14: Visualization 2 - Profit by Sub-Category (horizontal bar chart with plt.barh and red/green colors).
- Cell 15: Visualization 3 - Monthly Sales Trend (line chart with plt.plot).
Each cell should produce a chart rendered inline when you run it. If any cell shows no output, re-run it.
Secret mission
Investigate the Discount-Profit Relationship
The store offers discounts on many products. But are those discounts actually driving sales, or just destroying profit margins? Dig deeper into the data to find out whether discounting is helping or hurting the bottom line.
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 in Google Colab, so there are no ongoing costs.
Resources you used:
- Google Colab notebook Superstore Sales Analysis (saved in Google Drive).
- Uploaded CSV file Sample - Superstore.csv (stored in Colab's temporary runtime storage).
- Downloaded CSV file on your local computer (in your Downloads folder).
Keep everything running
No action needed. Choose this if you plan to revisit your analysis, add more charts, or extend the Secret Mission further.
- Your notebook is already saved in Google Drive. You can reopen it anytime from colab.research.google.com under Recent.
- The uploaded CSV disappears when your runtime disconnects. You will need to re-upload it next time you open the notebook.
- Keep the downloaded CSV file on your computer so you can re-upload it easily.
Pause - I'll come back to this later
Disconnect your Colab runtime to free up the allocated compute resources. Your notebook code stays saved in Google Drive.
- In your Colab notebook, click Runtime in the top menu bar.
- Click Disconnect and delete runtime.
- Your code cells remain saved. When you return, click Runtime > Run all to re-execute everything (you will need to re-upload the CSV first).
Delete - I don't want to use this again
Remove all project resources completely. This cannot be undone.
- In Google Colab, click File > Move to trash to delete the notebook from Google Drive.
- Open Google Drive (drive.google.com), navigate to Trash in the left sidebar, then right-click the notebook and select Delete forever.
- Delete the Sample - Superstore.csv file from your local Downloads folder.
Nice Work!
Nice Work!
You just completed a full data analysis workflow from raw CSV to business insights backed by visualizations. You now know how to do the core work of a data analyst: load data, clean it, ask questions, and answer them with charts.
You've learned how to:
- Load and explore a real-world retail dataset (9,994 rows, 21 columns) in Google Colab, then clean it by converting string dates to proper datetime objects to enable time-based analysis.
- Use groupby aggregations to discover that the West region leads in sales, and that Tables and Bookcases are actively losing money.
- Create three publication-quality visualizations with matplotlib: a regional sales bar chart, a sub-category profit bar chart with red/green coloring, and a monthly trend line showing seasonal spikes.
- Secret Mission: Proved that discounts above 20% are correlated with negative average profit, and delivered a data-backed recommendation to cap discount levels.
Ready to quiz yourself?