| name | data-visualization |
| description | Data visualization principles and tools for creating charts, graphs, and interactive dashboards to communicate insights from data effectively. |
| category | data-science |
| keywords | ["data-visualization","matplotlib","seaborn","plotting","charts","graphs","dashboards","visualization","exploratory visualization"] |
| difficulty | intermediate |
| related_skills | ["pandas","numpy","exploratory-data-analysis"] |
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
plt.style.use('seaborn-v0_8-whitegrid')
sns.set_palette("husl")
fig, axes = plt.subplots(2, 2, figsize=(12, 10))
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')
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')
axes[1, 0].bar(categories, values, color=['#1f77b4', '#ff7f0e', '#2ca02c'])
axes[, ].set_xlabel()
axes[, ].set_ylabel()
axes[, ].set_title()
axes[, ].hist(data, bins=, color=, edgecolor=, alpha=)
axes[, ].set_xlabel()
axes[, ].set_ylabel()
axes[, ].set_title()
plt.tight_layout()
plt.savefig(, dpi=, bbox_inches=)
plt.show()
fig, axes = plt.subplots(, , figsize=(, ))
sns.histplot(data, kde=, ax=axes[, ], color=)
sns.boxplot(x=, y=, data=df, ax=axes[, ])
sns.violinplot(x=, y=, data=df, ax=axes[, ])
fig, axes = plt.subplots(, , figsize=(, ))
sns.regplot(x=, y=, data=df, ax=axes[])
sns.scatterplot(x=, y=, hue=, data=df, ax=axes[])
correlation_matrix = df.corr()
sns.heatmap(correlation_matrix, annot=, cmap=, center=, ax=axes[])
plt.tight_layout()
plt.show()
fig, axes = plt.subplots(, , figsize=(, ))
sns.lineplot(x=, y=, data=df, ax=axes[])
axes[].set_title()
sns.lineplot(x=, y=, data=df, ax=axes[], fill=)
axes[].set_title()
plt.tight_layout()
plt.show()
fig, axes = plt.subplots(, , figsize=(, ))
sns.countplot(x=, data=df, ax=axes[])
sns.barplot(x=, y=, data=df, ax=axes[], errorbar=)
sns.barplot(x=, y=, hue=, data=df, ax=axes[])
plt.tight_layout()
plt.show()
fig = plt.figure(figsize=(, ))
matplotlib.gridspec GridSpec
gs = GridSpec(, , figure=fig, hspace=, wspace=)
ax1 = fig.add_subplot(gs[, :])
ax2 = fig.add_subplot(gs[, ])
ax3 = fig.add_subplot(gs[, :])
ax4 = fig.add_subplot(gs[, ])
ax5 = fig.add_subplot(gs[, ])
ax6 = fig.add_subplot(gs[, ])
ax1.plot(x, y)
ax2.bar(categories, values)
ax3.scatter(x, y, c=z, cmap=)
ax4.hist(data1, bins=, alpha=)
ax5.hist(data2, bins=, alpha=)
ax6.boxplot([data1, data2, data3])
plt.savefig(, dpi=, bbox_inches=)
plt.show()
fig, ax = plt.subplots(figsize=(, ))
ax.plot(x, y, , linewidth=)
ax.annotate(, xy=(x_max, y_max), xytext=(x_max+, y_max+),
arrowprops=(arrowstyle=, color=),
fontsize=, color=)
ax.axhline(y=mean_value, color=, linestyle=, label=)
ax.axvline(x=threshold, color=, linestyle=, alpha=)
ax.legend(loc=)
ax.set_xlabel(, fontsize=)
ax.set_ylabel(, fontsize=)
ax.set_title(, fontsize=, fontweight=)
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):
sns.histplot(df[col].dropna(), kde=True, ax=axes[i, 0])
axes[i, 0].set_title(f'{col} Distribution')
if categorical_cols:
sns.boxplot(x=categorical_cols[0], y=col, data=df, ax=axes[i, 1])
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))
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)
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', ax=axes[1])
axes[1].set_title('Best Model Confusion Matrix')
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))
axes[0, 0].plot(df[date_col], df[value_col], linewidth=0.5)
axes[0, 0].set_title('Time Series')
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()
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')
df['month'] = df[date_col].dt.month
sns.boxplot(x='month', y=value_col, data=df, ax=axes[, ])
axes[, ].set_title()
pandas.plotting autocorrelation_plot
autocorrelation_plot(df[value_col], ax=axes[, ])
plt.tight_layout()
fig