Pharma Sales Dashboard in Power BI
Clean pharmaceutical sales data with Python and build a Power BI dashboard.
Introduction
30 Second Summary
Pharmaceutical companies generate massive amounts of sales data every month. Turning that raw data into clear visual insights is exactly what healthcare data analysts do every day.
In this project, you will clean raw pharmaceutical sales data with Python, then build an interactive 2-page dashboard in Power BI that visualizes drug sales performance across categories and time periods.
What You'll Build
A professional pharmaceutical sales analytics dashboard powered by a Python data cleaning script and Power BI visualizations.
By the end of this project, you'll have:
- A Python script (clean_pharma_data.py) that transforms raw CSV sales data into a clean, analysis-ready Excel file using pandas.
- A 2-page interactive Power BI report with KPI cards, trend charts, category breakdowns, and interactive slicers for filtering.
- A custom DAX measure that calculates average sales per transaction.
- Secret Mission: A Year-over-Year growth analysis with conditional formatting that highlights underperforming products.
Are there any prerequisites?
None. This project includes setup instructions for all required tools, including Python, VS Code, and Power BI Desktop. You do not need any prior experience with data analytics or dashboards.
Before We Start
Pharmaceutical companies track sales across dozens of drug categories every month. Turning that raw data into a clear, interactive dashboard is one of the most valued skills for healthcare data analysts.
In this step, you will set up your Python environment and download the dataset you will clean and visualize throughout this project.
In this step, get ready to:
- Create a project folder with a Python virtual environment.
- Install the pandas and openpyxl libraries.
- Download the pharmaceutical sales dataset from Kaggle.
Create your project folder and virtual environment
A virtual environment gives your project its own isolated set of Python packages. This prevents conflicts with other projects on your machine.
- Press the Windows key (Windows) or Cmd+Space (macOS) to open your search bar.
- Type VS Code and press Enter to open it.
- Open the integrated terminal by pressing Ctrl+` (the backtick key, usually above Tab).
What is the integrated terminal?
VS Code has a built-in terminal panel so you can run commands without leaving the editor. On Windows, it defaults to PowerShell.
- Move to your Desktop by running this command:
cd ~/Desktop
- Create your project folder and move into it by running these commands:
mkdir pharma-dashboard
cd pharma-dashboard
- Confirm the folder was created by checking that your terminal prompt now shows pharma-dashboard as the current directory.
- Create a virtual environment and activate it by running these commands:
python -m venv venv
venv\Scripts\activate
You should see (venv) appear at the beginning of your terminal prompt. This confirms the virtual environment is active.
What is a virtual environment?
A virtual environment is an isolated Python workspace. Packages you install inside it stay separate from your system Python, so different projects can use different library versions without conflicts.
Not seeing (venv) in your prompt?
If you get an error about running scripts being disabled, PowerShell's execution policy is blocking activation. Run Set-ExecutionPolicy -Scope CurrentUser RemoteSigned then try venv\Scripts\activate again.
If you see a "python is not recognized" error, make sure Python 3.12 is installed and added to your system PATH.
Help me fix my virtual environment activation issue.
Install the required Python libraries
Your cleaning script needs two libraries: one for data manipulation and one for writing Excel files.
- Install pandas and openpyxl by running this command:
pip install pandas==2.2.3 openpyxl==3.1.5
You should see output ending with "Successfully installed" followed by the package names and versions.
What do these libraries do?
pandas is Python's most popular data manipulation library. You will use it to load, clean, reshape, and export your pharmaceutical sales data.
openpyxl is the engine pandas uses behind the scenes to write Excel .xlsx files. Without it, the Excel export step would fail.
Seeing a pip error?
Make sure you see (venv) in your prompt before running the install command. If it is missing, run venv\Scripts\activate first.
If you see a network timeout, check your internet connection and try the command again.
Help me fix my pip install error.
Download the dataset from Kaggle
The dataset you will use contains monthly pharmaceutical sales figures across multiple drug categories. It is hosted for free on Kaggle, a popular platform for finding public datasets.
- Open this link in your browser:
- https://www.kaggle.com/datasets/milanzdravkovic/pharma-sales-data
- If you do not have a Kaggle account, click Register and create a free account. You can sign up with your Google account for the fastest setup.
- On the dataset page, click the Download button near the top of the page.
- Extract the downloaded ZIP file. You will find a file called salesmonthly.csv inside.
- Move salesmonthly.csv into your pharma-dashboard folder (the one on your Desktop).
- Confirm the file is in the right place by running this command in your VS Code terminal:
dir
You should see salesmonthly.csv and the venv folder listed in the output.
Don't see salesmonthly.csv?
Make sure you extracted the ZIP file before moving it. The CSV file is inside the archive, not the ZIP itself.
Double-check that you moved the file into the pharma-dashboard folder on your Desktop, not a different location.
Help me find my downloaded dataset file.
Your environment is ready and the raw data is in place. Next up, you will write a Python script that cleans this data and prepares it for Power BI.
Clean the Data with Python
Your environment is set up and the raw dataset is ready to go. Now you need to transform that raw CSV into something Power BI can work with.
The Kaggle dataset stores each drug category as its own column. Power BI works best with "long" format data where each row is a single observation. You will write a Python script that reshapes the data, adds time columns, and exports a clean Excel file.
In this step, get ready to:
- Load and inspect the raw pharmaceutical sales CSV.
- Transform the data from wide format to long format and enrich it with time columns.
- Export a clean Excel file ready for Power BI.
Create your cleaning script and load the data
Before transforming anything, you need to load the CSV and understand what you are working with. The inspection step reveals column names, row counts, and missing values.
- In VS Code, create a new file called clean_pharma_data.py inside your pharma-dashboard folder.
- Add the following code to load and inspect the dataset:
import pandas as pd
# Load the raw CSV data
df = pd.read_csv("salesmonthly.csv")
# Inspect the data
print("Shape:", df.shape)
print("Columns:", df.columns.tolist())
print("First 5 rows:")
print(df.head())
print("\nMissing values:")
print(df.isnull().sum())
What does this code do?
This loads salesmonthly.csv into a pandas DataFrame and prints a quick health check.
- df.shape shows the number of rows and columns as a tuple.
- df.columns.tolist() lists every column name so you can see the drug categories.
- df.isnull().sum() counts missing values per column so you know what needs cleaning.
- Save clean_pharma_data.py.
- Run the script in your terminal by entering:
python clean_pharma_data.py
You should see the shape printed as a tuple, a list of column names including datum and drug category codes like M01AB and M01AE, the first 5 rows of data, and a count of missing values per column.
Seeing a FileNotFoundError?
- Make sure salesmonthly.csv is in the same folder as your script (pharma-dashboard).
- Check that your terminal is in the pharma-dashboard folder. Run ls (macOS) or dir (Windows) to confirm both files are listed.
- Verify the filename matches exactly. The Kaggle download may name it salesmonthly.csv with no capital letters.
Help me fix a FileNotFoundError when running my pandas script.
Transform and enrich the data
The raw dataset is in "wide" format where each drug category is its own column. Power BI works much better with "long" format where you have one row per observation. This lets you use the drug category as a filter and slicer dimension.
- Add the following code below your inspection block in clean_pharma_data.py to reshape the data from wide to long format:
# The dataset has a 'datum' column (date) and drug category columns (M01AB, M01AE, etc.)
# Each column represents monthly sales for a drug category
# We need to unpivot (melt) this from wide format to long format for Power BI
# Parse the date column
df["datum"] = pd.to_datetime(df["datum"])
# Get all drug category columns (everything except 'datum')
drug_columns = [col for col in df.columns if col != "datum"]
# Melt from wide to long format
df_long = df.melt(
id_vars=["datum"],
value_vars=drug_columns,
var_name="DrugCategory",
value_name="Sales"
)
# Rename columns for Power BI clarity
df_long = df_long.rename(columns={"datum": "Date"})
What does this code do?
pd.to_datetime() converts the datum text column into a proper datetime type that Power BI recognizes as a date.
df.melt() is the key transformation. It "unpivots" the wide table so each drug category column becomes a row with a DrugCategory label and a Sales value. This is the long format Power BI needs.
Why melt from wide to long?
Power BI charts expect a single column to use as a category dimension (for slicers, legends, and axes). With wide format, you would need a separate chart for each drug. Long format lets you filter, group, and compare all drugs in one visualization.
- Now add the enrichment and cleanup code directly below the rename line:
# Extract Year and Month for easier analysis in Power BI
df_long["Year"] = df_long["Date"].dt.year
df_long["Month"] = df_long["Date"].dt.month
df_long["MonthName"] = df_long["Date"].dt.strftime("%b")
# Drop rows where Sales is null
df_long = df_long.dropna(subset=["Sales"])
# Round sales to 2 decimal places
df_long["Sales"] = df_long["Sales"].round(2)
# Sort by date and category
df_long = df_long.sort_values(["Date", "DrugCategory"]).reset_index(drop=True)
What does this code do?
- .dt.year and .dt.month extract numeric year and month values. These make it easy to build Year slicers in Power BI.
- .dt.strftime("%b") creates a short month name (Jan, Feb, etc.) for readable chart labels.
- .dropna(subset=["Sales"]) removes any rows with missing sales values so they do not skew your dashboard totals.
- .round(2) keeps sales figures clean at two decimal places.
- Save clean_pharma_data.py.
You will not see new output yet. The next substep adds print statements and the Excel export so you can verify everything works.
Export to Excel
The final piece writes your cleaned DataFrame to an Excel file that Power BI can import directly.
- Add the following code at the bottom of clean_pharma_data.py:
# Display final shape and sample
print("\nCleaned data shape:", df_long.shape)
print("Sample:")
print(df_long.head(10))
# Export to Excel for Power BI
df_long.to_excel("pharma_sales_clean.xlsx", index=False, engine="openpyxl")
print("\nExported to pharma_sales_clean.xlsx successfully!")
What does this code do?
- The print statements show the final row count and a sample so you can confirm the transformation worked.
- to_excel() writes the DataFrame to pharma_sales_clean.xlsx. The index=False argument prevents pandas from adding an extra index column. The engine="openpyxl" argument uses the openpyxl library you installed earlier.
- Save clean_pharma_data.py.
- Run the complete script by entering:
python clean_pharma_data.py
You should see the original shape, column names, first 5 rows, and missing value counts from the inspection block. Then you should see the cleaned data shape (a much larger row count because of the melt), a 10-row sample with columns Date, DrugCategory, Sales, Year, Month, MonthName, and the success message.
- Confirm the Excel file was created by running:
ls
You should see pharma_sales_clean.xlsx listed alongside clean_pharma_data.py and salesmonthly.csv.
- Open pharma_sales_clean.xlsx in Microsoft Excel to confirm it contains clean data with the expected columns.
Script runs but no Excel file appears?
- Check the terminal output for error messages. A common issue is forgetting to activate your virtual environment, which means openpyxl is not available.
- Make sure you see the success message in the terminal output. If the script errors before reaching the export line, fix the error shown in the traceback first.
- Confirm your virtual environment is active. You should see (venv) at the start of your terminal prompt.
Help me fix my pandas Excel export.
✔️ Awesome, I've got everything!
Great. Double check you have saved clean_pharma_data.py and that pharma_sales_clean.xlsx exists in your folder.
ⓧ I'd like to double check the full code
Here is the complete clean_pharma_data.py file:
import pandas as pd
# Load the raw CSV data
df = pd.read_csv("salesmonthly.csv")
# Inspect the data
print("Shape:", df.shape)
print("Columns:", df.columns.tolist())
print("First 5 rows:")
print(df.head())
print("\nMissing values:")
print(df.isnull().sum())
# The dataset has a 'datum' column (date) and drug category columns (M01AB, M01AE, etc.)
# Each column represents monthly sales for a drug category
# We need to unpivot (melt) this from wide format to long format for Power BI
# Parse the date column
df["datum"] = pd.to_datetime(df["datum"])
# Get all drug category columns (everything except 'datum')
drug_columns = [col for col in df.columns if col != "datum"]
# Melt from wide to long format
df_long = df.melt(
id_vars=["datum"],
value_vars=drug_columns,
var_name="DrugCategory",
value_name="Sales"
)
# Rename columns for Power BI clarity
df_long = df_long.rename(columns={"datum": "Date"})
# Extract Year and Month for easier analysis in Power BI
df_long["Year"] = df_long["Date"].dt.year
df_long["Month"] = df_long["Date"].dt.month
df_long["MonthName"] = df_long["Date"].dt.strftime("%b")
# Drop rows where Sales is null
df_long = df_long.dropna(subset=["Sales"])
# Round sales to 2 decimal places
df_long["Sales"] = df_long["Sales"].round(2)
# Sort by date and category
df_long = df_long.sort_values(["Date", "DrugCategory"]).reset_index(drop=True)
# Display final shape and sample
print("\nCleaned data shape:", df_long.shape)
print("Sample:")
print(df_long.head(10))
# Export to Excel for Power BI
df_long.to_excel("pharma_sales_clean.xlsx", index=False, engine="openpyxl")
print("\nExported to pharma_sales_clean.xlsx successfully!")
Your data is cleaned and ready. Next up, you will import this Excel file into Power BI and start building your dashboard.
Import Data into Power BI and Transform with Power Query
Your cleaned Excel file is ready. Now you need to bring it into Power BI Desktop so you can build visualizations on top of it.
Power BI doesn't just display raw data. It uses a data model where each column has a defined type (Date, Text, Number). Getting these types right now prevents broken charts and calculation errors later.
In this step, get ready to:
- Import your clean Excel file into Power BI Desktop.
- Verify and correct column data types in Power Query Editor.
- Load the data model and save your project file.
Open Power BI Desktop and import your Excel file
Power BI needs a data source to work with. You will connect it to the pharma_sales_clean.xlsx file your Python script created.
- Press the Windows key to open your search bar.
- Type Power BI Desktop and press Enter to open it.
- Wait for Power BI Desktop to fully load. You will see a blank canvas with the Home ribbon at the top.
What is Power BI Desktop?
Power BI Desktop is a free Windows application for building interactive data reports. You connect it to data sources, create visualizations, and publish dashboards. No license is needed for building reports locally.
- In the Home ribbon, click Get Data.
- Select Excel Workbook from the dropdown menu.
- In the file browser, navigate to your pharma-dashboard folder on the Desktop.
- Select pharma_sales_clean.xlsx and click Open.
The Navigator pane appears, showing the sheets and tables inside your Excel file.
- Check the box next to the data sheet (it will be named Sheet1 or pharma_sales_clean).
- Click Load to import the data directly into Power BI.
Why Load instead of Transform Data here?
Clicking Load brings the data straight into the data model. You will open Power Query Editor in the next substep to verify types. This keeps the import and type-checking as separate, clear actions.
Don't see your file in the browser?
Make sure you are looking inside the pharma-dashboard folder on your Desktop. The file is called pharma_sales_clean.xlsx and was created when you ran your Python script in the previous step.
If you don't see it, return to VS Code and re-run your script to regenerate the file.
Help me find my Excel file in Power BI's file browser.
Verify and adjust data types in Power Query Editor
Power BI auto-detects column types when it imports data, but it doesn't always get them right. Incorrect types cause broken calculations and charts that won't render properly.
- Click Transform data on the Home tab of the ribbon to open Power Query Editor.
Power Query Editor opens in a new window. You can see your data in the center pane with column headers at the top. Each column header shows a small icon indicating its current data type.
- Check the Date column. Its icon should show a calendar (Date type). If it shows something else, click the icon next to the column header and select Date from the list.
- Check the DrugCategory column. Its icon should show ABC (Text type). If not, click the icon and select Text.
- Check the Sales column. Its icon should show 1.2 (Decimal Number). If not, click the icon and select Decimal Number.
- Check the Year column. Its icon should show 123 (Whole Number). If not, click the icon and select Whole Number.
- Check the Month column. Set it to Whole Number using the same method.
- Check the MonthName column. Set it to Text using the same method.
What do the data type icons mean?
Each column header in Power Query Editor has a small icon on its left side. A calendar means Date. ABC means Text. 1.2 means Decimal Number. 123 means Whole Number.
Clicking the icon opens a dropdown where you can change the type. If Power Query asks whether to replace or insert the step, choose Replace current.
Seeing a type conversion error?
If Power Query shows an error after changing a column type, the column may contain unexpected values. Make sure your Python script ran successfully and that pharma_sales_clean.xlsx opens cleanly in Microsoft Excel before importing.
Help me fix a data type error in Power Query Editor.
Close and apply the changes
With all column types verified, you can close Power Query Editor and load the finalized data into your Power BI data model.
- Click Close & Apply in the top-left corner of the Power Query Editor ribbon.
Power BI processes the data and returns you to the Report view. You should see your table listed in the Fields pane on the right side of the screen.
- In the Fields pane, expand the table (it may be named pharma_sales_clean). Confirm you see columns: Date, DrugCategory, Sales, Year, Month, and MonthName.
What is the Fields pane?
The Fields pane on the right side of the Report view shows all the tables and columns in your data model. When you build visualizations in the next step, you will drag fields from this pane onto the canvas.
- Save your Power BI file by pressing Ctrl+S.
- In the Save dialog, navigate to your pharma-dashboard folder on the Desktop.
- Name the file pharma_sales_dashboard and click Save.
Fields pane is empty?
If the Fields pane shows no table, the data may not have loaded correctly. Click Transform data on the Home ribbon to reopen Power Query Editor. Check that your query shows data in the preview pane, then click Close & Apply again.
Help me troubleshoot why my Fields pane is empty after importing data.
Your data is loaded and typed correctly. Next up, you will build your first dashboard page with KPI cards and charts that visualize the sales trends.
Build Page 1 - Sales Overview Dashboard
Your cleaned data is loaded into Power BI and ready for visualization. Now it is time to turn those rows of numbers into a dashboard that communicates insights at a glance.
In this step, you will build the Sales Overview page. This page gives anyone who opens your report a quick snapshot of total performance, trends over time, and which drug categories drive the most revenue.
In this step, get ready to:
- Create KPI cards showing total sales and an average sales measure.
- Build a line chart showing monthly sales trends.
- Build a bar chart showing top-performing drug categories with a year slicer.
Create KPI cards and a DAX measure
KPI cards are single-number visuals that highlight your most important metrics. You will create three cards: Total Sales, Total Quantity, and Average Sales per Transaction.
The first two cards use built-in aggregation. The third requires a custom DAX measure because Power BI does not have a built-in "average per row" aggregation for this data.
- Click an empty area of the report canvas so no visual is selected.
- In the Visualizations pane on the right, select the Build visual tab, then click the Card icon in the visual gallery.
- A blank card placeholder appears on the canvas.
- In the Fields pane (also on the right), expand the Sales table.
- Drag the Sales field into the Values field well in the Visualizations pane.
- The card now displays the sum of all sales. This is your Total Sales card.
What is a Card visual?
A Card visual displays a single number prominently. When you drag a numeric field to it, Power BI automatically applies SUM aggregation. This makes cards ideal for at-a-glance KPIs like total revenue or total count.
- Click an empty area of the canvas to deselect the first card.
- Add a second Card visual from the Visualizations pane.
- Drag the Sales field into its Values field well.
- This second card also shows the sum of Sales. It represents Total Quantity Sold.
Why do both cards show the same field?
This dataset does not have a separate quantity column. Each row represents one month of sales for one drug category. The Sales field is the only numeric measure available, so both cards draw from it. In a real-world scenario, you would map distinct fields to each card.
Now create a custom DAX measure for the third card. DAX (Data Analysis Expressions) lets you write formulas that calculate on the fly based on the filters applied to your report.
- In the Fields pane, right-click the Sales table.
- Select New measure from the context menu.
- A formula bar appears at the top of the report canvas with the placeholder text Measure =.
- Replace the placeholder with the following DAX formula:
Avg Sale = DIVIDE(SUM(Sales[Sales]), COUNTROWS(Sales))
- Press Enter to save the measure.
What does this DAX formula do?
DIVIDE safely divides two values and returns BLANK instead of an error when the denominator is zero. SUM(Sales[Sales]) totals all sales across the current filter context. COUNTROWS(Sales) counts how many rows are in the filtered table.
The result is the average sales value per transaction row. This measure recalculates dynamically when the user applies slicers or filters.
- Click an empty area of the canvas to deselect everything.
- Add a third Card visual from the Visualizations pane.
- In the Fields pane, expand the Sales table and drag Avg Sale (it has a calculator icon) into the Values field well.
- The third card now displays the average sales per transaction.
- Arrange all three cards side by side near the top of the canvas by dragging them into position.
Don't see Avg Sale in the Fields pane?
Make sure you pressed Enter after typing the formula. The measure only saves when you commit it. If you see a red underline in the formula bar, check for typos. The column reference must be Sales[Sales] (table name, then column name in brackets).
Help me fix my DAX measure.
Build a line chart for sales trends
A line chart shows how a metric changes over time. Placing Date on the X-axis and Sales on the Y-axis reveals seasonal patterns and long-term trends in drug sales.
- Click an empty area of the canvas below your cards.
- In the Visualizations pane, select the Line chart icon from the visual gallery.
- A blank line chart placeholder appears on the canvas.
- From the Fields pane, drag Date to the X-axis field well.
- Drag Sales to the Y-axis field well.
- The line chart now shows sales values plotted over time.
Next, give the chart a descriptive title so anyone viewing the dashboard understands what it shows.
- With the line chart selected, click the Format visual icon (the paint roller) in the Visualizations pane.
- Select the General tab.
- Expand the Title section.
- Replace the default title text with Monthly Sales Trend.
Why format chart titles?
Clear titles make dashboards self-explanatory. A hiring manager reviewing your portfolio should understand what each chart shows without needing to inspect field wells or data sources.
Line chart shows a single point instead of a trend?
Power BI may have placed Date into a date hierarchy (Year > Quarter > Month > Day). If you see only one aggregated point, click the small double-arrow icon on the X-axis of the chart to drill down, or expand the Date field in the X-axis well and remove the hierarchy levels you do not need.
Help me fix my line chart.
Build a bar chart for top categories and add a slicer
A bar chart makes it easy to compare sales across drug categories. Adding a Slicer lets users filter the entire page by year, turning a static report into an interactive tool.
- Click an empty area of the canvas.
- In the Visualizations pane, select the Clustered bar chart icon.
- Drag DrugCategory to the Y-axis field well.
- Drag Sales to the X-axis field well.
- The chart now shows bars representing total sales for each drug category.
Sort the chart so the highest-selling categories appear at the top.
- With the bar chart selected, click the More options icon (...) at the top-right corner of the visual.
- Select Sort axis > Sales.
- Click More options (...) again and select Sort axis > Sort descending.
- The longest bar (highest sales) now appears at the top of the chart.
Now add a Slicer so users can filter the dashboard by year.
- Click an empty area of the canvas.
- In the Visualizations pane, select the Slicer icon.
- Drag the Year field from the Fields pane into the slicer's field well.
- The slicer appears with year values. Clicking a year filters all visuals on the page to that year.
What is a Slicer?
A Slicer is a visual filter that sits directly on the report canvas. When a user clicks a value in the slicer, all other visuals on the same page update to show only data matching that selection. This is what makes Power BI dashboards interactive.
Verify your dashboard by clicking different years in the slicer. The line chart, bar chart, and KPI cards should all update to reflect the selected year.
Slicer not filtering other visuals?
Make sure the Year field in your slicer comes from the same Sales table as the fields in your other visuals. If they share the same table, cross-filtering happens automatically.
Help me fix my slicer.
Your Sales Overview page is complete. Next up, you will build a second page that lets users drill into product-level details with a matrix table and donut chart.
Build Page 2 - Product Deep Dive
Your Sales Overview page gives a great high-level picture of total revenue and trends. But a hiring manager will want to see you can drill deeper into product-level performance.
In this step, you will build a second report page focused on individual drug categories. You will add a matrix table (a pivot-table style visual), a donut chart for distribution, and slicers so viewers can interactively filter the data.
In this step, get ready to:
- Add and rename a new report page.
- Create a matrix table showing sales by product and month.
- Add a donut chart and interactive slicers for filtering.
Add a new report page
Multi-page reports let you separate high-level summaries from detailed analysis. This keeps each page focused and easier to read.
- At the bottom of the Power BI canvas, click the + icon to add a new page.
- Double-click the new page tab at the bottom of the screen.
- Type Product Deep Dive and press Enter to rename it.
You should now see a blank canvas with the tab labelled Product Deep Dive at the bottom.
Create a matrix table
A Matrix visual works like a pivot table. It shows values broken down by both rows and columns, so you can compare drug categories across months in a single view.
- In the Visualizations pane on the right, click the Matrix icon (a grid of cells).
- From the Fields pane, drag DrugCategory into the Rows well.
- Drag MonthName into the Columns well.
- Drag Sales into the Values well.
Your matrix should now display a grid with drug categories down the left side and month abbreviations across the top, with sales figures in each cell.
What is a Matrix visual?
Think of it as an interactive spreadsheet pivot table embedded directly in your report. Viewers can expand and collapse rows, and the matrix responds to slicers and cross-filtering from other visuals on the same page.
Now enable row subtotals so each drug category shows a total across all months.
- With the Matrix visual selected, click the paintbrush icon (Format visual) in the Visualizations pane.
- Expand the Row subtotals section.
- Toggle the switch to On.
You should now see a Total row at the bottom of the matrix summarizing sales across all categories.
Matrix showing a single column or looks blank?
Make sure you placed MonthName in the Columns well, not in Rows. If both fields land in Rows you will see a flat list instead of a grid.
Also check that Sales is in the Values well. Without a value field, the matrix has no numbers to display.
Help me fix my Matrix visual layout.
Add a donut chart and slicers
A donut chart shows how total sales are distributed across categories at a glance. Slicers give viewers push-button control over which data appears on the page.
- Click an empty area of the canvas to deselect the matrix.
- In the Visualizations pane, click the Donut Chart icon.
- Drag DrugCategory into the Legend well.
- Drag Sales into the Values well.
You should see a donut chart with coloured segments representing each drug category's share of total sales.
Now add two slicers so viewers can filter by year and by drug category.
- Click an empty area of the canvas to deselect the donut chart.
- In the Visualizations pane, click the Slicer icon.
- Drag the Year field into the slicer's Field well.
- Click an empty area of the canvas again to deselect.
- Add a second Slicer visual by clicking the Slicer icon in the Visualizations pane.
- Drag DrugCategory into this slicer's Field well.
Your page should now have a Year slicer and a DrugCategory slicer alongside the matrix and donut chart.
Why two slicers instead of one?
The Year slicer lets viewers isolate a specific time period, while the DrugCategory slicer lets them focus on one or more products. Together, they provide the fine-grained control that stakeholders expect from an interactive dashboard.
Now test that cross-filtering is working correctly.
- Click on any coloured segment of the donut chart.
- Observe that the matrix table updates to highlight only the selected category's row.
- Click the same donut segment again to deselect it and restore the full view.
What is cross-filtering?
Power BI visuals on the same page are interconnected by default. Clicking a data point in one visual automatically filters or highlights the others based on shared data fields. This is what makes the dashboard interactive without any extra configuration.
- Save your file by pressing Ctrl+S.
Clicking the donut doesn't change the matrix?
Make sure both visuals are on the same page. Cross-filtering only works between visuals that share a report page.
If you accidentally placed a visual on Page 1, delete it and recreate it on the Product Deep Dive page.
Help me troubleshoot cross-filtering between my visuals.
Your two-page dashboard is now complete. You have a high-level Sales Overview and a granular Product Deep Dive. Next up is the Secret Mission, where you will add a Year-over-Year growth measure and conditional formatting to highlight underperforming products.
Secret mission
Add Year-over-Year Growth Analysis with Conditional Formatting
Your dashboard shows current sales performance, but a hiring manager wants to see trend analysis. Can you add Year-over-Year growth measures and use conditional formatting to instantly highlight which drug categories are growing or declining?
Clean Up Your Resources
Clean Up Your Resources
This project runs entirely on your local machine, so there are no ongoing costs or cloud resources to worry about. Decide whether to keep your project files for your portfolio or delete them to free up disk space.
Resources you used:
- pharma-dashboard project folder (includes clean_pharma_data.py, pharma_sales_clean.xlsx, salesmonthly.csv, your .pbix Power BI report, and the Python virtual environment).
- Kaggle account (free, used to download the dataset).
Keep everything running
No action needed. Choose this if you plan to continue refining your dashboard or want to keep it as a portfolio piece.
- Your pharma-dashboard folder stays on your Desktop with all files intact.
- Your Kaggle account remains active for future dataset downloads.
- Your .pbix file is ready to open in Power BI Desktop any time.
Pause - I'll come back to this later
Close running applications to free up memory. Your project files stay on disk for when you return.
- Save and close your Power BI Desktop report.
- Close VS Code.
- If your virtual environment is still active in any terminal, deactivate it by running:
deactivate
Your files remain in the pharma-dashboard folder, ready to pick up again later.
Delete - I don't want to use this again
Remove all project files from your machine. This cannot be undone.
- Close Power BI Desktop and VS Code.
- Delete the entire pharma-dashboard folder from your Desktop.
On Windows, open a terminal and run:
rmdir /s /q ~\Desktop\pharma-dashboard
On macOS or Linux, run:
rm -rf ~/Desktop/pharma-dashboard
This removes your Python script, the cleaned Excel file, the raw CSV, the virtual environment, and the Power BI report.
Nice Work!
Nice Work!
You just built a professional pharmaceutical sales analytics dashboard from scratch. From raw CSV data to interactive Power BI visualizations, you now have a portfolio-ready project that demonstrates the exact skills healthcare data analyst roles demand.
Here's what you accomplished:
- Cleaned and transformed raw pharmaceutical sales data using Python and pandas, converting wide-format CSV into a long-format Excel file ready for analysis.
- Imported and validated data in Power BI Desktop using Power Query, then built a 2-page interactive dashboard with KPI cards, line charts, bar charts, a matrix table, and slicers.
- Created custom DAX measures including Average Sales per Transaction, giving you hands-on experience with Power BI's formula language.
- Secret Mission: Built Year-over-Year growth analysis with DAX time intelligence functions and applied conditional formatting to highlight underperforming products.
Ready to quiz yourself?