5.3. Pandas Plot Styling#

Hide code cell source

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

np.random.seed(42)
df1 = pd.DataFrame({
    'A': np.arange(100),
    'B': np.random.randn(100).cumsum(),
    'C': np.random.randn(100).cumsum(),
})
df2 = pd.DataFrame({
    'a': np.random.rand(50),
    'b': np.random.rand(50),
    'c': np.random.rand(50),
})
df = pd.DataFrame(np.random.randn(1000, 2), columns=['a', 'b'])
tips = sns.load_dataset('tips')

5.3.1. Styling Options#

5.3.1.1. Plotting Styles#

matplotlib offers a range of pre-configured plotting styles. Setting the style can be used to easily give plots the general look that you want. To set the style, the syntax is:

matplotlib.style.use(my_plot_style)

To check the aviaible style in the environment, use

plt.style.available

Uncomment/comment the following styles one by one to see the style effect.

plt.style.use("default")        ### reset to default style
# plt.style.use("ggplot")
# plt.style.use("bmh")  
# plt.style.use("classic") 
# plt.style.use("seaborn-v0_8-muted")  


np.random.seed(42)              ### for reproducibility
df_test = pd.DataFrame({'values': [np.random.randint(0, 100) for num in range(10)]})
df_test.plot.bar(figsize=(4, 3), fontsize=7);
plt.title("Bar Plot with Style", fontsize=10);
plt.legend(fontsize=7, loc="best", bbox_to_anchor=(1, 1));
plt.tick_params(axis='x', rotation=0)
plt.tight_layout()
../../_images/ee9714dcace1560fa15b13523001887b536b464e4480f89d0a17f0cf1d54156f.png

5.3.1.2. Color Maps#

tips = sns.load_dataset("tips")

ax = tips.plot(
    kind="scatter",
    x="total_bill", y="tip",
    c="size",              # column to map to color
    colormap="viridis",
    figsize=(5, 3),
    alpha=0.7,
    fontsize=8,
    title="Tips vs Total Bill — colored by party size"
)

plt.tight_layout()
../../_images/d13549adcbdc004d04e6238af8719b4adc2e478a6965fbfe6f5b0bdd4f1e9103.png

Different colormaps can be used for different presentation effects. To see the available colormaps, use the syntax:

plt.colormaps()
fig, axes = plt.subplots(1, 3, figsize=(12, 3))

for ax, cmap in zip(axes, ["viridis", "coolwarm", "RdYlGn"]):
    tips.plot(
        kind="scatter",
        x="total_bill", y="tip",
        c="size",
        colormap=cmap,
        alpha=0.7,
        fontsize=8,
        ax=ax,
        title=cmap
    )

plt.tight_layout()
../../_images/18b1808803fd67496ea410bcd800ad7bac5206e4a1b39a2482747afe7e20c06b.png

5.3.1.3. Size#

Or use s to indicate size based off another column. s parameter needs to be an array, not just the name of a column:

tips = sns.load_dataset("tips")

ax = tips.plot(
    kind="scatter",
    x="total_bill",
    y="tip",
    s=tips["size"] * 20,
    figsize=(4, 3),
    alpha=0.5,
    fontsize=8,
    title="Tips vs Total Bill"
)

ax.set_xlabel("Total Bill ($)")
ax.set_ylabel("Tip ($)")
plt.tight_layout()
../../_images/cffcf830d5d543d4584820b55921f3b51386399aa3ae2605410d447c973cf969.png
### EXERCISE 5: Size-Encoded Scatter
# Goal: Add a third variable using marker size.
# Requirements:
# 1) Plot `A` vs `B` from `df1`.
# 2) Use point size based on `abs(C) * 60`.
# 3) Set `alpha=0.5` so overlap stays readable.
# Stretch: Compare size encoding to color encoding and note tradeoffs.

# Your code here

Hide code cell source

### Solution
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

try:
    df1
except NameError:
    rng = np.random.default_rng(0)
    df1 = pd.DataFrame(rng.normal(size=(100, 3)), columns=['A', 'B', 'C'])

ax = df1.plot(kind='scatter', x='A', y='B', s=df1['C'].abs() * 60, alpha=0.5)
ax.set_title('A vs B with Size Encoding')
plt.show()
../../_images/16cf186e5ebab8aae7bf7dd8ba28eacec74c1de4c5f9bc965dc8da34c8a0d917.png
# Sample DataFrames for exercises
import numpy as np

np.random.seed(42)

df1 = pd.DataFrame({
    'A': np.random.randn(100),
    'B': np.random.randn(100),
    'C': np.random.randn(100)
})

# Use positive values to support stacked area plots
df2 = pd.DataFrame({
    'a': np.random.rand(50),
    'b': np.random.rand(50),
    'c': np.random.rand(50)
})
### EXERCISE 6: Box Plot Comparison
# Goal: Compare spread and outliers across `df2` columns.
# Requirements:
# 1) Create a box plot for all numeric columns in `df2`.
# 2) Use `figsize=(8, 4)`.
# 3) Set title to "Box Plot of df2".
# Stretch: Rotate x tick labels by 30 degrees for readability.

# Your code here

Hide code cell source

### Solution
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

try:
    df2
except NameError:
    rng = np.random.default_rng(1)
    df2 = pd.DataFrame(rng.normal(size=(80, 4)), columns=['A', 'B', 'C', 'D'])

ax = df2.plot(kind='box', figsize=(8, 4))
ax.set_title('Box Plot of df2')
ax.tick_params(axis='x', rotation=30)
plt.show()
../../_images/f2184a4b1acc8f6640d5bf7ab22d6aa7494fdc792e55849a623e78a089ab5010.png
# Solution
df2.plot.box()
<Axes: >
../../_images/7c988fb4a266e4cc7d85e1ef3ea854bca801c5ef6115c44f5134e05d5651b2b4.png
### EXERCISE 7: Hexbin for Dense Data
# Goal: Visualize dense bivariate data without overplotting.
# Requirements:
# 1) Use the existing `df` with columns `a` and `b`.
# 2) Create a hexbin plot with `gridsize=25`.
# 3) Use a visible colormap (for example, `cmap='Oranges'`).
# Stretch: Change `gridsize` to 15 and 40 and compare detail vs smoothness.

# Your code here

Hide code cell source

### Solution
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

try:
    df
except NameError:
    rng = np.random.default_rng(2)
    df = pd.DataFrame({'a': rng.normal(size=500), 'b': rng.normal(size=500)})

ax = df.plot(kind='hexbin', x='a', y='b', gridsize=25, cmap='Oranges')
ax.set_title('Hexbin Plot')
plt.show()
../../_images/ccc2e95c23fdbd962b8a1e1d5ba8aaa0b390f696ab617841c7554be52997175f.png
# Solution
df.plot.hexbin(x='a', y='b', gridsize=25, cmap='Oranges')
<Axes: xlabel='a', ylabel='b'>
../../_images/7de140cbc1ac7858d783ea91281724783f90659c826463130e303e4f16fbb8a8.png
### EXERCISE: KDE for a Single Variable
# Goal: Plot a smooth estimate of one distribution.
# load dataset if needed tips = sns.load_dataset("tips")
# Requirements:
# 1) Plot KDE for `tips['tip']`.
# 2) Set `figsize=(4, 3)`.
# 3) Add title "KDE of Column tip".
### Your code starts here.


### Your code ends here.

Hide code cell source

### Solution
import seaborn as sns
import matplotlib.pyplot as plt

tips = sns.load_dataset('tips')
ax = tips['tip'].plot(kind='kde', figsize=(4, 3))
ax.set_title('KDE of Column tip')
plt.show()
../../_images/4614c68d9e64ba57b44faa80fe8542534b05efcc89acfe01be61df7d1eaf96cb.png
### Solution

tips['tip'].plot(kind="kde", 
                 figsize=(4,3), 
                 title="KDE of Column tip")
<Axes: title={'center': 'KDE of Column tip'}, ylabel='Density'>
../../_images/4614c68d9e64ba57b44faa80fe8542534b05efcc89acfe01be61df7d1eaf96cb.png
### EXERCISE:Multi-Column Density Plot
# Goal: Compare distributions of all `df2` columns on one chart.
# Requirements:
# 1) Create a density plot for `df2`.
# 2) Set `figsize=(8, 4)`.
# 3) Add title "Density Curves for df2".
# Stretch: Keep only two columns and compare how interpretation changes.

# Your code here

Hide code cell source

### Solution
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

try:
    df2
except NameError:
    rng = np.random.default_rng(1)
    df2 = pd.DataFrame(rng.normal(size=(80, 4)), columns=['A', 'B', 'C', 'D'])

ax = df2.plot(kind='density', figsize=(8, 4))
ax.set_title('Density Curves for df2')
plt.show()
../../_images/b647741a3b36ef5e7d2eca8a27686e0bcc50e78662a91f016818107122b018d7.png

5.3.2. Section Practice#

Use this short exercise to check the main workflow from this section.

### Exercise: Plan a Pandas Plot Styling Chart
# A team wants to compare sales across four regions.
# Create two lists named regions and sales. Then print the region with the highest sales.
### Your code starts here




### Your code ends here

Hide code cell source

### Solution
regions = ['North', 'South', 'East', 'West']
sales = [120, 145, 132, 118]
best_index = sales.index(max(sales))
print("Highest sales region:", regions[best_index])
Highest sales region: South
### Solution
regions = ["North", "South", "East", "West"]
sales = [240, 215, 260, 230]
best_index = sales.index(max(sales))
print(regions[best_index])
East