By Fatskills Exam Guides Team — the exam nerds behind 28,500+ quizzes and 2.1M practice questions across 500+ global exams.
A Hyper-Practical, Zero-Fluff Guide
You’re building a dashboard for a client, and your raw matplotlib/seaborn plots look like they were generated by a 2005 Excel macro. The labels are unreadable, the legend is misplaced, the colors are clashing, and there’s no clear takeaway. This is what happens when you ignore chart customization.
matplotlib
seaborn
In production, bad charts = bad decisions. Stakeholders won’t trust your analysis if they can’t read it. Executives won’t act on insights if they’re buried in clutter. And if you’re preparing for a PL-300 (Power BI) or data science certification, you’ll fail if your visuals don’t meet professional standards.
Real-world scenario:You’re a data scientist at a retail company. Your team just ran an A/B test on two ad campaigns. You plot the results, but: - The y-axis label says "conversion_rate" instead of "Conversion Rate (%)".- The legend overlaps the data.- The colors are indistinguishable for colorblind users.- There’s no annotation highlighting the statistically significant difference.
"conversion_rate"
"Conversion Rate (%)"
Your manager rejects the report. You just wasted 3 hours of work because you didn’t customize the chart.
This guide will teach you how to: ✅ Make charts readable (labels, titles, axis formatting).✅ Guide attention (legends, annotations, color palettes).✅ Avoid common pitfalls (overlapping text, poor color choices).✅ Pass certification exams (PL-300, Google Data Analytics, etc.).
"Revenue (USD)"
"rev"
"colorblind"
"viridis"
"$10K"
10000
grid
spines
figsize
dpi
tight_layout()
subplots_adjust()
pandas
bash pip install matplotlib seaborn pandas
Create a professional-looking sales dashboard with: ✅ Clear labels & title.✅ A well-positioned legend.✅ A colorblind-friendly palette.✅ Annotations highlighting key trends.✅ Proper axis formatting.
import pandas as pd import matplotlib.pyplot as plt import seaborn as sns # Load sample data (replace with your CSV) data = { "Month": ["Jan", "Feb", "Mar", "Apr", "May", "Jun"], "Product_A": [12000, 15000, 18000, 22000, 25000, 28000], "Product_B": [8000, 9000, 11000, 13000, 15000, 17000], "Product_C": [5000, 6000, 7000, 8000, 9000, 10000] } df = pd.DataFrame(data) df.set_index("Month", inplace=True) print(df.head())
Output:
Product_A Product_B Product_C Month Jan 12000 8000 5000 Feb 15000 9000 6000 Mar 18000 11000 7000
plt.figure(figsize=(10, 6)) plt.plot(df.index, df["Product_A"], label="Product A") plt.plot(df.index, df["Product_B"], label="Product B") plt.plot(df.index, df["Product_C"], label="Product C") plt.title("Monthly Sales") plt.xlabel("Month") plt.ylabel("Revenue") plt.legend() plt.show()
Problem: The chart is ugly and unprofessional: - Default colors are hard to distinguish.- Legend overlaps the data.- No units on the y-axis.- No annotations for key insights.
plt.figure(figsize=(10, 6)) plt.plot(df.index, df["Product_A"], label="Product A") plt.plot(df.index, df["Product_B"], label="Product B") plt.plot(df.index, df["Product_C"], label="Product C") # Custom title & labels plt.title("Monthly Sales Performance (2023)", fontsize=16, pad=20) # pad = space below title plt.xlabel("Month", fontsize=12) plt.ylabel("Revenue (USD)", fontsize=12) plt.legend() plt.show()
Improvements:✅ Clearer title with padding.✅ Units on y-axis (USD).
USD
plt.figure(figsize=(10, 6)) sns.set_palette("colorblind") # Colorblind-friendly palette plt.plot(df.index, df["Product_A"], label="Product A", linewidth=2.5) plt.plot(df.index, df["Product_B"], label="Product B", linewidth=2.5) plt.plot(df.index, df["Product_C"], label="Product C", linewidth=2.5) plt.title("Monthly Sales Performance (2023)", fontsize=16, pad=20) plt.xlabel("Month", fontsize=12) plt.ylabel("Revenue (USD)", fontsize=12) # Move legend outside the plot plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left', borderaxespad=0) plt.show()
Improvements:✅ Colorblind-friendly palette (sns.set_palette("colorblind")).✅ Thicker lines for better visibility.✅ Legend outside the plot (bbox_to_anchor).
sns.set_palette("colorblind")
bbox_to_anchor
plt.figure(figsize=(10, 6)) sns.set_palette("colorblind") plt.plot(df.index, df["Product_A"], label="Product A", linewidth=2.5) plt.plot(df.index, df["Product_B"], label="Product B", linewidth=2.5) plt.plot(df.index, df["Product_C"], label="Product C", linewidth=2.5) plt.title("Monthly Sales Performance (2023)", fontsize=16, pad=20) plt.xlabel("Month", fontsize=12) plt.ylabel("Revenue (USD)", fontsize=12) # Highlight Product A's growth plt.annotate( "Strong growth (+133%)", xy=("Jun", 28000), xytext=("Apr", 25000), arrowprops=dict(facecolor="black", shrink=0.05), fontsize=10 ) plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left', borderaxespad=0) plt.show()
Improvements:✅ Annotation highlights key trend.✅ Arrow guides attention.
plt.figure(figsize=(10, 6)) sns.set_palette("colorblind") plt.plot(df.index, df["Product_A"], label="Product A", linewidth=2.5) plt.plot(df.index, df["Product_B"], label="Product B", linewidth=2.5) plt.plot(df.index, df["Product_C"], label="Product C", linewidth=2.5) plt.title("Monthly Sales Performance (2023)", fontsize=16, pad=20) plt.xlabel("Month", fontsize=12) plt.ylabel("Revenue (USD)", fontsize=12) # Format y-axis to show $10K instead of 10000 plt.gca().yaxis.set_major_formatter('${x:,.0f}K') # Remove top/right spines (borders) sns.despine() # Add light grid plt.grid(alpha=0.3) plt.annotate( "Strong growth (+133%)", xy=("Jun", 28000), xytext=("Apr", 25000), arrowprops=dict(facecolor="black", shrink=0.05), fontsize=10 ) plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left', borderaxespad=0) plt.tight_layout() # Prevent label cutoff plt.show()
Final Improvements:✅ Y-axis formatted ($10K instead of 10000).✅ Removed clutter (sns.despine()).✅ Light grid for readability.✅ tight_layout() prevents label cutoff.
$10K
sns.despine()
plt.savefig( "sales_dashboard.png", dpi=300, # High resolution for print bbox_inches="tight" # Prevents label cutoff )
Why this matters:- Low DPI (72) = blurry in reports.- High DPI (300) = crisp in PDFs/print.
"Revenue"
pad
plt.title()
bbox_to_anchor=(1.05, 1)
frameon=False
sns.color_palette("viridis")
plt.gca().yaxis.set_major_formatter()
plt.yscale("log")
plt.xticks(rotation=45)
figsize=(10, 6)
dpi=300
dpi=150
bbox_inches="tight"
plt.tight_layout()
plt.subplots_adjust()
sns.FacetGrid
plt.legend(bbox_to_anchor=(1.05, 1))
plt.savefig(dpi=300)
plt.legend(loc="best")
✅ plt.legend(bbox_to_anchor=(1.05, 1))
"How do you format y-axis labels as currency?"
plt.ylabel("$")
✅ plt.gca().yaxis.set_major_formatter('${x:,.0f}')
plt.gca().yaxis.set_major_formatter('${x:,.0f}')
"Which palette is colorblind-friendly?"
"tab10"
ax.set_title()
ax.set_title() is explicit (better for subplots).
sns.despine() vs plt.grid(False)
plt.grid(False)
"You need to highlight a key data point in a line chart. Which method should you use?"- ❌ plt.text() (static, no arrow) - ✅ plt.annotate() (supports arrows)
plt.text()
plt.annotate()
Create a bar chart comparing quarterly sales for 3 products. Customize it with: - A colorblind-friendly palette.- Dollar-formatted y-axis.- Annotations showing the highest sales quarter.
import pandas as pd import matplotlib.pyplot as plt import seaborn as sns data = { "Quarter": ["Q1", "Q2", "Q3", "Q4"], "Product_X": [50000, 60000, 70000, 80000], "Product_Y": [30000, 35000, 40000, 45000], "Product_Z": [20000, 25000, 30000, 35000] } df = pd.DataFrame(data).set_index("Quarter") plt.figure(figsize=(10, 6)) sns.set_palette("colorblind") df.plot(kind="bar", width=0.8) plt.title("Quarterly Sales by Product", fontsize=16, pad=20) plt.xlabel("Quarter", fontsize=12) plt.ylabel("Revenue (USD)", fontsize=12) # Format y-axis as currency plt.gca().yaxis.set_major_formatter('${x:,.0f}') # Annotate highest sales max_sales = df.max().max() max_quarter = df.idxmax().idxmax() plt.annotate( "Peak Sales", xy=(df.index.get_loc(max_quarter), max_sales), xytext=(1, max_sales * 0.9), arrowprops=dict(facecolor="black", shrink=0.05) ) plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left') plt.tight_layout() plt.show()
Why it works:- sns.set_palette("colorblind") ensures accessibility.- yaxis.set_major_formatter formats currency.- annotate() highlights the peak sales quarter.
yaxis.set_major_formatter
annotate()
plt.title("Title", fontsize=16, pad=20)
plt.xlabel("X Label", fontsize=12)
plt.annotate("Text", xy=(x, y), xytext=(x2, y2), arrowprops=dict(facecolor="black"))
plt.savefig("chart.png", dpi=300, bbox_inches="tight")
plt.legend()
Join 4M+ learners. Unlock unlimited quizzes, wrong-answer tracking, flashcards + reminders, study guides, and 1-on-1 challenges.