Why One Chart Beats Twenty Tables
A table makes the reader do the math in their head. A chart does it for them. When you show Sales by Region as bars, the West bar towers and the story is instant. Reserve tables for the exact numbers a reader will copy, and use charts for the shape of the story.
matplotlib is the engine under almost every Python chart; seaborn is a layer on top that styles and simplifies common statistical plots. Start with matplotlib, add seaborn when you want a professional look with less code.
Step 1: Set Up the Plotting Stack
With your venv active run 'pip install matplotlib seaborn'. matplotlib draws the chart; seaborn themes it. Together they cover nearly every analyst chart.
Run 'import matplotlib.pyplot as plt' and 'import seaborn as sns', then 'df = pd.read_csv("orders.csv")'. The plt alias is the standard you'll see in every example online.
Run 'sns.set_theme(style="whitegrid")'. This adds light gridlines and removes the harsh default look. A common mistake is skipping this and shipping a chart that looks like 2005.
Step 2: Build a Bar Chart of Sales by Region
Run 'region_sales = df.groupby('Region')['Sales'].sum()'. Charts need summarized data, not 50,000 raw rows, so group before you plot or the bars become unreadable.
Run 'region_sales.plot(kind='bar')' then 'plt.title('Sales by Region')' and 'plt.show()'. The West bar at 4,210,000 visibly beats East at 3,980,500.
Run 'sns.barplot(x='Region', y='Sales', data=df.groupby('Region')['Sales'].sum().reset_index())'. Seaborn computes the aggregation for you and applies a cleaner theme in one call.
I recommend always calling plt.show() in a notebook and plt.savefig() in a script. In a script the figure closes before you see it, so saving to PNG is the only way your chart survives. A missing show in a notebook just shows nothing.
Step 3: Plot a Trend With a Line Chart
Run 'df['OrderDate'] = pd.to_datetime(df['OrderDate'])'. Line charts need real dates on the x-axis, not text, or the points connect in the wrong order.
Run 'monthly = df.set_index('OrderDate')['Sales'].resample('M').sum()'. This totals Sales per month. On a year of data you get 12 points, the right density for a trend line.
Run 'monthly.plot(kind='line', marker='o')' then 'plt.show()'. The marker dots each month so a flat stretch reads as steady, not missing data.
Step 4: See Distribution With a Histogram
Run 'sns.histplot(df['Sales'], bins=30)'. This shows how often each Sales value range appears. You'll see most orders cluster under 500 and a thin tail of big deals.
Run 'sns.histplot(data=df, x='Sales', hue='Region', bins=30)'. Coloring by Region overlays four distributions so you can spot which region lands more high-value orders at a glance.
If the histogram piles up at zero, your Sales column likely holds negatives or blanks. Print 'df['Sales'].describe()' to check the min before you trust the shape.
A common mistake is plotting a histogram on a column with commas in the numbers, so Sales stays text and seaborn throws an error. Run df['Sales'] = df['Sales'].astype(float) first if describe() shows it as object.
Step 5: Correlations With a Heatmap
Run 'corr = df[['Sales','Orders','Discount']].corr()'. This returns how each numeric column moves with the others, from -1 to 1. Discount and Sales often sit near -0.4.
Run 'sns.heatmap(corr, annot=True, cmap='coolwarm')'. The annot=True prints the numbers in each cell, so a manager reads '-0.42' without guessing the color.
Run 'plt.savefig("corr.png", dpi=150, bbox_inches="tight")'. The tight box crops whitespace so the image drops cleanly into PowerPoint without a white border.

Worked Example: A 35 Percent West Share on a Slide
Group Sales by Region: West 4,210,000, East 3,980,500, North 2,640,000, South 1,170,000. A bar chart makes West's lead obvious, but the exact share comes from dividing by the 12,000,500 total. West is 35.1 percent, East 33.2 percent, North 22.0 percent, South 9.7 percent. I put those four percentages in a caption under the chart so the slide carries both the story and the proof.
Run 'shares = region_sales / region_sales.sum() * 100' then 'plt.figtext(0.5, 0.01, shares.round(1).to_string())'. The caption prints the numbers below the plot.
Run 'plt.savefig("region_sales.png", dpi=150, bbox_inches="tight")'. At 150 dpi the text stays sharp when projected in a conference room.
Python Charts vs Excel Charts
Excel charts are fine for a one-off. But when the source CSV refreshes weekly, a saved script rebuilds every chart in one run while Excel charts need manual reconnecting. If your data is already in a workbook, our Excel chart selection guide helps you pick the right chart type before you plot.
Step 6: Show a Relationship With a Scatter Plot
When you suspect two columns move together, a scatter plot is the honest test. Plot Orders on x and Sales on y and the dots either climb, meaning they relate, or sit in a cloud, meaning they don't. A correlation number alone hides this shape; the scatter shows it.
Run 'sns.scatterplot(data=df, x="Orders", y="Sales")'. If the dots rise left to right, more Orders come with more Sales, which sounds obvious until a region breaks the pattern and you spot it here.
Run 'sns.scatterplot(data=df, x="Orders", y="Sales", hue="Region")'. Separating regions by color reveals whether one region drives the trend or all of them share it, a detail a single correlation line blurs.
Step 7: Add a Title That Ages Well
Run 'plt.title("Sales by Region, 2024", fontsize=12)'. A title with the year and metric means the saved PNG still makes sense months later when you've forgotten what it showed.
Run 'plt.savefig("sales_by_region.png", dpi=150, bbox_inches="tight")'. The dpi=150 keeps text sharp when projected; bbox_inches="tight" trims the white margin so it drops cleanly into a slide.
If a saved chart looks empty, you likely called savefig before show or plotted into a figure you later cleared. Build the plot, then save as the last step, and the file will match your screen.
Match the chart type to the question or the reader fills in their own story. Use a bar for category comparisons like Region, a line for time like monthly Sales, and a scatter for relationships between two numbers. Picking wrong, say a line across unrelated regions, implies an order that does not exist and misleads the room. Our how to read charts guide covers that choice in detail.
Choose the Chart Type From the Question
Pick the chart from the question, not from habit. 'Which region sells most' is a bar chart. 'Are sales growing' is a line chart. 'Do big orders come with more units' is a scatter. Reaching for a pie chart by default hides the small slices and makes close values impossible to compare, which is why analysts lean on bars and lines for real numbers rather than wedges.
Label everything a reader can't guess. A bar with no axis title forces the viewer to infer that height means dollars, and they often infer wrong. Set 'xlabel', 'ylabel', and 'title' on every chart you save, and keep the title specific, like 'Sales by Region, 2024', so the image still makes sense months later without the notebook open beside it to explain the bars.
Watch the scale. A line chart that starts its y-axis at zero shows true change; one that starts at 1,000,000 makes a flat quarter look like a crash. matplotlib defaults to a tight range, so set 'plt.ylim(0, max)' when the point is the size of the bars, not a dramatic wiggle. The honest scale is the one a skeptic in the room would accept without a caveat.
Save at a size that survives a slide. A 72 dpi screenshot goes blurry when projected, so export at 150 dpi with 'bbox_inches="tight"' to drop the empty margin. Build the plot, then save as the last step, because the figure closes the moment the cell finishes and an early save captures a blank canvas with no bars on it.
One chart, one message. A stacked bar with five series and a trend line and a second axis tells no story because the eye doesn't know where to land. When you catch yourself adding a third element, split it into a second chart. A clean single-message plot beats a busy mockup that confuses the room and buries the one number that mattered.
Next Steps
A chart is only as good as the data cleaning behind it. The next move is scrubbing the raw Orders file so the bars you plot represent real sales, not duplicate or mis-typed rows.
Pick one question, group the data, plot it, and save a PNG with a one-line caption. That single image is a finished answer to a real manager question.
Wrap the load, group, and savefig calls in a script and rerun it each week. Your deck updates from one command instead of an hour of clicks.


