Data Visualization
What I do
I provide tools and techniques for creating effective visual representations of data. I enable you to explore data patterns through exploratory plots, communicate insights through explanatory visualizations, and build interactive dashboards. Good visualization helps stakeholders understand complex data quickly and supports data-driven decision making.
When to use me
- Exploring data distributions and relationships
- Identifying patterns, trends, and anomalies
- Comparing groups or categories
- Showing changes over time
- Presenting findings to stakeholders
- Building interactive dashboards
- Reporting analysis results
- Communicating uncertainty
Core Concepts
Chart Types
- Distribution: Histogram, KDE, box plot, violin plot
- Relationship: Scatter plot, line plot, heatmap
- Comparison: Bar chart, grouped bar chart, bubble chart
- Composition: Pie chart, stacked bar, treemap
- Time Series: Line chart, area chart, candlestick
Design Principles
- Clarity: Clear titles, labels, and legends
- Simplicity: Avoid chart junk and unnecessary elements
- Color: Use appropriate color schemes (sequential, diverging, qualitative)
- Scale: Use appropriate axis scales (linear, log)
- Context: Include reference lines, annotations, and context
Tools
- Matplotlib: Low-level, flexible, publication-quality plots
- Seaborn: High-level statistical visualizations
- Plotly: Interactive plots and dashboards
- Altair: Declarative visualization
Code Examples (Python)
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
import pandas as pd
# Set style
plt.style.use('seaborn-v0_8-whitegrid')
sns.set_palette("husl")
# Basic plots with matplotlib
fig, axes = plt.subplots(2, 2, figsize=(12, 10))
# Line plot
axes[0, 0].plot(x, y, 'b-', linewidth=2, marker='o', markersize=4)
axes[0, 0].set_xlabel('X Axis')
axes[0, 0].set_ylabel('Y Axis')
axes[0, 0].set_title('Line Plot')
# Scatter plot
axes[0, 1].scatter(x, y, c=z, cmap='viridis', alpha=0.7, s=50)
axes[0, 1].set_xlabel('X Axis')
axes[0, 1].set_ylabel('Y Axis')
axes[0, 1].set_title('Scatter Plot')
# Bar chart
axes[1, 0].bar(categories, values, color=['#1f77b4', '#ff7f0e', '#2ca02c'])
axes[1, 0].set_xlabel('Category')
axes[1, 0].set_ylabel('Value')
axes[1, 0].set_title('Bar Chart')
# Histogram
axes[1, 1].hist(data, bins=30, color='steelblue', edgecolor='white', alpha=0.7)
axes[1, 1].set_xlabel('Value')
axes[1, 1].set_ylabel('Frequency')
axes[1, 1].set_title('Histogram')
plt.tight_layout()
plt.savefig('basic_plots.png', dpi=150, bbox_inches='tight')
plt.show()
# Seaborn plots
# Distribution plots
fig, axes = plt.subplots(2, 2, figsize=(12, 10))
# Histogram with KDE
sns.histplot(data, kde=True, ax=axes[0, 0], color='skyblue')
# Box plot
sns.boxplot(x='category', y='value', data=df, ax=axes[0, 1])
# Violin plot
sns.violinplot(x='category', y='value', data=df, ax=axes[1, 0])
# Pair plot for multiple variables
# sns.pairplot(df, hue='category', diag_kind='kde')
# Relationship plots
fig, axes = plt.subplots(1, 3, figsize=(15, 5))
# Scatter with regression line
sns.regplot(x='x', y='y', data=df, ax=axes[0])
# Scatter with hue
sns.scatterplot(x='x', y='y', hue='category', data=df, ax=axes[1])
# Heatmap
correlation_matrix = df.corr()
sns.heatmap(correlation_matrix, annot=True, cmap='coolwarm', center=0, ax=axes[2])
plt.tight_layout()
plt.show()
# Time series visualization
fig, axes = plt.subplots(2, 1, figsize=(12, 8))
# Line chart with confidence interval
sns.lineplot(x='date', y='value', data=df, ax=axes[0])
axes[0].set_title('Time Series')
# Area chart
sns.lineplot(x='date', y='value', data=df, ax=axes[1], fill=True)
axes[1].set_title('Area Chart')
plt.tight_layout()
plt.show()
# Categorical data visualization
fig, axes = plt.subplots(1, 3, figsize=(15, 5))
# Count plot
sns.countplot(x='category', data=df, ax=axes[0])
# Bar plot with error bars
sns.barplot(x='category', y='value', data=df, ax=axes[1], errorbar='sd')
# Grouped bar chart
sns.barplot(x='category', y='value', hue='group', data=df, ax=axes[2])
plt.tight_layout()
plt.show()
# Multi-panel figure
fig = plt.figure(figsize=(14, 10))
# GridSpec for custom layout
from matplotlib.gridspec import GridSpec
gs = GridSpec(3, 3, figure=fig, hspace=0.3, wspace=0.3)
# Create subplots
ax1 = fig.add_subplot(gs[0, :2])
ax2 = fig.add_subplot(gs[0, 2])
ax3 = fig.add_subplot(gs[1, :])
ax4 = fig.add_subplot(gs[2, 0])
ax5 = fig.add_subplot(gs[2, 1])
ax6 = fig.add_subplot(gs[2, 2])
# Add content
ax1.plot(x, y)
ax2.bar(categories, values)
ax3.scatter(x, y, c=z, cmap='viridis')
ax4.hist(data1, bins=20, alpha=0.7)
ax5.hist(data2, bins=20, alpha=0.7)
ax6.boxplot([data1, data2, data3])
plt.savefig('complex_layout.png', dpi=150, bbox_inches='tight')
plt.show()
# Annotations and styling
fig, ax = plt.subplots(figsize=(10, 6))
ax.plot(x, y, 'b-', linewidth=2)
# Add annotations
ax.annotate('Peak', xy=(x_max, y_max), xytext=(x_max+5, y_max+10),
arrowprops=dict(arrowstyle='->', color='red'),
fontsize=12, color='red')
# Add reference lines
ax.axhline(y=mean_value, color='gray', linestyle='--', label=f'Mean: {mean_value:.2f}')
ax.axvline(x=threshold, color='orange', linestyle=':', alpha=0.7)
# Add legend
ax.legend(loc='upper left')
# Styling
ax.set_xlabel('X Label', fontsize=12)
ax.set_ylabel('Y Label', fontsize=12)
ax.set_title('Styled Plot', fontsize=14, fontweight='bold')
plt.show()
Best Practices
Know your audience: Tailor complexity and detail to the audience's expertise.
Choose the right chart type: Match the chart to the data and message (comparison vs. distribution vs. relationship).
Keep it simple: Remove unnecessary elements (chart junk, excessive gridlines, decorative 3D effects).
Use color strategically: Use color to highlight, not decorate. Use consistent color schemes.
Label clearly: Axis labels, titles, and legends should be informative and readable.
Provide context: Include reference points, benchmarks, and relevant annotations.
Consider accessibility: Use colorblind-friendly palettes and ensure text is readable.
Iterate: Create multiple versions and get feedback before finalizing.
Common Patterns
Pattern 1: Exploratory Data Analysis Dashboard
def eda_dashboard(df, numeric_cols, categorical_cols):
fig, axes = plt.subplots(len(numeric_cols), 3, figsize=(15, 4*len(numeric_cols)))
for i, col in enumerate(numeric_cols):
# Distribution
sns.histplot(df[col].dropna(), kde=True, ax=axes[i, 0])
axes[i, 0].set_title(f'{col} Distribution')
# Box plot by category
if categorical_cols:
sns.boxplot(x=categorical_cols[0], y=col, data=df, ax=axes[i, 1])
# Outlier summary
q1, q3 = df[col].quantile([0.25, 0.75])
iqr = q3 - q1
outliers = df[(df[col] < q1-1.5*iqr) | (df[col] > q3+1.5*iqr)][col].count()
axes[i, 2].text(0.5, 0.5, f'Outliers: {outliers}',
ha='center', va='center', fontsize=14)
axes[i, 2].set_title(f'{col} Summary')
plt.tight_layout()
return fig
Pattern 2: Model Performance Comparison
def compare_model_performance(results_df):
fig, axes = plt.subplots(1, 3, figsize=(15, 5))
# Accuracy comparison
sns.barplot(x='model', y='accuracy', data=results_df, ax=axes[0])
axes[0].set_title('Model Accuracy Comparison')
axes[0].tick_params(axis='x', rotation=45)
# Confusion matrix heatmap
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', ax=axes[1])
axes[1].set_title('Best Model Confusion Matrix')
# ROC curves
for model_name, fpr, tpr in roc_data:
axes[2].plot(fpr, tpr, label=f'{model_name} (AUC={auc:.2f})')
axes[2].plot([0, 1], [0, 1], 'k--')
axes[2].set_xlabel('False Positive Rate')
axes[2].set_ylabel('True Positive Rate')
axes[2].set_title('ROC Curves')
axes[2].legend()
plt.tight_layout()
return fig
Pattern 3: Time Series Analysis Visualization
def timeseries_dashboard(df, date_col, value_col):
fig, axes = plt.subplots(3, 2, figsize=(14, 12))
# Raw time series
axes[0, 0].plot(df[date_col], df[value_col], linewidth=0.5)
axes[0, 0].set_title('Time Series')
# Rolling mean
rolling_mean = df[value_col].rolling(window=30).mean()
axes[0, 1].plot(df[date_col], rolling_mean, color='red', label='30-day MA')
axes[0, 1].plot(df[date_col], df[value_col], alpha=0.3)
axes[0, 1].set_title('30-Day Moving Average')
axes[0, 1].legend()
# Seasonal decomposition
from statsmodels.tsa.seasonal import seasonal_decompose
decomposition = seasonal_decompose(df[value_col], model='additive', period=365)
axes[1, 0].plot(decomposition.trend)
axes[1, 0].set_title('Trend')
axes[1, 1].plot(decomposition.seasonal)
axes[1, 1].set_title('Seasonal')
# Distribution by period
df['month'] = df[date_col].dt.month
sns.boxplot(x='month', y=value_col, data=df, ax=axes[2, 0])
axes[2, 0].set_title('Monthly Distribution')
# Autocorrelation
from pandas.plotting import autocorrelation_plot
autocorrelation_plot(df[value_col], ax=axes[2, 1])
plt.tight_layout()
return fig
1---2name: data-visualization-23description: Data visualization principles and tools for creating charts, graphs, and interactive dashboards to communicate insights from data effectively.4---56# Data Visualization78## What I do910I provide tools and techniques for creating effective visual representations of data. I enable you to explore data patterns through exploratory plots, communicate insights through explanatory visualizations, and build interactive dashboards. Good visualization helps stakeholders understand complex data quickly and supports data-driven decision making.1112## When to use me1314- Exploring data distributions and relationships15- Identifying patterns, trends, and anomalies16- Comparing groups or categories17- Showing changes over time18- Presenting findings to stakeholders19- Building interactive dashboards20- Reporting analysis results21- Communicating uncertainty2223## Core Concepts2425### Chart Types26- **Distribution**: Histogram, KDE, box plot, violin plot27- **Relationship**: Scatter plot, line plot, heatmap28- **Comparison**: Bar chart, grouped bar chart, bubble chart29- **Composition**: Pie chart, stacked bar, treemap30- **Time Series**: Line chart, area chart, candlestick3132### Design Principles33- **Clarity**: Clear titles, labels, and legends34- **Simplicity**: Avoid chart junk and unnecessary elements35- **Color**: Use appropriate color schemes (sequential, diverging, qualitative)36- **Scale**: Use appropriate axis scales (linear, log)37- **Context**: Include reference lines, annotations, and context3839### Tools40- **Matplotlib**: Low-level, flexible, publication-quality plots41- **Seaborn**: High-level statistical visualizations42- **Plotly**: Interactive plots and dashboards43- **Altair**: Declarative visualization4445## Code Examples (Python)4647```python48import matplotlib.pyplot as plt49import seaborn as sns50import numpy as np51import pandas as pd5253# Set style54plt.style.use('seaborn-v0_8-whitegrid')55sns.set_palette("husl")5657# Basic plots with matplotlib58fig, axes = plt.subplots(2, 2, figsize=(12, 10))5960# Line plot61axes[0, 0].plot(x, y, 'b-', linewidth=2, marker='o', markersize=4)62axes[0, 0].set_xlabel('X Axis')63axes[0, 0].set_ylabel('Y Axis')64axes[0, 0].set_title('Line Plot')6566# Scatter plot67axes[0, 1].scatter(x, y, c=z, cmap='viridis', alpha=0.7, s=50)68axes[0, 1].set_xlabel('X Axis')69axes[0, 1].set_ylabel('Y Axis')70axes[0, 1].set_title('Scatter Plot')7172# Bar chart73axes[1, 0].bar(categories, values, color=['#1f77b4', '#ff7f0e', '#2ca02c'])74axes[1, 0].set_xlabel('Category')75axes[1, 0].set_ylabel('Value')76axes[1, 0].set_title('Bar Chart')7778# Histogram79axes[1, 1].hist(data, bins=30, color='steelblue', edgecolor='white', alpha=0.7)80axes[1, 1].set_xlabel('Value')81axes[1, 1].set_ylabel('Frequency')82axes[1, 1].set_title('Histogram')8384plt.tight_layout()85plt.savefig('basic_plots.png', dpi=150, bbox_inches='tight')86plt.show()8788# Seaborn plots89# Distribution plots90fig, axes = plt.subplots(2, 2, figsize=(12, 10))9192# Histogram with KDE93sns.histplot(data, kde=True, ax=axes[0, 0], color='skyblue')9495# Box plot96sns.boxplot(x='category', y='value', data=df, ax=axes[0, 1])9798# Violin plot99sns.violinplot(x='category', y='value', data=df, ax=axes[1, 0])100101# Pair plot for multiple variables102# sns.pairplot(df, hue='category', diag_kind='kde')103104# Relationship plots105fig, axes = plt.subplots(1, 3, figsize=(15, 5))106107# Scatter with regression line108sns.regplot(x='x', y='y', data=df, ax=axes[0])109110# Scatter with hue111sns.scatterplot(x='x', y='y', hue='category', data=df, ax=axes[1])112113# Heatmap114correlation_matrix = df.corr()115sns.heatmap(correlation_matrix, annot=True, cmap='coolwarm', center=0, ax=axes[2])116117plt.tight_layout()118plt.show()119120# Time series visualization121fig, axes = plt.subplots(2, 1, figsize=(12, 8))122123# Line chart with confidence interval124sns.lineplot(x='date', y='value', data=df, ax=axes[0])125axes[0].set_title('Time Series')126127# Area chart128sns.lineplot(x='date', y='value', data=df, ax=axes[1], fill=True)129axes[1].set_title('Area Chart')130131plt.tight_layout()132plt.show()133134# Categorical data visualization135fig, axes = plt.subplots(1, 3, figsize=(15, 5))136137# Count plot138sns.countplot(x='category', data=df, ax=axes[0])139140# Bar plot with error bars141sns.barplot(x='category', y='value', data=df, ax=axes[1], errorbar='sd')142143# Grouped bar chart144sns.barplot(x='category', y='value', hue='group', data=df, ax=axes[2])145146plt.tight_layout()147plt.show()148149# Multi-panel figure150fig = plt.figure(figsize=(14, 10))151152# GridSpec for custom layout153from matplotlib.gridspec import GridSpec154gs = GridSpec(3, 3, figure=fig, hspace=0.3, wspace=0.3)155156# Create subplots157ax1 = fig.add_subplot(gs[0, :2])158ax2 = fig.add_subplot(gs[0, 2])159ax3 = fig.add_subplot(gs[1, :])160ax4 = fig.add_subplot(gs[2, 0])161ax5 = fig.add_subplot(gs[2, 1])162ax6 = fig.add_subplot(gs[2, 2])163164# Add content165ax1.plot(x, y)166ax2.bar(categories, values)167ax3.scatter(x, y, c=z, cmap='viridis')168ax4.hist(data1, bins=20, alpha=0.7)169ax5.hist(data2, bins=20, alpha=0.7)170ax6.boxplot([data1, data2, data3])171172plt.savefig('complex_layout.png', dpi=150, bbox_inches='tight')173plt.show()174175# Annotations and styling176fig, ax = plt.subplots(figsize=(10, 6))177ax.plot(x, y, 'b-', linewidth=2)178179# Add annotations180ax.annotate('Peak', xy=(x_max, y_max), xytext=(x_max+5, y_max+10),181 arrowprops=dict(arrowstyle='->', color='red'),182 fontsize=12, color='red')183184# Add reference lines185ax.axhline(y=mean_value, color='gray', linestyle='--', label=f'Mean: {mean_value:.2f}')186ax.axvline(x=threshold, color='orange', linestyle=':', alpha=0.7)187188# Add legend189ax.legend(loc='upper left')190191# Styling192ax.set_xlabel('X Label', fontsize=12)193ax.set_ylabel('Y Label', fontsize=12)194ax.set_title('Styled Plot', fontsize=14, fontweight='bold')195196plt.show()197```198199## Best Practices2002011. **Know your audience**: Tailor complexity and detail to the audience's expertise.2022032. **Choose the right chart type**: Match the chart to the data and message (comparison vs. distribution vs. relationship).2042053. **Keep it simple**: Remove unnecessary elements (chart junk, excessive gridlines, decorative 3D effects).2062074. **Use color strategically**: Use color to highlight, not decorate. Use consistent color schemes.2082095. **Label clearly**: Axis labels, titles, and legends should be informative and readable.2102116. **Provide context**: Include reference points, benchmarks, and relevant annotations.2122137. **Consider accessibility**: Use colorblind-friendly palettes and ensure text is readable.2142158. **Iterate**: Create multiple versions and get feedback before finalizing.216217## Common Patterns218219### Pattern 1: Exploratory Data Analysis Dashboard220```python221def eda_dashboard(df, numeric_cols, categorical_cols):222 fig, axes = plt.subplots(len(numeric_cols), 3, figsize=(15, 4*len(numeric_cols)))223 224 for i, col in enumerate(numeric_cols):225 # Distribution226 sns.histplot(df[col].dropna(), kde=True, ax=axes[i, 0])227 axes[i, 0].set_title(f'{col} Distribution')228 229 # Box plot by category230 if categorical_cols:231 sns.boxplot(x=categorical_cols[0], y=col, data=df, ax=axes[i, 1])232 233 # Outlier summary234 q1, q3 = df[col].quantile([0.25, 0.75])235 iqr = q3 - q1236 outliers = df[(df[col] < q1-1.5*iqr) | (df[col] > q3+1.5*iqr)][col].count()237 axes[i, 2].text(0.5, 0.5, f'Outliers: {outliers}', 238 ha='center', va='center', fontsize=14)239 axes[i, 2].set_title(f'{col} Summary')240 241 plt.tight_layout()242 return fig243```244245### Pattern 2: Model Performance Comparison246```python247def compare_model_performance(results_df):248 fig, axes = plt.subplots(1, 3, figsize=(15, 5))249 250 # Accuracy comparison251 sns.barplot(x='model', y='accuracy', data=results_df, ax=axes[0])252 axes[0].set_title('Model Accuracy Comparison')253 axes[0].tick_params(axis='x', rotation=45)254 255 # Confusion matrix heatmap256 sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', ax=axes[1])257 axes[1].set_title('Best Model Confusion Matrix')258 259 # ROC curves260 for model_name, fpr, tpr in roc_data:261 axes[2].plot(fpr, tpr, label=f'{model_name} (AUC={auc:.2f})')262 axes[2].plot([0, 1], [0, 1], 'k--')263 axes[2].set_xlabel('False Positive Rate')264 axes[2].set_ylabel('True Positive Rate')265 axes[2].set_title('ROC Curves')266 axes[2].legend()267 268 plt.tight_layout()269 return fig270```271272### Pattern 3: Time Series Analysis Visualization273```python274def timeseries_dashboard(df, date_col, value_col):275 fig, axes = plt.subplots(3, 2, figsize=(14, 12))276 277 # Raw time series278 axes[0, 0].plot(df[date_col], df[value_col], linewidth=0.5)279 axes[0, 0].set_title('Time Series')280 281 # Rolling mean282 rolling_mean = df[value_col].rolling(window=30).mean()283 axes[0, 1].plot(df[date_col], rolling_mean, color='red', label='30-day MA')284 axes[0, 1].plot(df[date_col], df[value_col], alpha=0.3)285 axes[0, 1].set_title('30-Day Moving Average')286 axes[0, 1].legend()287 288 # Seasonal decomposition289 from statsmodels.tsa.seasonal import seasonal_decompose290 decomposition = seasonal_decompose(df[value_col], model='additive', period=365)291 axes[1, 0].plot(decomposition.trend)292 axes[1, 0].set_title('Trend')293 axes[1, 1].plot(decomposition.seasonal)294 axes[1, 1].set_title('Seasonal')295 296 # Distribution by period297 df['month'] = df[date_col].dt.month298 sns.boxplot(x='month', y=value_col, data=df, ax=axes[2, 0])299 axes[2, 0].set_title('Monthly Distribution')300 301 # Autocorrelation302 from pandas.plotting import autocorrelation_plot303 autocorrelation_plot(df[value_col], ax=axes[2, 1])304 305 plt.tight_layout()306 return fig307```