Marketplace

data-visualization

Master advanced declarative visualization with HoloViews. Use this skill when creating complex multi-dimensional visualizations, composing overlays and layouts, implementing interactive streams and selection, building network or hierarchical visualizations, or exploring data with dynamic maps and faceted displays.

$ Installer

git clone https://github.com/cdcore09/holoviz-claude /tmp/holoviz-claude && cp -r /tmp/holoviz-claude/plugins/holoviz-expert/skills/data-visualization ~/.claude/skills/holoviz-claude

// tip: Run this command in your terminal to install the skill


name: data-visualization description: Master advanced declarative visualization with HoloViews. Use this skill when creating complex multi-dimensional visualizations, composing overlays and layouts, implementing interactive streams and selection, building network or hierarchical visualizations, or exploring data with dynamic maps and faceted displays. compatibility: Requires holoviews >= 1.18.0, pandas >= 1.0.0, numpy >= 1.15.0, bokeh >= 3.0.0, networkx >= 2.0.0 (for network visualizations)

Data Visualization Skill

Overview

Master advanced declarative visualization with HoloViews and composition patterns. This skill covers sophisticated visualization techniques for complex data exploration and presentation.

Dependencies

  • holoviews >= 1.18.0
  • pandas >= 1.0.0
  • numpy >= 1.15.0
  • bokeh >= 3.0.0
  • networkx >= 2.0.0 (for network visualizations)

Core Capabilities

1. Advanced Element Composition

HoloViews allows sophisticated composition of visualization elements:

import holoviews as hv
from holoviews import opts
import pandas as pd
import numpy as np

# Create overlaid elements
curve = hv.Curve(df, 'x', 'y', label='Measured')
scatter = hv.Scatter(df_with_noise, 'x', 'y', label='Noisy')
overlay = curve * scatter  # Multiplication overlays

# Create layouts
col_layout = hv.Column(plot1, plot2, plot3)
row_layout = hv.Row(plot1, plot2, plot3)
grid_layout = hv.GridMatrix(data_dict)

# Faceted displays
faceted = hv.Curve(df, 'date', 'value').facet('category')

# Nested layouts
complex_layout = hv.Column(
    hv.Row(plot1, plot2),
    hv.Row(plot3, plot4),
    hv.Row(plot5, plot6)
)

2. Interactive Streams and Selection

Create responsive visualizations with interactive selection:

from holoviews import streams

# Selection stream
range_stream = streams.RangeXY()
scatter = hv.Scatter(df, 'x', 'y').opts(tools=['box_select'])

@hv.transform
def selected_data(data):
    if range_stream.selection:
        x0, x1 = range_stream.selection[0], range_stream.selection[1]
        y0, y1 = range_stream.selection[2], range_stream.selection[3]
        mask = (data['x'] >= x0) & (data['x'] <= x1) & \
               (data['y'] >= y0) & (data['y'] <= y1)
        return data[mask]
    return data

histogram = selected_data.to(hv.Histogram)
scatter_with_hist = scatter + histogram

3. Dynamic Maps for Responsive Visualization

# Dynamic updating based on parameters
from holoviews import DynamicMap, streams

def plot_by_category(category):
    data = df[df['category'] == category]
    return hv.Scatter(data, 'x', 'y', title=f'Category: {category}')

category_stream = streams.Stream.define('category', category='A')
dmap = DynamicMap(plot_by_category, streams=[category_stream])

# Parameterized dynamic map
def plot_with_params(threshold=0.5):
    filtered = df[df['value'] > threshold]
    return hv.Scatter(filtered, 'x', 'y')

dmap_param = DynamicMap(
    plot_with_params,
    streams=[streams.Stream.define('threshold', threshold=0.5)]
)

4. Network and Hierarchical Visualizations

import networkx as nx

# Network graph
G = nx.karate_club_graph()
pos = nx.spring_layout(G)
edges = [(u, v) for u, v in G.edges()]
nodes = list(G.nodes())

# Create nodes and edges visualization
edge_plot = hv.Segments(edges, kdims=['source', 'target'])
node_plot = hv.Scatter(
    [(pos[n][0], pos[n][1], n) for n in nodes],
    kdims=['x', 'y', 'node']
)
network = (edge_plot * node_plot).opts(
    opts.Scatter(size=100, color='red'),
    opts.Segments(color='gray')
)

# Treemap for hierarchical data
treemap = hv.TreeMap(
    hierarchical_data,
    label='Organization'
).opts(tools=['hover'])

5. Statistical and Aggregate Visualizations

# Aggregate with Rasterize
from holoviews.operation import datashader as dshade

# Box plot for comparison
box_plot = hv.BoxWhisker(df, kdims=['category'], vdims=['value'])

# Violin plot
violin = hv.Violin(df, kdims=['category'], vdims=['value'])

# Distribution comparison
dist_layout = hv.Column(*[
    df[df['category'] == cat]['value'].hvplot.hist()
    for cat in df['category'].unique()
])

6. Multi-Dimensional Data Exploration

# HoloMap for multi-dimensional data
def plot_by_params(category, metric):
    data = df[(df['category'] == category) & (df['metric'] == metric)]
    return hv.Scatter(data, 'x', 'y', title=f'{category} - {metric}')

hmap = hv.HoloMap(
    {(cat, met): plot_by_params(cat, met)
     for cat in categories for met in metrics},
    kdims=['Category', 'Metric']
)

# NdLayout for structured multi-dimensional display
ndlayout = hv.NdLayout({
    (cat, met): plot_by_params(cat, met)
    for cat in categories for met in metrics
}, kdims=['Category', 'Metric'])

Advanced Styling and Theming

1. Global Options

# Set global defaults
opts.defaults(
    opts.Curve(width=700, height=400, responsive=True),
    opts.Scatter(size=100, alpha=0.5),
    opts.Image(cmap='viridis')
)

# Apply to multiple elements
styled_plots = [
    plot.opts(
        title='Styled Plot',
        xlabel='X Axis',
        ylabel='Y Axis',
        toolbar='right',
        active_tools=['pan', 'wheel_zoom']
    )
    for plot in plots
]

2. Custom Styling

# Element-specific styling
plot = hv.Scatter(df, 'x', 'y').opts(
    color=hv.dim('category').categorize({
        'A': '#FF6B6B',
        'B': '#4ECDC4',
        'C': '#45B7D1'
    }),
    size=hv.dim('value').norm(min=10, max=100),
    selection_color='red',
    nonselection_alpha=0.1
)

# Conditional formatting
plot.opts(
    color=hv.dim('status').categorize({
        'good': 'green',
        'warning': 'orange',
        'error': 'red'
    })
)

3. Interactive Legends and Annotations

# Annotations
annotated_plot = hv.Curve(df, 'x', 'y')
annotations = [
    hv.Text(x, y, text, fontsize=10)
    for x, y, text in annotations_data
]
plot_with_annotations = annotated_plot * hv.Overlay(annotations)

# Custom legend
plot = hv.Overlay([
    hv.Curve(df1, label='Series 1'),
    hv.Curve(df2, label='Series 2'),
    hv.Curve(df3, label='Series 3')
]).opts(
    legend_position='top_left',
    legend_muted_alpha=0.2
)

Best Practices

1. Performance with Large Datasets

# Use rasterize for dense plots
from holoviews.operation import rasterize

large_scatter = hv.Scatter(large_df, 'x', 'y')
rasterized = rasterize(large_scatter, pixel_ratio=2)

# Use aggregation
aggregated = df.groupby('category')['value'].mean().hvplot.bar()

# Use datashader for massive datasets (>100M points)
from holoviews.operation.datashader import datashade
dshaded = datashade(large_scatter)

2. Responsive and Accessible Plots

# Responsive sizing
plot = hv.Scatter(df, 'x', 'y').opts(
    responsive=True,
    sizing_mode='stretch_width'
)

# Accessible color palettes
plot = hv.Scatter(df, 'x', 'y').opts(
    color=hv.dim('value').norm(),
    cmap='cet_gray_r'  # Perceptually uniform
)

# Clear labels
plot.opts(
    title='Clear Title',
    xlabel='Independent Variable (units)',
    ylabel='Dependent Variable (units)',
    fontsize=14
)

3. Composition Patterns

# Avoid deep nesting
# Bad: ((a + (b + (c + d)))
# Good: a + b + c + d

# Create helper functions
def create_comparison_layout(data_dict):
    plots = [hv.Scatter(v, label=k) for k, v in data_dict.items()]
    return hv.Column(*plots)

# Modular composition
sidebar = hv.Column(title_text, filter_widget)
main = hv.Row(plot1, plot2)
app = hv.Column(sidebar, main)

Common Patterns

Pattern 1: Linked Brushing

def create_linked_views(df):
    scatter = hv.Scatter(df, 'x', 'y').opts(tools=['box_select'])

    def get_histogram(selection):
        if selection:
            selected_df = df.iloc[selection.event.inds]
        else:
            selected_df = df
        return hv.Histogram(selected_df['x'], bins=20)

    return scatter + DynamicMap(get_histogram, streams=[streams.Selection1D()])

Pattern 2: Multi-Scale Exploration

def create_zoomable_view(df):
    scatter = hv.Scatter(df, 'x', 'y')
    zoomed = scatter.opts(
        xlim=(0, 10),
        ylim=(0, 10)
    )
    return hv.Column(scatter, zoomed)

Pattern 3: Faceted Analysis

def create_faceted_analysis(df, facet_col):
    return df.hvplot.scatter(
        x='x',
        y='y',
        by=facet_col,
        subplots=True,
        layout='vertical'
    )

Integration with Other HoloViz Tools

  • Panel: Embed interactive HoloViews in dashboards
  • hvPlot: Quick plotting that produces HoloViews objects
  • Datashader: Efficient rendering for large data
  • Param: Parameter-driven dynamic visualizations
  • GeoViews: Geographic data visualization building on HoloViews

Common Use Cases

  1. Exploratory Data Analysis: Multi-dimensional data exploration
  2. Dashboard Metrics: KPI and metric visualization
  3. Scientific Visualization: Complex data relationships
  4. Financial Analysis: Time series and correlation analysis
  5. Report Generation: Publication-quality visualizations
  6. Real-time Monitoring: Streaming data visualization

Troubleshooting

Issue: Plot Elements Overlapping

  • Use layouts instead of overlays for clarity
  • Adjust alpha transparency
  • Use complementary colors

Issue: Slow Interactive Performance

  • Use rasterize for dense plots
  • Reduce data size with aggregation
  • Use datashader for massive datasets
  • Cache plot computations

Issue: Unclear Data Relationships

  • Use multiple linked views
  • Apply faceting for categorical comparison
  • Use color and size encoding
  • Add annotations and reference lines

Resources