### Install Detroit with pip Source: https://github.com/bourbonut/detroit/blob/main/docs/source/index.rst Installs the latest stable version of the Detroit library from PyPI using pip. This is the standard method for installing Python packages. ```shell pip install detroit ``` -------------------------------- ### Load and Prepare Data using Polars Source: https://github.com/bourbonut/detroit/blob/main/docs/source/bar.rst Loads alphabet frequency data from a CSV URL using Polars and sorts it by frequency in descending order. This step prepares the data for visualization. ```python # Source : https://observablehq.com/@d3/bar-chart/2 import detroit as d3 import polars as pl # for data manipulation from collections import namedtuple URL = "https://static.observableusercontent.com/files/09f63bb9ff086fef80717e2ea8c974f918a996d2bfa3d8773d3ae12753942c002d0dfab833d7bee1e0c9cd358cd3578c1cd0f9435595e76901508adc3964bbdc?response-content-disposition=attachment%3Bfilename*%3DUTF-8%27%27alphabet.csv" Margin = namedtuple("Margin", ["top", "right", "bottom", "left"]) alphabet = pl.read_csv(URL).sort(by="frequency", descending=True) ``` -------------------------------- ### Create an SVG element with Detroit Source: https://github.com/bourbonut/detroit/blob/main/docs/source/index.rst Shows how to create a root SVG element using the `d3.create` function in the Detroit library. This is the starting point for building SVG-based visualizations. ```python import detroit as d3 svg = d3.create("svg") ``` -------------------------------- ### Load Car Data with Polars Source: https://github.com/bourbonut/detroit/blob/main/docs/source/scatter.rst Loads car dataset from a URL into a Polars DataFrame with a predefined schema. Requires detroit, polars, and collections.namedtuple. ```python # Source : https://observablehq.com/@d3/brushable-scatterplot import detroit as d3 import polars as pl # for data manipulation from collections import namedtuple URL = "https://static.observableusercontent.com/files/53c407ee531bab128477148c9e28c49dd06bf83a93ae317e58dbb9fc819db0d4f6c4fb9646fa2fe20faad76addee20cfc360eab2362eeaec3340a5e4655b9996?response-content-disposition=attachment%3Bfilename*%3DUTF-8%27%27cars-2.csv" Margin = namedtuple("Margin", ["top", "right", "bottom", "left"]) schema = pl.Schema( { "Name": pl.String, "Miles_per_Gallon": pl.Float32, "Cylinders": pl.Int32, "Displacement": pl.Float32, "Horsepower": pl.Int32, "Weight_in_lbs": pl.Int32, "Acceleration": pl.Float32, "Year": pl.Int32, "Origin": pl.String, } ) cars = pl.read_csv(URL, schema=schema) ``` -------------------------------- ### Install Detroit using pip Source: https://github.com/bourbonut/detroit/blob/main/README.md This command installs the Detroit Python package using pip. Ensure you have Python and pip installed on your system. ```sh pip install detroit ``` -------------------------------- ### Load Data for Pie Chart (Python) Source: https://github.com/bourbonut/detroit/blob/main/docs/source/pie.rst Loads population data by age from a CSV file using the polars library. This data is then used to generate a pie chart. Dependencies include polars and detroit. ```python # Source : https://observablehq.com/@d3/donut-chart/2 import polars as pl # for data manipulation import detroit as d3 URL = "https://static.observableusercontent.com/files/bee673b386dd058ab8d2cf353acbedc6aa01ebd1e6f63e2a9ab1b4273c7e6efd1eeea526345e4be7f0012d5db3ec743ef39ad9e6a043c196670bf9658cb02e79?response-content-disposition=attachment%3Bfilename*%3DUTF-8%27%27population-by-age.csv" data = pl.read_csv(URL) ``` -------------------------------- ### Save SVG Chart to File Source: https://github.com/bourbonut/detroit/blob/main/docs/source/bar.rst Writes the generated SVG chart to a file named 'bar.svg'. This allows the visualization to be saved and shared. ```python with open("bar.svg", "w") as file: file.write(str(svg)) ``` -------------------------------- ### Load Penguin Data with Polars Source: https://github.com/bourbonut/detroit/blob/main/docs/source/complex_charts/scatter_matrix.rst Loads the penguin dataset from a URL into a Polars DataFrame and converts it to a list of dictionaries. Requires Polars and standard Python libraries. ```python # Source: https://observablehq.com/@d3/brushable-scatterplot-matrix import detroit as d3 import polars as pl from operator import itemgetter, iadd from math import isnan, exp from itertools import product, accumulate URL = "https://static.observableusercontent.com/files/715db1223e067f00500780077febc6cebbdd90c151d3d78317c802732252052ab0e367039872ab9c77d6ef99e5f55a0724b35ddc898a1c99cb14c31a379af80a?response-content-disposition=attachment%3Bfilename*%3DUTF-8%27%27penguins.csv" # Load data penguins = pl.read_csv(URL) data = penguins.to_dicts() ``` -------------------------------- ### Draw a line chart with axes using Detroit Source: https://github.com/bourbonut/detroit/blob/main/docs/source/index.rst Provides a complete example of drawing a line chart with X and Y axes using the Detroit library. It includes data preparation, scale definition, axis generation, and path creation for the line. ```python data = [ {"quantity": 0, "ratio": 50}, {"quantity": 1, "ratio": 12}, {"quantity": 2, "ratio": 89}, {"quantity": 3, "ratio": 87}, {"quantity": 4, "ratio": 62}, {"quantity": 5, "ratio": 8}, {"quantity": 6, "ratio": 10}, {"quantity": 7, "ratio": 33}, {"quantity": 8, "ratio": 8}, {"quantity": 9, "ratio": 23}, {"quantity": 10, "ratio": 10}, ] # Add x axis ( svg.append("g") .attr("class", "x-axis") .attr("transform", f"translate(0, {height - margin_bottom})") .call(d3.axis_bottom(x)) ) # Add y axis ( svg.append("g") .attr("class", "y-axis") .attr("transform", f"translate({margin_left}, 0)") .call(d3.axis_left(y)) ) line = d3.line().x(lambda d: x(d["quantity"])).y(lambda d: y(d["ratio"])) # noqa # Add line path ( svg.append("path") .attr("fill", "none") .attr("stroke", "steelblue") .attr("stroke-width", 1.5) .attr("d", line(data)) ) ``` -------------------------------- ### DataFrame Shape and Sample Data Source: https://github.com/bourbonut/detroit/blob/main/docs/source/stack.rst This section displays the shape of the loaded unemployment DataFrame and a sample of its data. It shows the column names, data types, and a few rows to illustrate the data structure, including 'date', 'industry', and 'unemployed'. ```text shape: (1_708, 3) ┌─────────────────────┬──────────────────────────────┬────────────┐ │ date ┆ industry ┆ unemployed │ │ --- ┆ --- ┆ --- │ │ datetime[μs] ┆ str ┆ i64 │ ╞═════════════════════╪══════════════════════════════╪════════════╡ │ 2000-01-01 00:00:00 ┆ Wholesale and Retail Trade ┆ 1000 │ │ 2000-01-01 00:00:00 ┆ Manufacturing ┆ 734 │ │ 2000-01-01 00:00:00 ┆ Leisure and hospitality ┆ 782 │ │ 2000-01-01 00:00:00 ┆ Business services ┆ 655 │ │ 2000-01-01 00:00:00 ┆ Construction ┆ 745 │ │ … ┆ … ┆ … │ │ 2010-02-01 00:00:00 ┆ Other ┆ 603 │ │ 2010-02-01 00:00:00 ┆ Transportation and Utilities ┆ 591 │ │ 2010-02-01 00:00:00 ┆ Information ┆ 300 │ │ 2010-02-01 00:00:00 ┆ Agriculture ┆ 285 │ │ 2010-02-01 00:00:00 ┆ Mining and Extraction ┆ 79 │ └─────────────────────┴──────────────────────────────┴────────────┘ ``` -------------------------------- ### Load and Prepare Unemployment Data using Polars Source: https://github.com/bourbonut/detroit/blob/main/docs/source/stack.rst This snippet loads unemployment data from a CSV file using the Polars library. It parses the 'date' column into datetime objects and selects relevant columns for further processing. The data is fetched from a public URL. ```python # Source: https://observablehq.com/@d3/normalized-stacked-area-chart/2 import polars as pl import detroit as d3 URL = "https://static.observableusercontent.com/files/76f13741128340cc88798c0a0b7fa5a2df8370f57554000774ab8ee9ae785ffa2903010cad670d4939af3e9c17e5e18e7e05ed2b38b848ac2fc1a0066aa0005f?response-content-disposition=attachment%3Bfilename*%3DUTF-8%27%27unemployment.csv" unemployment = pl.read_csv(URL).select( pl.col("date").str.to_datetime("%Y-%m-%d"), pl.all().exclude("date"), ) ``` -------------------------------- ### Load Data for Histogram (Python) Source: https://github.com/bourbonut/detroit/blob/main/docs/source/histogram.rst Loads unemployment data from a CSV file using the Polars library. It also defines a named tuple for margin values and imports the detroit library. ```python # Source : https://observablehq.com/@d3/histogram/2 import detroit as d3 import polars as pl # for data manipulation from collections import namedtuple URL = "https://static.observableusercontent.com/files/8a6057f29caa4e010854bfc31984511e074ff9042ec2a99f30924984821414fbaeb75e59654e9303db359dfa0c1052534691dac86017c4c2f992d23b874f9b6e?response-content-disposition=attachment%3Bfilename*%3DUTF-8%27%27unemployment-x.csv" Margin = namedtuple("Margin", ["top", "right", "bottom", "left"]) unemployment = pl.read_csv(URL) ``` -------------------------------- ### Create a Line Chart using Detroit Source: https://github.com/bourbonut/detroit/blob/main/docs/source/line.rst Configures and generates a line chart using the Detroit library. It sets up scales for time and linear data, defines a line generator, creates an SVG container, and appends axes with custom styling and grid lines. The line path is drawn using the prepared data. ```python # Declare the chart dimensions and margins. width = 928 height = 500 margin = Margin(20, 30, 30, 40) # Declare the x (horizontal position) scale. x = d3.scale_time( [aapl["date"].min(), aapl["date"].max()], [margin.left, width - margin.right] ) # Declare the y (vertical position) scale. y = d3.scale_linear([0, aapl["close"].max()], [height - margin.bottom, margin.top]) # Declare the area generator. line = d3.line().x(lambda d: x(d[0].timestamp())).y(lambda d: y(d[1])) # Create the SVG container. svg = ( d3.create("svg") .attr("width", width) .attr("height", height) .attr("viewBox", f"0 0 {width} {height}") .attr("style", "max-width: 100%; height: auto; height: intrinsic;") ) # Add the x-axis. svg.append("g").attr("transform", f"translate(0, {height - margin.bottom})").call( d3.axis_bottom(x).set_ticks(width / 80).set_tick_size_outer(0) ) # Add the y-axis, remove the domain line, add grid lines and a label. ( svg.append("g") .attr("transform", f"translate({margin.left}, 0)") .call(d3.axis_left(y).set_ticks(height / 40)) .call(lambda g: g.select(".domain").remove()) .call(lambda g: g.select_all(".tick") .select_all("line") .clone() .attr("x2", width - margin.left - margin.right) .attr("stroke-opacity", 0.1) ) .call( lambda g: ( g.append("text") .attr("x", -margin.left) .attr("y", 10) .attr("fill", "currentColor") .attr("text-anchor", "start") .text("↑ Daily close ($)") ) ) ) # Append a path for the line. ( svg.append("path") .attr("fill", "none") .attr("stroke", "steelblue") .attr("stroke-width", 1.5) .attr("d", line(aapl.iter_rows())) ) ``` -------------------------------- ### Python D3.js Scatter Matrix Setup Source: https://github.com/bourbonut/detroit/blob/main/docs/source/complex_charts/scatter_matrix.rst This snippet sets up the SVG canvas and defines a D3.js y-axis. It then defines a Python function to generate transform attributes for cells in the scatter matrix. ```python .attr("transform", lambda d, i: f"translate(0,{i * size})") .each(lambda node, d, i, data: d3.select(node).call(axis_y.set_scale(d))) .call(lambda g: g.select(".domain").remove()) .call(lambda g: g.select_all(".tick").select_all("line").attr("stroke", "#ddd")) ) svg.append("g").call(y_axis) # Translate function for cells def transform(d): i, j = d return f"translate({i * size},{j * size})" ``` -------------------------------- ### Load and Prepare Apple Stock Data with Polars Source: https://github.com/bourbonut/detroit/blob/main/docs/source/line.rst Loads Apple stock data from a CSV URL using the Polars library. It selects the 'date' and 'close' columns and converts the date column to datetime objects. This step is crucial for time-series visualization. ```python # Source : https://observablehq.com/@d3/line-chart/2 import detroit as d3 import polars as pl # for data manipulation from collections import namedtuple URL = "https://static.observableusercontent.com/files/de259092d525c13bd10926eaf7add45b15f2771a8b39bc541a5bba1e0206add4880eb1d876be8df469328a85243b7d813a91feb8cc4966de582dc02e5f8609b7?response-content-disposition=attachment%3Bfilename*%3DUTF-8%27%27aapl.csv" Margin = namedtuple("Margin", ["top", "right", "bottom", "left"]) aapl = pl.read_csv(URL).select( pl.col("date").str.to_datetime("%Y-%m-%d"), pl.col("close"), ) ``` -------------------------------- ### Load and Prepare Data with Polars Source: https://github.com/bourbonut/detroit/blob/main/docs/source/area.rst Loads Apple stock data from a CSV file using Polars, selecting the date and closing price. It converts the date column to datetime objects. Dependencies include 'detroit', 'polars', and 'collections.namedtuple'. ```python # Source : https://observablehq.com/@d3/area-chart/2 import detroit as d3 import polars as pl # for data manipulation from collections import namedtuple URL = "https://static.observableusercontent.com/files/de259092d525c13bd10926eaf7add45b15f2771a8b39bc541a5bba1e0206add4880eb1d876be8df469328a85243b7d813a91feb8cc4966de582dc02e5f8609b7?response-content-disposition=attachment%3Bfilename*%3DUTF-8%27%27aapl.csv" Margin = namedtuple("Margin", ["top", "right", "bottom", "left"]) aapl = pl.read_csv(URL).select( pl.col("date").str.to_datetime("%Y-%m-%d"), pl.col("close"), ) ``` -------------------------------- ### Save Histogram Chart to SVG (Python) Source: https://github.com/bourbonut/detroit/blob/main/docs/source/histogram.rst Saves the generated SVG chart to a file named 'histogram.svg'. This allows the visualization to be shared or embedded elsewhere. ```python with open("histogram.svg", "w") as file: file.write(str(svg)) ``` -------------------------------- ### Save SVG Heatmap to File (Python) Source: https://github.com/bourbonut/detroit/blob/main/docs/source/heatmap.rst Saves the generated SVG heatmap to a file named 'heatmap.svg'. This snippet demonstrates basic file writing operations in Python to persist the visualization. ```python with open(f"heatmap.svg", "w") as file: file.write(str(svg)) ``` -------------------------------- ### Detroit Group Functions (Multiple) Source: https://github.com/bourbonut/detroit/blob/main/docs/source/api/array.rst Provides functionalities for grouping and indexing data. Includes functions for creating groups, getting group indices, and rolling up data. ```python detroit.group ``` ```python detroit.groups ``` ```python detroit.index ``` ```python detroit.indexes ``` ```python detroit.rollup ``` ```python detroit.rollups ``` -------------------------------- ### Generate and Render Pie Chart (Python) Source: https://github.com/bourbonut/detroit/blob/main/docs/source/pie.rst Generates a pie chart using detroit's arc and pie generators. It configures dimensions, color scales, and appends data to the SVG. The chart includes labels and values for each segment. Dependencies: detroit, polars. ```python # Declare the chart dimensions. width = 500 height = min(width, 500) radius = min(width, height) / 2 # Declare the arc generator with its dimensions. arc = d3.arc().set_inner_radius(radius * 0.67).set_outer_radius(radius - 1) # Declare pie generator with its dimensions. pie = d3.pie().set_pad_angle(1 / radius).set_sort(None).set_value(lambda d: d[1]) # Declare color scale. color = ( d3.scale_ordinal() .set_domain(data["name"].to_list()) .set_range( d3.quantize( lambda t: d3.interpolate_spectral(t * 0.8 + 0.1), data.height, )[::-1] ) ) # Create the SVG container. svg = ( d3.create("svg") .attr("width", width) .attr("height", height) .attr("viewBox", f"{-width / 2} {-height / 2} {width} {height}") .attr("style", "max-width: 100% height: auto;") ) # Generate pies and add arcs to the chart. ( svg.append("g") .select_all() .data(pie(data.iter_rows())) .join("path") .attr("fill", lambda d: color(d["data"][0])) .attr("d", arc) .append("title") .text(lambda d: f"{d['data'][0]}: {d['data'][1]}") ) # Generate pies and add text on them. ( svg.append("g") .attr("font-family", "sans-serif") .attr("font-size", 12) .attr("text-anchor", "middle") .select_all() .data(pie(data.iter_rows())) .join("g") # .attr("fill", "white") # white text .attr( "transform", lambda d: f"translate({arc.centroid(d)[0]}, {arc.centroid(d)[1]})" ) .call( lambda g: ( g.append("text") .append("tspan") .attr("y", "-0.4em") .attr("font-weight", "bold") .text(lambda d: d["data"][0]) ) ) .call( lambda g: ( g.filter(lambda d: (d["end_angle"] - d["start_angle"]) > 0.25) .select_all("text") .append("tspan") .attr("x", 0) .attr("y", "0.7em") .attr("fill-opacity", 0.7) .text(lambda d: str(d["data"][1])) ) ) ) ``` -------------------------------- ### Create Normalized Stacked Area Chart using Detroit Source: https://github.com/bourbonut/detroit/blob/main/docs/source/stack.rst This Python snippet constructs a normalized stacked area chart using the Detroit library. It configures stacking parameters, defines scales for time and linear axes, sets up color encoding, and prepares the area shape generator. It also creates an SVG container and appends elements for each series, including paths with tooltips. ```python data = unemployment.to_dicts() # Declare chart's dimensions width = 928 height = 500 margin_top = 20 margin_right = 20 margin_bottom = 20 margin_left = 40 # Determine the series that need to be stacked. # set_keys: distinct series keys, in input order # set_values: get value for each series key and stack # index: group by stack then series key series = ( d3.stack() .set_order(d3.stack_order_descending) .set_offset(d3.stack_offset_expand) .set_keys(unemployment["industry"].unique().to_list()) .set_value(lambda d, key, i, data: data[d][key]["unemployed"])( d3.index(data, lambda d: d["date"], lambda d: d["industry"]) ) ) # Prepare the scales for positional and color encodings. x = ( d3.scale_time() .set_domain(d3.extent(data, lambda d: d["date"])) .set_range([margin_left, width - margin_right]) ) y = d3.scale_linear().set_range_round([height - margin_bottom, margin_top]) color = ( d3.scale_ordinal() .set_domain([d.key for d in series]) .set_range(d3.SCHEME_TABLEAU_10) ) # Construct an area shape. area = ( d3.area() .x(lambda d: x(d.data.timestamp())) .y0(lambda d: y(d[0])) .y1(lambda d: y(d[1])) ) # Create the SVG container. svg = ( d3.create("svg") .attr("width", width) .attr("height", height) .attr("view_box", [0, 0, width, height]) .attr("style", "max-width: 100% height: auto") ) # Append a path for each series. ( svg.append("g") .select_all() .data(series) .join("path") .attr("fill", lambda d: color(d.key)) .attr("d", area) .append("title") .text(lambda d: d.key) ) # Append the x axis, and remove the domain line. ( svg.append("g") .attr("transform", f"translate(0, {height - margin_bottom})") .call(d3.axis_bottom(x).set_tick_size_outer(0)) .call(lambda g: g.select(".domain").remove()) ) # Add the y axis, remove the domain line, add grid lines and a label. ( svg.append("g") .attr("transform", f"translate({margin_left},0)") .call(d3.axis_left(y).set_ticks(height / 80, "%" )) .call(lambda g: g.select(".domain").remove()) .call( lambda g: g.select_all(".tick line") .filter(lambda d: d == 0 or d == 1) .clone() .attr("x2", width - margin_left - margin_right) ) .call( lambda g: g.append("text") .attr("x", -margin_left) .attr("y", 10) .attr("fill", "currentColor") .attr("text-anchor", "start") .text("↑ Unemployed persons") ) ) ``` -------------------------------- ### Create Histogram Chart (Python) Source: https://github.com/bourbonut/detroit/blob/main/docs/source/histogram.rst Generates a histogram chart using detroit. It bins the data, defines scales for x and y axes, creates an SVG container, and appends rectangular elements for each bin. It also adds x and y axes with labels. ```python width = 928 height = 500 margin = Margin(20, 20, 30, 40) # Bin the data. bins = d3.bin().set_thresholds(40).set_value(lambda d: d[3])(unemployment.iter_rows()) # Declare the x (horizontal position) scale. x = ( d3.scale_linear() .set_domain([bins[0].x0, bins[-1].x1]) .set_range([margin.left, width - margin.right]) ) # Declare the y (vertical position) scale. y = ( d3.scale_linear() .set_domain([0, max(map(len, bins))]) .set_range([height - margin.bottom, margin.top]) ) # Create the SVG container. svg = ( d3.create("svg") .attr("width", width) .attr("height", height) .attr("viewBox", f"0, 0, {width}, {height}") .attr("style", "max-width: 100%; height: auto;") ) # Add a rect for each bin. ( svg.append("g") .attr("fill", "steelblue") .select_all() .data(bins) .join("rect") .attr("x", lambda d: x(d.x0) + 1) .attr("width", lambda d: x(d.x1) - x(d.x0) - 1) .attr("y", lambda d: y(len(d))) .attr("height", lambda d: y(0) - y(len(d))) ) # Add the x-axis and label. ( svg.append("g") .attr("transform", f"translate(0, {height - margin.bottom})") .call(d3.axis_bottom(x).set_ticks(width / 80).set_tick_size_outer(0)) .call( lambda g: g.append("text") .attr("x", width) .attr("y", margin.bottom - 4) .attr("fill", "currentColor") .attr("text-anchor", "end") .text("Unemployment rate (%) →") ) ) # Add the y-axis and label, and remove the domain line. ( svg.append("g") .attr("transform", f"translate({margin.left}, 0)") .call(d3.axis_left(y).set_ticks(height / 40)) .call(lambda g: g.select(".domain").remove()) .call( lambda g: ( g.append("text") .attr("x", -margin.left) .attr("y", 10) .attr("fill", "currentColor") .attr("text-anchor", "start") .text("↑ Frequency (no. of counties)") ) ) ) ``` -------------------------------- ### Load Population and US Geographical Data Source: https://github.com/bourbonut/detroit/blob/main/docs/source/bubble.rst Loads population data from a URL and US geographical data (nation, states, counties) from a local JSON file. It also loads state and county mesh data for borders. Dependencies include requests, json, pytopojson, math, and detroit. It processes the data to create dictionaries for quick lookup and calculates centroids. ```python # https://observablehq.com/@d3/bubble-map/ import detroit as d3 import requests import json from pytopojson.feature import Feature from math import isnan URL = "https://static.observableusercontent.com/files/beb56a2d9534662123fa352ffff2db8472e481776fcc1608ee4adbd532ea9ccf2f1decc004d57adc76735478ee68c0fd18931ba01fc859ee4901deb1bee2ed1b?response-content-disposition=attachment%3Bfilename*%3DUTF-8%27%27population.json" US_URL = "https://cdn.jsdelivr.net/npm/us-atlas@3/counties-10m.json" # Load data population = json.loads(requests.get(URL).content) us = json.loads(requests.get(US_URL).content) nation = Feature()(us, us["objects"]["nation"]) statemap = dict( (d["id"], d) for d in Feature()(us, us["objects"]["states"])["features"] ) countymap = dict( (d["id"], d) for d in Feature()(us, us["objects"]["counties"])["features"] ) statemesh = json.load(open("data/statemesh.json")) countymesh = json.load(open("data/countymesh.json")) # Declare the chart dimensions. width = 975 height = 610 projection = ( d3.geo_albers_usa().scale(width * 1.2).translate([width * 0.5, height * 0.5]) ) # Helps to compute centroid positions class Centroid: def __init__(self): self._centroid = d3.geo_path(projection).centroid def __call__(self, feature): return f"translate({','.join(map(str, self._centroid(feature)))})" def is_valid(self, feature): return not any(map(isnan, self._centroid(feature))) centroid = Centroid() # Process data population = [ { "state": statemap.get(state), "county": countymap.get(f"{state}{county}"), "fips": f"{state}{county}", "population": int(p), } for p, state, county in population[1:] ] data = sorted( filter(lambda d: centroid.is_valid(d["county"]), population), key=lambda d: d["population"], reverse=True, ) ``` -------------------------------- ### Save SVG chart to file Source: https://github.com/bourbonut/detroit/blob/main/docs/source/scatter.rst This snippet shows how to save an SVG object to a file named 'scatter.svg'. It opens the file in write mode and writes the string representation of the SVG object. ```python with open("scatter.svg", "w") as file: file.write(str(svg)) ``` -------------------------------- ### Save Stacked Area Chart to SVG File Source: https://github.com/bourbonut/detroit/blob/main/docs/source/stack.rst This snippet shows how to save the generated SVG chart to a file named 'stack-area.svg'. It opens the file in write mode and writes the string representation of the SVG object to it. ```python with open("stack-area.svg", "w") as file: file.write(str(svg)) ``` -------------------------------- ### Create Scatter Chart Axes with Detroit Source: https://github.com/bourbonut/detroit/blob/main/docs/source/scatter.rst Configures the horizontal (x) and vertical (y) scales for a scatter plot using Detroit's scale_linear. Handles data ranges and margins. Requires Detroit library and Margin namedtuple. ```python # Specify the chart’s dimensions. width = 928 height = 600 margin = Margin(20, 30, 30, 40) # Create the horizontal (x) scale, positioning N/A values on the left margin. x = ( d3.scale_linear() .set_domain([0, cars["Miles_per_Gallon"].max()]) .nice() .set_range([margin.left, width - margin.right]) .set_unknown(margin.left) ) # Create the vertical (y) scale, positioning N/A values on the bottom margin. y = ( d3.scale_linear() .set_domain([0, cars["Horsepower"].max()]) .nice() .set_range([height - margin.bottom, margin.top]) .set_unknown(height - margin.bottom) ) # Create the SVG container. svg = ( d3.create("svg") .attr("width", width) .attr("height", height) .attr("viewBox", f"0 0 {width} {height}") ) # Append the axes. ( svg.append("g") .attr("transform", f"translate(0, {height - margin.bottom})") .call(d3.axis_bottom(x)) .call(lambda g: g.select(".domain").remove()) .call( lambda g: g.append("text") .attr("x", width - margin.right) .attr("y", -4) .attr("fill", "#000") .attr("font-weight", "bold") .attr("text-anchor", "end") .text("Miles per Gallon") ) ) ( svg.append("g") .attr("transform", f"translate({margin.left}, 0)") .call(d3.axis_left(y)) .call(lambda g: g.select(".domain").remove()) .call( ``` -------------------------------- ### Python D3.js Scatter Matrix Legend Creation Source: https://github.com/bourbonut/detroit/blob/main/docs/source/complex_charts/scatter_matrix.rst This section creates the legend for the scatter matrix. It calculates weights and spaces for labels based on their lengths and then appends rectangles and text for each legend item. ```python # Legend part # Labels of the legend data = color.get_domain() # Function to clamp input between 0 and 1 def clamp_total(total): def f(x): return 1 - exp(-x / total) return f offset_space = 80 lengths = list(map(len, data)) clamp = clamp_total(max(lengths)) weights = list(map(clamp, lengths)) w_max = max(weights) weights = [w / w_max for w in weights] # normalize weights # Spaces between labels spaces = [0] + list( accumulate( map(lambda w: w * offset_space + rect_size, weights[:-1]), iadd, ) ) g = ( legend.select_all("g") .data(data) .enter() .append("g") .attr("transform", lambda _, i: f"translate({spaces[i]}, 0)") ) ( g.append("rect") .attr("x", 0) .attr("y", 0) .attr("width", rect_size) .attr("height", rect_size) .attr("fill", lambda d: color(d)) .attr("stroke", "none") ) ( g.append("text") .attr("x", rect_size + 5) .attr("y", rect_size * 0.75) .attr("fill", "black") .attr("stroke", "none") .attr("font-size", "0.75em") .text(lambda d: d) ) ``` -------------------------------- ### Python Save Scatter Matrix to SVG Source: https://github.com/bourbonut/detroit/blob/main/docs/source/complex_charts/scatter_matrix.rst This snippet shows how to save the generated D3.js scatter matrix visualization to an SVG file named 'scatter-matrix.svg'. ```python # 3. Save your chart with open(f"scatter-matrix.svg", "w") as file: file.write(str(scatter)) ``` -------------------------------- ### Save the Generated SVG Map Source: https://github.com/bourbonut/detroit/blob/main/docs/source/bubble.rst Saves the complete SVG chart object to a file named 'bubble-map.svg'. This action writes the string representation of the SVG DOM to the specified file. ```python with open(f"bubble-map.svg", "w") as file: file.write(str(svg)) ``` -------------------------------- ### Save Chart to SVG File Source: https://github.com/bourbonut/detroit/blob/main/docs/source/area.rst Saves the generated SVG chart to a file named 'area.svg'. This step requires the 'svg' object created in the previous step. The code writes the string representation of the SVG object to the file. ```python with open("area.svg", "w") as file: file.write(str(svg)) ``` -------------------------------- ### Python D3.js Scatter Matrix Text Labels Source: https://github.com/bourbonut/detroit/blob/main/docs/source/complex_charts/scatter_matrix.rst This snippet adds text labels for each column to the scatter matrix. It sets the font style, positions the text, and displays the column name. ```python # Add some texts in cells ( svg.append("g") .style("font", "bold 10px sans-serif") .style("pointer-events", "none") .select_all("text") .data(columns) .join("text") .attr("transform", lambda d, i: f"translate({i * size},{i * size})") .attr("x", padding) .attr("y", padding) .attr("dy", ".71em") .text(lambda d: d) ) ``` -------------------------------- ### Create Heatmap SVG with Detroit (Python) Source: https://github.com/bourbonut/detroit/blob/main/docs/source/heatmap.rst Generates an SVG heatmap visualization using the Detroit library. It configures band scales for x and y axes, a sequential color scale based on vehicle counts, and appends rect elements to represent the heatmap cells. The chart includes axes and is styled according to defined margins. ```python data = traffic.to_dicts() width = 640 height = 820 margin = Margin(15, 40, 45, 120) # Declare the x (horizontal position) scale. x = d3.scale_band(list(map(str, range(24))), [margin.left, width - margin.right]) # Declare the y (vertical position) scale. sorted_locations = ( traffic.select(["location", "vehicles"]) .sort("vehicles", descending=True)["location"] .unique(maintain_order=True) .to_list() ) y = d3.scale_band(sorted_locations, [height - margin.bottom, margin.top]) # Color scale for cell colors color = d3.scale_sequential([0, traffic["vehicles"].max()], d3.interpolate_turbo) svg = ( d3.create("svg") .attr("width", width) .attr("height", height) .attr("viewBox", f"0 0 {width} {height}") ) # Add the x-axis, remove the domain line. ( svg.append("g") .attr("transform", f"translate(0, {height - margin.bottom})") .call(d3.axis_bottom(x)) .call(lambda g: g.select(".domain").remove()) ) # Add the y-axis, remove the domain line. ( svg.append("g") .attr("transform", f"translate({margin.left}, 0)") .call(d3.axis_left(y)) .call(lambda g: g.select(".domain").remove()) ) # Add cells. ( svg.append("g") .select_all() .data(data) .join("rect") .attr("x", lambda d: x(str(d["hour"])) + 0.5) .attr("y", lambda d: y(d["location"]) + 0.5) .attr("width", 19) .attr("height", 19) .attr("fill", lambda d: color(d["vehicles"])) ) ``` -------------------------------- ### Create Bar Chart SVG with Detroit Source: https://github.com/bourbonut/detroit/blob/main/docs/source/bar.rst Generates an SVG bar chart using the Detroit library. It configures scales for x and y axes, appends rectangles for each data point, and adds axis labels and ticks. The y-axis is formatted to display percentages. ```python width = 928 height = 500 margin = Margin(30, 0, 30, 40) # Declare the x (horizontal position) scale. # descending frequency x = ( d3.scale_band() .set_domain(alphabet["letter"].unique(maintain_order=True)) .set_range([margin.left, width - margin.right]) .set_padding(0.1) ) # Declare the y (vertical position) scale. y = ( d3.scale_linear() .set_domain([0, alphabet["frequency"].max()]) .set_range([height - margin.bottom, margin.top]) ) # Create the SVG container. svg = ( d3.create("svg") .attr("width", width) .attr("height", height) .attr("viewBox", f"0 0 {width} {height}") .attr("style", "max-width: 100%; height: auto;") ) # Add a rect for each bar. ( svg.append("g") .select_all() .data(alphabet.iter_rows()) .join("rect") .attr("x", lambda d: x(d[0])) .attr("y", lambda d: y(d[1])) .attr("height", lambda d: y(0) - y(d[1])) .attr("width", x.get_bandwidth()) .attr("fill", "steelblue") ) # Add the x-axis and label. svg.append("g").attr("transform", f"translate(0, {height - margin.bottom})").call( d3.axis_bottom(x).set_tick_size_outer(0) ) # Add the y-axis and label, and remove the domain line. ( svg.append("g") .attr("transform", f"translate({margin.left}, 0)") .call(d3.axis_left(y).set_tick_format(lambda y: str(int(y * 100)))) .call(lambda g: g.select(".domain").remove()) .call( lambda g: g.append("text") .attr("x", -margin.left) .attr("y", 10) .attr("fill", "currentColor") .attr("text-anchor", "start") .text("↑ Frequency (%)") ) ) ```