Visualization Platforms

In this course, you get to choose a platform to work with through the semester. We recommend picking one of:

  • Python / matplotlib (and Seaborn)
  • Python / altair
  • R / ggplot2
  • JavaScript / D3.js
  • JavaScript / ObservableJS

All of these can be incorporated in a Quarto setup for easy authoring and generation of the resulting pages and reports in a variety of formats. To help with this, we provide an example Quarto file that demonstrates how to access each of the recommended platforms from within Quarto. You will still need to install all relevant libraries on your own to make the example document work.

The source code below will render to produce this example.

title: "Example of Quarto and different platforms"
format: html
engine: knitr

## Dataset used

In this document, we will show visualizations of the [Palmer Penguins dataset]( We will be using the CSV version stored at .

## Visualization Example

In each platform, we will make a scatterplot of `bill_length_mm` vs. `bill_depth_mm` colored by species.

## Python / matplotlib

from matplotlib import pyplot
import pandas

palmerpenguins = pandas.read_csv("")
palmerpenguins["species"] = palmerpenguins["species"].astype("category")
pyplot.scatter("bill_length_mm", "bill_depth_mm", c=palmerpenguins["species"], data=palmerpenguins)

## Python / altair

import altair
import pandas

palmerpenguins = pandas.read_csv("")

  x="bill_length_mm", y="bill_depth_mm", color="species"

## R / ggplot2


palmerpenguins = read_csv("")

ggplot(palmerpenguins, aes(bill_length_mm, bill_depth_mm, color=species)) +

## Preparation for both the JavaScript options

Both raw D3.js and ObservableJS will need the exact same declarations to get access to the D3 library and to load the dataset we want, so for now we extract that declaration to a separate code block.

d3 = require("d3@7")
palmerpenguins = d3.csv("")

## JS / d3.js

::: {#svg}

width = 300
height = 300
margin_top = 30
margin_bottom = 30
margin_left = 30
margin_right = 30
svg ="#svg")
    .attr("width", width+margin_left+margin_right)
    .attr("height", height+margin_top+margin_bottom)
    .attr("transform", `translate(${margin_left},${margin_top})`)
x = d3.scaleLinear()
  .domain(d3.extent(palmerpenguins, d => parseFloat(d.bill_length_mm)))
  .range([0, width])
svg.append("g").attr("transform", `translate(0, ${height})`)
y = d3.scaleLinear()
  .domain(d3.extent(palmerpenguins, d => parseFloat(d.bill_depth_mm)))
  .range([height,0]) // <- because screen coordinates go down, so reverse scale
c = d3.scaleOrdinal()
  .domain(["Adelie", "Chinstrap", "Gentoo"])
  .range(["#ffff00", "#ff00ff", "#00ffff"])
     .attr("cx", d => x(parseFloat(d.bill_length_mm)))
     .attr("cy", d => y(parseFloat(d.bill_depth_mm)))
     .attr("r", 5)
     .style("fill", d => c(d.species))

## JS / ObservableJS

```{ojs}, {
  x: "bill_length_mm",
  y: "bill_depth_mm",
  stroke: "species",
  fill: "species"