Skip to content

punchcard

Mojo function 🡭

punchcard

fn def punchcard(df: DataFrame, x: String, y: String, sizes: String, scale: Float64 = 10, theme: Theme = Theme(WHITE, Color(UInt8(30), UInt8(100), UInt8(180), UInt8(255)), Color(UInt8(80), UInt8(80), UInt8(80), UInt8(255)), Color(UInt8(225), UInt8(225), UInt8(225), UInt8(255)), Color(UInt8(40), UInt8(40), UInt8(40), UInt8(255)), SIMD(12), SIMD(3.5), SIMD(2), Int(60), Int(20), Int(20), Int(50), True, False, False, Color(UInt8(240), UInt8(240), UInt8(240), UInt8(255)), Int(3), Color(UInt8(60), UInt8(110), UInt8(200), UInt8(255)), Color(UInt8(235), UInt8(235), UInt8(235), UInt8(255)), Color(UInt8(220), UInt8(90), UInt8(40), UInt8(255)), ColorRamp(), ColorPalette(), SIMD(3), SIMD(15), True, SIMD(1), Int(0), False, Color(UInt8(200), UInt8(60), UInt8(60), UInt8(255)), Color(UInt8(224), UInt8(224), UInt8(224), UInt8(255)), Color(UInt8(120), UInt8(120), UInt8(120), UInt8(255)), Color(UInt8(100), UInt8(100), UInt8(100), UInt8(255)), Color(UInt8(230), UInt8(230), UInt8(230), UInt8(255)), Color(UInt8(255), UInt8(255), UInt8(255), UInt8(255)), UInt8(90), UInt8(160), False, False, SIMD(0), SIMD(18), SIMD(14), Color(UInt8(110), UInt8(110), UInt8(110), UInt8(255)), SIMD(14), Color(UInt8(150), UInt8(150), UInt8(150), UInt8(255)), Color(UInt8(224), UInt8(236), UInt8(246), UInt8(200)), Color(UInt8(255), UInt8(255), UInt8(255), UInt8(255)), True, False, False, True, AxisPosition.EDGE, AxisPosition.EDGE, String("sans-serif"), True, UInt8(90), Int(5), Int(4), Int(130), Int(14), Int(8), Int(14), Int(100), Int(8), SIMD(4), OutputFormat.SVG, Tooltips.AUTO, Missing.DRAW, String("(missing)"), Int(1000), False, LineStyle.SOLID, SIMD(1.5), LineStyle.SOLID, LegendPosition.RIGHT, XAxisLabelRotation.AUTO, TickFormat.AUTO, TickFormat.AUTO), width: Int = Int(640), height: Int = Int(420), title: String = "", subtitle: String = "", x_title: String = "", y_title: String = "") -> Chart[Punchcard]

punchcard() over named columns of a dataframe_mojo DataFrame (#743). Each argument names a column instead of holding the values.

See Plot.encode_frame() for how columns are read and what a column with missing values does.

Args:

  • df (DataFrame): The frame to read.
  • x (String): The string column for this channel.
  • y (String): The string column for this channel.
  • sizes (String): The numeric column for this channel.
  • scale (Float64): See the list overload.
  • theme (Theme): See the list overload.
  • width (Int): See the list overload.
  • height (Int): See the list overload.
  • title (String): See the list overload.
  • subtitle (String): See the list overload.
  • x_title (String): See the list overload.
  • y_title (String): See the list overload.

Returns:

Chart[Punchcard]: The finished chart – unrendered.

Raises:

Error: A named column is missing, has the wrong dtype for its channel, or has missing values.

fn def punchcard[dtype: DType](x: List[String], y: List[String], sizes: List[Scalar[dtype]], scale: Float64 = 10, theme: Theme = Theme(WHITE, Color(UInt8(30), UInt8(100), UInt8(180), UInt8(255)), Color(UInt8(80), UInt8(80), UInt8(80), UInt8(255)), Color(UInt8(225), UInt8(225), UInt8(225), UInt8(255)), Color(UInt8(40), UInt8(40), UInt8(40), UInt8(255)), SIMD(12), SIMD(3.5), SIMD(2), Int(60), Int(20), Int(20), Int(50), True, False, False, Color(UInt8(240), UInt8(240), UInt8(240), UInt8(255)), Int(3), Color(UInt8(60), UInt8(110), UInt8(200), UInt8(255)), Color(UInt8(235), UInt8(235), UInt8(235), UInt8(255)), Color(UInt8(220), UInt8(90), UInt8(40), UInt8(255)), ColorRamp(), ColorPalette(), SIMD(3), SIMD(15), True, SIMD(1), Int(0), False, Color(UInt8(200), UInt8(60), UInt8(60), UInt8(255)), Color(UInt8(224), UInt8(224), UInt8(224), UInt8(255)), Color(UInt8(120), UInt8(120), UInt8(120), UInt8(255)), Color(UInt8(100), UInt8(100), UInt8(100), UInt8(255)), Color(UInt8(230), UInt8(230), UInt8(230), UInt8(255)), Color(UInt8(255), UInt8(255), UInt8(255), UInt8(255)), UInt8(90), UInt8(160), False, False, SIMD(0), SIMD(18), SIMD(14), Color(UInt8(110), UInt8(110), UInt8(110), UInt8(255)), SIMD(14), Color(UInt8(150), UInt8(150), UInt8(150), UInt8(255)), Color(UInt8(224), UInt8(236), UInt8(246), UInt8(200)), Color(UInt8(255), UInt8(255), UInt8(255), UInt8(255)), True, False, False, True, AxisPosition.EDGE, AxisPosition.EDGE, String("sans-serif"), True, UInt8(90), Int(5), Int(4), Int(130), Int(14), Int(8), Int(14), Int(100), Int(8), SIMD(4), OutputFormat.SVG, Tooltips.AUTO, Missing.DRAW, String("(missing)"), Int(1000), False, LineStyle.SOLID, SIMD(1.5), LineStyle.SOLID, LegendPosition.RIGHT, XAxisLabelRotation.AUTO, TickFormat.AUTO, TickFormat.AUTO), width: Int = Int(640), height: Int = Int(420), title: String = "", subtitle: String = "", x_title: String = "", y_title: String = "") -> Chart[Punchcard]

A punchcard, in the style of GitHub’s old commit-activity graph: a scatter plot on a categorical grid where bubble size encodes a value at each (x, y) cell, for spotting when activity clusters across two categorical dimensions such as day and hour.

Mark.PUNCHCARD: a scatter plot on a categorical grid where bubble size (sizes[i] / scale) encodes a third variable, GitHub-style. See _render_punchcard.

Example:

from dataviz import punchcard
from dataviz import save

def main() raises:
    var day_names: List[String] = [
        "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun",
    ]
    var hour_names: List[String] = [
        "6am", "9am", "12pm", "3pm", "6pm", "9pm",
    ]
    # Illustrative station entries (thousands): commute peaks dominate
    # weekdays, while weekend travel shifts toward midday and evening.
    var entries_by_day: List[List[Int]] = [
        [38, 72, 31, 35, 68, 24],
        [41, 78, 33, 37, 73, 25],
        [43, 81, 35, 39, 76, 27],
        [42, 79, 34, 38, 74, 28],
        [39, 70, 36, 42, 71, 39],
        [14, 25, 43, 51, 57, 45],
        [11, 21, 38, 47, 52, 34],
    ]

    var x = List[String]()
    var y = List[String]()
    var counts = List[Int]()
    for day_i in range(len(day_names)):
        for hour_i in range(len(hour_names)):
            x.append(day_names[day_i])
            y.append(hour_names[hour_i])
            counts.append(entries_by_day[day_i][hour_i])

    var c = punchcard(
        x,
        y,
        counts,
        title="Illustrative Transit Entries by Day and Hour",
        x_title="Day",
        y_title="Hour",
    )
    save(c, "docs/src/examples/out_punchcard.svg")

Parameters:

  • dtype (DType)

Args:

  • x (List[String]): Each bubble’s column category, one entry per row of data.
  • y (List[String]): Each bubble’s row category, one entry per row of data.
  • sizes (List[Scalar[dtype]]): Each bubble’s raw size value, divided by scale before drawing.
  • scale (Float64): Divides sizes before drawing – raise it to shrink bubbles that would otherwise overlap.
  • theme (Theme): Full styling knobs beyond this function’s own parameters (colors, margins, fonts, gridlines, …) – see Theme’s docstring.
  • width (Int): Pixel width of the returned Plot (.size()).
  • height (Int): Pixel height of the returned Plot (.size()).
  • title (String): The chart’s title, shown above the plot.
  • subtitle (String): A secondary line shown under the title.
  • x_title (String): The x-axis caption.
  • y_title (String): The y-axis caption.

Returns:

Chart[Punchcard]: The finished chart – unrendered. Call save(plot, path) to write it (any of .svg/.png/.bmp), or render(plot)/render_svg(plot) for the explicit two-step.

Raises: