Skip to content

Mark Filter Examples

Observable Plot filters allow you to conditionally display data points on marks. Filters are applied at the mark level, making it easy to show or hide specific records based on conditions.

Basic Boolean Field Filter

Filter marks by a boolean column to show only active or matching records:

View Source
type: scatter
x: sales
y: profit
data:
  source: '[{"name": "Product A", "sales": 1200, "profit": 300, "active": true}, {"name": "Product B", "sales": 800, "profit": -50, "active": false}, {"name": "Product C", "sales": 2100, "profit": 550, "active": true}, {"name": "Product D", "sales": 500, "profit": 50, "active": false}, {"name": "Product E", "sales": 1800, "profit": 400, "active": true}]'
marks:
  - type: dot
    configuration:
      x: sales
      y: profit
      fill: active
      filter: active
      title: '(d) => `${d.name}: $${d.sales}k sales, $${d.profit}k profit`'

This filter displays only active products. Notice how only 3 points appear (Products A, C, and E).

Numeric Comparison Filter

Use comparison operators to filter by numeric thresholds:

View Source
type: bar
x: month
y: revenue
data:
  source: '[{"month": "Jan", "revenue": 1200, "target": 1500}, {"month": "Feb", "revenue": 2100, "target": 1500}, {"month": "Mar", "revenue": 1100, "target": 1500}, {"month": "Apr", "revenue": 2400, "target": 1500}, {"month": "May", "revenue": 900, "target": 1500}]'
marks:
  - type: bar
    configuration:
      x: month
      y: revenue
      fill: "#4285F4"
      filter: "revenue > 1000"
      title: '(d) => `${d.month}: $${d.revenue}k (beats $${d.target}k target)`'

This filter shows only months where revenue exceeded the target of $1,500k.

String Equality Filter

Filter by categorical values using equality comparison:

View Source
type: scatter
x: experience
y: salary
data:
  source: '[{"name": "Alice", "department": "Engineering", "experience": 5, "salary": 120}, {"name": "Bob", "department": "Sales", "experience": 3, "salary": 80}, {"name": "Carol", "department": "Engineering", "experience": 7, "salary": 140}, {"name": "David", "department": "HR", "experience": 4, "salary": 75}, {"name": "Eve", "department": "Engineering", "experience": 6, "salary": 130}, {"name": "Frank", "department": "Sales", "experience": 5, "salary": 95}]'
marks:
  - type: dot
    configuration:
      x: experience
      y: salary
      fill: department
      r: 4
      filter: 'department === "Engineering"'
      title: '(d) => `${d.name}: ${d.experience} years, $${d.salary}k`'

Shows only Engineering department employees.

Arrow Function Filter

Use arrow functions for complex filtering logic:

View Source
type: scatter
x: x
y: y
data:
  source: |
	  [{"x": 10, "y": 20, "category": "A"}, {"x": 15, "y": 500, "category": "B"}, {"x": 5, "y": 12, "category": "A"}, {"x": 20, "y": 30, "category": "C"}, {"x": 8, "y": 600, "category": "B"}, {"x": 12, "y": 25, "category": "A"}]
marks:
  - type: dot
    configuration:
      x: x
      y: y
      fill: "#EA4335"
      filter: "(d) => d.y < 100"
      title: '(d) => `Outlier: (${d.x}, ${d.y})`'

This filter removes outliers where y-values exceed 100.

Multiple Marks with Different Filters

Layer marks with different filters to highlight specific data:

View Source
type: scatter
x: value
y: growth
data:
  source: '[{"label": "Product A", "value": 100, "growth": 0.15, "highlight": true}, {"label": "Product B", "value": 80, "growth": -0.05, "highlight": false}, {"label": "Product C", "value": 150, "growth": 0.25, "highlight": true}, {"label": "Product D", "value": 60, "growth": 0.05, "highlight": false}, {"label": "Product E", "value": 120, "growth": 0.20, "highlight": true}]'
marks:
  - type: dot
    configuration:
      x: value
      y: growth
      fill: "#CCCCCC"
      r: 3
      opacity: 0.5
      title: '(d) => `${d.label}: $${d.value}m, ${(d.growth * 100).toFixed(1)}% growth`'
  - type: dot
    configuration:
      x: value
      y: growth
      fill: "#4285F4"
      r: 5
      stroke: "#1967D2"
      strokeWidth: 2
      filter: highlight
      title: '(d) => `${d.label}: Highlighted`'

Background layer shows all products as small gray dots, highlighted layer shows top products as larger blue dots.

Handling Missing/NULL Values

Filter with comparison operators to exclude nulls or specific values:

View Source
type: bar
x: region
y: sales
data:
  source: '[{"region": "North", "sales": 1200}, {"region": "South", "sales": null}, {"region": "East", "sales": 1800}, {"region": "West", "sales": null}, {"region": "Central", "sales": 950}]'
marks:
  - type: bar
    configuration:
      x: region
      y: sales
      fill: "#34A853"
      filter: 'sales !== null'
      title: '(d) => `${d.region}: $${d.sales || "N/A"}k`'

Only regions with valid sales data are displayed.

Percentage Threshold Filter

Filter based on calculated percentages:

View Source
title: Percentage Threshold Filter
type: scatter
x: totalSpend
y: ratio
data:
  source: '[{"customer": "Acme Corp", "totalSpend": 50000, "onlineSpend": 10000}, {"customer": "TechCorp", "totalSpend": 80000, "onlineSpend": 25000}, {"customer": "RetailCo", "totalSpend": 30000, "onlineSpend": 2000}, {"customer": "GlobalInc", "totalSpend": 120000, "onlineSpend": 36000}, {"customer": "StartupXYZ", "totalSpend": 15000, "onlineSpend": 13000}]'
marks:
  - type: dot
    configuration:
      x: totalSpend
      y: '(d) => (d.onlineSpend / d.totalSpend * 100)'
      fill: '(d) => (d.onlineSpend / d.totalSpend > 0.3 ? "#EA4335" : "#34A853")'
      r: 5
      filter: '(d) => (d.onlineSpend / d.totalSpend > 0.25)'
      title: '(d) => `${d.customer}: ${((d.onlineSpend / d.totalSpend) * 100).toFixed(1)}% online`'

Shows only customers with >25% online spending ratio.

Filter Best Practices

  1. Use boolean fields for simple on/off filtering - filter: "active"
  2. Use comparisons for numeric thresholds - filter: "sales > 1000"
  3. Use string equality for categories - filter: 'region === "North"'
  4. Use arrow functions for complex logic - filter: "(d) => d.value > threshold && d.category === 'A'"
  5. Apply filters at the mark level - Different marks can have different filters
  6. Combine filters with visual channels - Use fill/stroke colors to distinguish filtered marks

Performance Considerations

  • Filters are applied client-side during rendering
  • Large datasets (>10,000 rows) may need preprocessing before visualization
  • Consider using data transformations for complex filtering logic
  • Multiple filtered marks on the same chart increase rendering time

Released under the MIT License. Built by Boundary Lab.