{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Top 6 Python Libraries for Visualization: Which One to Use?\n", "\n", "## Motivation {#motivation}\n", "\n", "If you're new to Python visualization, the vast number of libraries and examples available might seem overwhelming. Some popular libraries for visualization include Matplotlib, seaborn, Plotly, Bokeh, Altair, and Pygal.\n", "\n", "When visualizing a DataFrame, choosing the right library can be challenging as different libraries excel in specific cases.\n", "\n", "This article will show the pros and cons of each library. By the end, you will gain a better understanding of their distinct features, making it easier for you to select the optimal library.\n", "\n", "## Quick Reference {#quick-reference}\n", "\n", "Before diving into detailed examples, here's a comprehensive comparison to help you choose the right visualization library for your project:\n", "\n", "| **Feature** | **Matplotlib** | **seaborn** | **Pygal** | **Plotly** | **Altair** | **Bokeh** |\n", "|-------------|----------------|-------------|-----------|------------|------------|-----------|\n", "| **Code Complexity** | High | Low | Low | Medium | Medium | Medium-High |\n", "| **Interactivity** | None (static) | None (static) | Basic hover | Advanced | Grammar-based | Advanced |\n", "| **Chart Types** | Extensive (50+) | Common plots | Basic (14 types) | Extensive (50+) | Statistical focus | Extensive |\n", "| **Web Integration** | Poor | Poor | Good (SVG) | Excellent | Good | Excellent |\n", "| **Customization** | High | Limited | Medium | High | Medium | High |\n", "| **Best Use Cases** | Publications, Papers | Statistical plots | Lightweight web apps | Dashboards, BI | Data exploration | Interactive web apps |\n", "| **Dependencies** | Moderate | Moderate | Minimal | Heavy | Moderate | Moderate |\n", "\n", "### Quick Decision Guide\n", "\n", "Here is a quick decision guide to help you choose the right visualization library for your project:\n", "\n", "**Choose Matplotlib when:** Creating publication-quality static plots, need unlimited customization control, working on academic papers or research\n", "\n", "**Choose seaborn when:** Making statistical visualizations quickly, want beautiful plots with minimal code, working with pandas DataFrames \n", "\n", "**Choose Pygal when:** Building lightweight web applications, need SVG vector graphics that scale perfectly, want minimal dependencies and fast loading\n", "\n", "**Choose Plotly when:** You need interactive visualizations with hover tooltips, zooming, and clickable legends, or when building web dashboards and applications that require user engagement with the data\n", "\n", "**Choose Altair when:** Doing statistical data exploration, want grammar-of-graphics approach, need linked/coordinated visualizations, working primarily in Jupyter notebooks\n", "\n", "**Choose Bokeh when:** Building complex interactive web applications, need linked plots and advanced interactions, want fine-grained control over web deployment, creating custom visualization tools\n", "\n", "\n", "## Matplotlib {#matplotlib}\n", "\n", "[Matplotlib](https://matplotlib.org/) is probably the most common Python library for visualizing data. Almost everyone interested in data science has likely utilized Matplotlib at least once.\n", "\n", "### Pros\n", "\n", "#### Easy to interpret data properties\n", "\n", "When analyzing data, it's often helpful to get a quick overview of its distribution.\n", "\n", "For example, if you want to examine the distribution of the top 100 users with the most followers, Matplotlib is typically sufficient." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import matplotlib.pyplot as plt\n", "import numpy as np\n", "import pandas as pd\n", "\n", "new_profile = pd.read_csv(\n", " \"https://gist.githubusercontent.com/khuyentran1401/98658198f0ef0cb12abb34b4f2361fd8/raw/ece16eb32e1b41f5f20c894fb72a4c198e86a5ea/github_users.csv\"\n", ")\n", "\n", "top_followers = new_profile.sort_values(by=\"followers\", axis=0, ascending=False)[:100]\n", "\n", "fig = plt.figure()\n", "\n", "plt.bar(top_followers.user_name, top_followers.followers)\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Despite Matplotlib's suboptimal x-axis representation, the graph provides a clear understanding of the data distribution.\n", "\n", "#### Versatility\n", "\n", "Matplotlib is very versatile and capable of generating a wide range of graph types. The Matplotlib's [website](https://matplotlib.org/tutorials/introductory/sample_plots.html) offers comprehensive documentation and a gallery of various graphs, making it easy to find tutorials for virtually any type of plot." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "fig = plt.figure()\n", "\n", "plt.text(\n", " 0.6,\n", " 0.7,\n", " \"learning\",\n", " size=40,\n", " rotation=20.0,\n", " ha=\"center\",\n", " va=\"center\",\n", " bbox={\n", " \"boxstyle\": \"round\",\n", " \"ec\": (1.0, 0.5, 0.5),\n", " \"fc\": (1.0, 0.8, 0.8),\n", " },\n", ")\n", "\n", "plt.text(\n", " 0.55,\n", " 0.6,\n", " \"machine\",\n", " size=40,\n", " rotation=-25.0,\n", " ha=\"right\",\n", " va=\"top\",\n", " bbox={\n", " \"boxstyle\": \"square\",\n", " \"ec\": (1.0, 0.5, 0.5),\n", " \"fc\": (1.0, 0.8, 0.8),\n", " },\n", ")\n", "\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Animation capabilities\n", "\n", "Matplotlib provides powerful animation features through the `matplotlib.animation` module, enabling dynamic visualizations that evolve over time. Here are three examples that showcase the animation capabilities:\n", "\n", "**Animated Line Plot with Real-time Data**" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import matplotlib.animation as animation\n", "from IPython.display import Image\n", "\n", "fig, ax = plt.subplots()\n", "\n", "x = np.arange(0, 2 * np.pi, 0.01)\n", "(line,) = ax.plot(x, np.sin(x))\n", "ax.set_ylim(-1.5, 1.5)\n", "ax.set_title(\"Animated Sine Wave\")\n", "\n", "\n", "def animate(frame):\n", " line.set_ydata(np.sin(x + frame / 10.0))\n", " return (line,)\n", "\n", "\n", "ani = animation.FuncAnimation(fig, animate, frames=10, interval=50, blit=True)\n", "ani.save(\"sine_wave_animation.gif\", writer=\"pillow\", fps=10)\n", "\n", "Image(\"sine_wave_animation.gif\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Animated Bar Chart Race**" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Create sample data for animation\n", "categories = [\"Product A\", \"Product B\", \"Product C\", \"Product D\"]\n", "fig, ax = plt.subplots()\n", "\n", "\n", "def animate_bars(frame):\n", " ax.clear()\n", " # Simulate changing data over time\n", " values = [np.sin(frame / 10 + i) * 50 + 60 for i in range(4)]\n", " colors = plt.cm.viridis(np.linspace(0, 1, 4))\n", "\n", " bars = ax.bar(categories, values, color=colors)\n", " ax.set_ylim(0, 120)\n", " ax.set_title(f\"Sales Performance - Month {frame + 1}\")\n", "\n", " # Add value labels on bars\n", " for bar, value in zip(bars, values, strict=False):\n", " height = bar.get_height()\n", " ax.text(\n", " bar.get_x() + bar.get_width() / 2.0,\n", " height + 2,\n", " f\"{value:.0f}\",\n", " ha=\"center\",\n", " va=\"bottom\",\n", " )\n", "\n", " return bars\n", "\n", "\n", "ani = animation.FuncAnimation(fig, animate_bars, frames=50, interval=100)\n", "ani.save(\"bar_race_animation.gif\", writer=\"pillow\", fps=5)\n", "\n", "Image(\"bar_race_animation.gif\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "These animations demonstrate Matplotlib's versatility for creating engaging dynamic visualizations, from scientific data trends to business dashboards.\n", "\n", "#### Publication-quality output\n", "\n", "Matplotlib excels at creating high-resolution, publication-ready visualizations suitable for academic papers, research reports, and professional presentations. The library provides precise control over figure size, DPI, and output formats (PNG, PDF, SVG, EPS), ensuring your plots meet the strict requirements of scientific journals and publications." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Set publication-quality parameters\n", "plt.rcParams.update({\n", " \"font.size\": 10, # Standard academic paper font size\n", " \"font.family\": \"serif\", # Traditional serif fonts for publications\n", " \"axes.linewidth\": 1.2, # Thicker axes for better print visibility\n", " \"figure.dpi\": 300, # High resolution for sharp display\n", " \"savefig.dpi\": 300, # High resolution for saved files\n", " \"savefig.bbox\": \"tight\" # Remove extra whitespace when saving\n", "})\n", "\n", "fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))\n", "fig.suptitle(\"GitHub User Analysis: Publication Ready\", fontsize=14, fontweight=\"bold\")\n", "\n", "# Subplot 1: Distribution histogram\n", "top_users = new_profile.sort_values(\"followers\", ascending=False)[:50]\n", "ax1.hist(top_users[\"followers\"], bins=15, alpha=0.7, color=\"steelblue\", edgecolor=\"black\")\n", "ax1.set_xlabel(\"Followers Count\")\n", "ax1.set_ylabel(\"Frequency\")\n", "ax1.set_title(\"A) Follower Distribution\")\n", "ax1.grid(True, alpha=0.3)\n", "\n", "# Subplot 2: Correlation scatter\n", "ax2.scatter(top_users[\"followers\"], top_users[\"total_stars\"], alpha=0.6, s=30)\n", "ax2.set_xlabel(\"Followers\")\n", "ax2.set_ylabel(\"Total Stars\")\n", "ax2.set_title(\"B) Followers vs Stars Correlation\")\n", "ax2.grid(True, alpha=0.3)\n", "\n", "# Save as publication-ready formats\n", "plt.tight_layout()\n", "plt.savefig(\"github_analysis.pdf\", format=\"pdf\", bbox_inches=\"tight\")\n", "plt.savefig(\"github_analysis.eps\", format=\"eps\", bbox_inches=\"tight\")\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Cons\n", "\n", "#### Steep learning curve\n", "\n", "Matplotlib's extensive functionality comes with complexity. New users often find the syntax overwhelming, especially when transitioning from point-and-click visualization tools. Understanding the figure-axes hierarchy and object-oriented vs. pyplot interfaces requires significant time investment.\n", "\n", "#### Extensive styling needed for publication-ready common plots\n", "\n", "While Matplotlib supports virtually any chart type, producing visually polished versions of standard plots like histograms, scatter plots, or bar charts requires substantial customization work.\n", "\n", "To make common visualizations suitable for presentations or sharing, you must manually style numerous elements: axis formatting, color schemes, legends, annotations, and layout spacing. Matplotlib's low-level interface provides complete control but assumes users will configure all visual aspects from scratch.\n", "\n", "For example, by default, the heatmap doesn't have the x-axis and y-axis labels and annotations." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "num_features = new_profile.select_dtypes(\"int64\")\n", "correlation = num_features.corr()\n", "\n", "fig, ax = plt.subplots()\n", "im = plt.imshow(correlation, cmap=\"coolwarm\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Creating a readable heatmap in Matplotlib requires several manual steps:\n", "\n", "- Define the visualization layout and color scheme\n", "- Manually position axis ticks and labels\n", "- Loop through each cell to add number annotations with appropriate formatting" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "num_features = new_profile.select_dtypes(\"int64\")\n", "correlation = num_features.corr()\n", "\n", "fig, ax = plt.subplots()\n", "im = plt.imshow(correlation, cmap=\"coolwarm\")\n", "\n", "\n", "ax.set_xticks(np.arange(len(correlation.columns)))\n", "ax.set_yticks(np.arange(len(correlation.columns)))\n", "ax.set_xticklabels(correlation.columns)\n", "ax.set_yticklabels(correlation.columns)\n", "\n", "# Add number annotations manually\n", "for i in range(len(correlation.columns)):\n", " for j in range(len(correlation.columns)):\n", " # Choose text color based on background intensity\n", " ax.text(\n", " j,\n", " i,\n", " f\"{correlation.iloc[i, j]:.2f}\",\n", " ha=\"center\",\n", " va=\"center\",\n", " color=\"black\",\n", " fontweight=\"bold\",\n", " )\n", "\n", "plt.setp(ax.get_xticklabels(), rotation=45, ha=\"right\", rotation_mode=\"anchor\")\n", "plt.tight_layout()\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Creating a basic annotated heatmap shouldn't require this many lines of manual setup and configuration.\n", "\n", "#### Manual statistical processing required\n", "\n", "Unlike higher-level libraries like seaborn, Matplotlib doesn't automatically handle statistical computations or data preprocessing. You must manually perform all data grouping, filtering, aggregations, and statistical calculations before plotting." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import seaborn as sns\n", "from scipy import stats\n", "\n", "# Load penguins dataset for this example\n", "penguins = sns.load_dataset(\"penguins\")\n", "\n", "# Matplotlib requires manual statistical processing for regression analysis\n", "# Filter out missing values manually\n", "penguins_clean = penguins.dropna(subset=[\"bill_length_mm\", \"flipper_length_mm\"])\n", "\n", "# Manual regression calculation (no automatic trend estimation)\n", "x = penguins_clean[\"bill_length_mm\"].values\n", "y = penguins_clean[\"flipper_length_mm\"].values\n", "\n", "# Compute regression statistics manually\n", "slope, intercept, r_value, p_value, std_err = stats.linregress(x, y)\n", "\n", "# Manual confidence interval calculation with proper statistical formula\n", "n = len(x)\n", "x_mean = np.mean(x)\n", "sxx = np.sum((x - x_mean) ** 2)\n", "y_pred = slope * x + intercept\n", "residuals = y - y_pred\n", "mse = np.sum(residuals**2) / (n - 2)\n", "std_error_regression = np.sqrt(mse)\n", "\n", "# Create confidence bands with proper varying width\n", "x_smooth = np.linspace(x.min(), x.max(), 100)\n", "y_smooth = slope * x_smooth + intercept\n", "\n", "# Calculate standard error for each point on the smooth line\n", "se_y = std_error_regression * np.sqrt(1 / n + (x_smooth - x_mean) ** 2 / sxx)\n", "\n", "# Use t-distribution for 95% confidence interval\n", "t_val = stats.t.ppf(0.975, df=n - 2) # 95% confidence\n", "ci = t_val * se_y\n", "\n", "# Plot with manually computed statistics\n", "plt.figure(figsize=(8, 6))\n", "plt.scatter(x, y, alpha=0.6, s=20, color=\"#1f77b4\", label=\"Data points\")\n", "plt.plot(x_smooth, y_smooth, color=\"#1f77b4\", linewidth=2, label=\"Regression line\")\n", "plt.fill_between(\n", " x_smooth,\n", " y_smooth - ci,\n", " y_smooth + ci,\n", " alpha=0.2,\n", " color=\"#1f77b4\",\n", " label=\"95% Confidence interval\",\n", ")\n", "plt.xlabel(\"bill_length_mm\")\n", "plt.ylabel(\"flipper_length_mm\")\n", "plt.title(\"Penguins Regression (Manual statistical processing required)\")\n", "plt.legend()\n", "plt.tight_layout()\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Key Takeaways\n", "\n", "Matplotlib is capable of producing any plot, but creating complex plots often requires more code compared to other libraries.\n", "\n", "## seaborn {#seaborn}\n", "\n", "[seaborn](https://seaborn.pydata.org/) is a Python data visualization library built on top of Matplotlib. It offers a higher-level interface, simplifying the process of creating visually appealing plots.\n", "\n", "### Pros\n", "\n", "#### Reduced code\n", "\n", "seaborn offers a higher-level interface that simplifies plot creation compared to Matplotlib. Since it's designed specifically for pandas DataFrames, you can create attractive visualizations with minimal code.\n", "\n", "For instance, using the same data as before, we can create a nice heatmap without explicitly setting the x and y labels:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import seaborn as sns\n", "\n", "# Load penguins dataset for seaborn examples\n", "penguins = sns.load_dataset(\"penguins\")\n", "\n", "# Use numeric features only for correlation\n", "correlation = num_features.corr()\n", "\n", "sns.heatmap(correlation, annot=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This results in a more visually appealing heatmap without the need for additional configuration.\n", "\n", "#### Statistical plots with automatic processing\n", "\n", "seaborn excels at automatically performing statistical computations and aggregations, eliminating the need for manual data processing. It handles statistical estimation, uncertainty visualization, and data transformations behind the scenes.\n", "\n", "**Automatic statistical estimation with confidence intervals:**\n", "\n", "Unlike the extensive manual statistical processing required in Matplotlib (as shown above), seaborn can create a scatter plot with trend line and confidence interval using just one function call:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Load penguins dataset and automatically estimate trend lines with confidence intervals\n", "sns.lmplot(\n", " data=penguins,\n", " x=\"bill_length_mm\",\n", " y=\"flipper_length_mm\",\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Other examples of seaborn's statistical plots:\n", "\n", "**Automatic distribution fitting and visualization:**" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Automatically computes and overlays histogram, KDE, and rug plots\n", "sns.displot(data=penguins, x=\"flipper_length_mm\", kde=True, rug=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Automatic marginal distribution and correlation computation:**" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Automatically computes scatter plot, marginal histograms, and correlation coefficient\n", "sns.jointplot(data=penguins, x=\"flipper_length_mm\", y=\"body_mass_g\", kind=\"reg\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Automatic pairwise relationships:**" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Automatically creates scatter plots for all numeric pairs with marginal histograms\n", "sns.pairplot(data=penguins, hue=\"species\", palette=\"deep\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Distribution visualization with kernel density:**" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Automatically fits KDE and shows distribution shape\n", "sns.violinplot(data=penguins, x=\"species\", y=\"body_mass_g\", palette=\"coolwarm\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Statistical summary with quartiles:**" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Automatically computes median, quartiles, and outliers\n", "sns.boxplot(data=penguins, x=\"species\", y=\"body_mass_g\", palette=\"coolwarm\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "These examples demonstrate how seaborn handles complex statistical processing automatically, saving significant manual computation and code complexity.\n", "\n", "### Cons\n", "\n", "#### Limited customization compared to Matplotlib\n", "\n", "seaborn excels at creating attractive plots quickly but sacrifices fine-grained control for simplicity. Advanced customizations like precise positioning, custom annotations, or non-standard modifications require dropping to matplotlib's lower level, defeating seaborn's simplicity purpose.\n", "\n", "In the following example, while seaborn creates clean line plots effortlessly, adding highlighted periods and custom annotations requires matplotlib's lower-level interface." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Load flights dataset - contains smooth passenger trends\n", "flights = sns.load_dataset(\"flights\")\n", "\n", "# seaborn creates smooth line plot \n", "sns.lineplot(data=flights, x=\"year\", y=\"passengers\")\n", "\n", "# But adding business annotations requires matplotlib\n", "ax = plt.gca()\n", "\n", "# Highlight jet age introduction period\n", "ax.axvspan(1955, 1958, alpha=0.2, color=\"green\", label=\"Jet Age Introduction\")\n", "\n", "# Add annotation for technical achievement\n", "ax.annotate(\"Jet Engine Impact\", \n", " xy=(1957, 400), \n", " xytext=(1952, 450),\n", " arrowprops={\"arrowstyle\": \"->\", \"color\": \"red\", \"lw\": 2},\n", " fontsize=12, color=\"red\", weight=\"bold\")\n", "\n", "# Custom legend with mixed elements\n", "ax.legend([\"Passenger Trend\", \"Jet Age\"], loc=\"upper left\")\n", "plt.title(\"Air Travel Growth with Historical Context\")\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Limited plot type collection\n", "\n", "While seaborn excels at statistical plots, it lacks the breadth of Matplotlib's visualization options for specialized scientific or custom chart types.\n", "\n", "#### No interactive or animated features\n", "\n", "seaborn is designed exclusively for static statistical visualizations and lacks any built-in support for interactivity or animations.\n", "\n", "### Key Takeaways\n", "\n", "seaborn is a higher-level version of Matplotlib. Even though it does not have a wide collection as Matplotlib, seaborn makes popular plots such as bar plot, box plot, heatmap, etc look pretty in less code.\n", "\n", "## Pygal {#pygal}\n", "\n", "[Pygal](https://github.com/Kozea/pygal) is a lightweight Python library that generates scalable vector graphics (SVG) charts. Built specifically for web applications, Pygal creates interactive visualizations with minimal dependencies and extremely fast rendering.\n", "\n", "### Pros\n", "\n", "#### SVG vector graphics with perfect scaling\n", "\n", "Pygal generates pure SVG output that scales perfectly across all devices and screen sizes. Unlike bitmap images from other libraries, SVG charts maintain crisp quality at any zoom level.\n", "\n", "This makes Pygal ideal for responsive web applications where charts need to look sharp on both mobile devices and large desktop monitors:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import pygal\n", "\n", "# Create a bar chart showing top GitHub users by followers\n", "top_followers = new_profile.sort_values(by=\"followers\", ascending=False)[:10]\n", "\n", "bar_chart = pygal.Bar(\n", " title=\"Top 10 GitHub Users by Followers\",\n", " x_title=\"Users\",\n", " y_title=\"Followers\"\n", ")\n", "bar_chart.x_labels = top_followers[\"user_name\"].tolist()\n", "bar_chart.add(\"Followers\", top_followers[\"followers\"].tolist())\n", "\n", "# Save chart as SVG file\n", "bar_chart.render_to_file(\"github_top_users.svg\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The resulting SVG can be embedded directly into HTML without additional dependencies or image files.\n", "\n", "#### Built-in interactivity with hover tooltips\n", "\n", "Every Pygal chart includes hover tooltips by default through native SVG interactivity. Users can explore data points without requiring additional JavaScript libraries, frameworks, or configuration.\n", "\n", "The bar chart above automatically displays precise follower counts when you hover over each bar, providing instant data exploration without any setup required.\n", "\n", "To see the chart in a browser, we can use the following code:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "bar_chart.render_in_browser()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "To see Pygal's interactivity in Jupyter notebooks, include the following JavaScript dependencies:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# For interactive display in notebooks, we need to wrap the SVG with JavaScript\n", "from IPython.display import HTML, display\n", "\n", "\n", "def display_pygal_chart(chart):\n", " \"\"\"Display a Pygal chart with full interactivity in Jupyter notebooks\"\"\"\n", " html_template = \"\"\"\n", " \n", " \n", "
\n", " \n", " \n", " \n", " \n", "