Charts on boston.gov (legacy)

Technical and project documentation for charts on boston.gov.

We use the VegaLitearrow-up-right and Vegaarrow-up-right libraries to create our charts on boston.gov. VegaLite is an easier to use version of Vega. Both libraries are built on top of D3arrow-up-right. It does a little more guess work for us so we don't have to be so specific in defining our charts. These libraries let users define/create a chart using a JSON schema.

From a technical standpoint, we wrap this library up as a web component that is stored in Fleet, our patterns library. The <cob-chart> component takes a JSON object as input in a Vega or VegaLite schema as input and creates a chart.

From a functional standpoint, when putting charts on boston.gov, we place them within text components in an effort to bring context to the data and information the chart is displaying. The FY20 Budget Websitearrow-up-right has good examples of how charts should be used with narrative explanation.

Good Reads

Putting a chart on boston.gov

In general, content on boston.gov should be at or below an 8th grade reading level. In an attempt to be in accordance with this and keep our site as easy-to-understand as possible, we push for simple and straight forward charts (e.g. bar charts, line charts, and sometimes pie charts if we have to).

Coordination with both the boston.gov Content Manager (for chart placement) and the Analytics Team (for chart data) will be required to get a chart on boston.gov.

The general overview for getting a chart on boston.gov is:

  1. Get some data

  2. Work with the Analytics Team to get it into a public s3 bucket and set up an automated workflow for it getting updated (if appropriate).

  3. Grab the schema from one of the charts below that looks/is most like the one you want to build

  4. Drop it into the Online Vega Editorarrow-up-right to start editing it to use your data

  5. Check that your chart works/looks okay using the COB-chart editorarrow-up-right.

  6. Add your chart to boston.gov through Drupal.

Getting the data with the Analytics Team

Vega/VegaLite can read in data from a publicly available url. We leverage this functionality so that we can set up separate automation practices for the data charts on boston.gov display. This helps ensure the data on the chart stays up-to-date.

For testing purposes, you could upload a csv as a Github Gistarrow-up-right and use that url, but when things move to production, all data should be pushing/pulling from an s3 bucket.

Using s3

The Analytics Team has the ability to create s3 buckets that can store completely public csv files. Once a file has been loaded to a public bucket, you can supply the "Object URL" to Vega.

Location of the "Object URL" in s3.

Storing data for charts on s3, means we can set up separate workflows that will automatically update the data on the chart. For example, for the FY20 Budget websitearrow-up-right, we set up a workflow in Civisarrow-up-right (the Analytics Teams data wharehouse and ETL platform) that:

  1. Pulls data from a publicly available google sheetarrow-up-right the Budget Office updates

  2. Drops the data into Civis' Postgres database

  3. Uploads the tables as csv to s3 (e.g. https://s3.amazonaws.com/public-budget-data/fy20_capital_projects_chart_data.csvarrow-up-right), replacing existing files of the same name with new information.

With this workflow, we can ensure that when the Budget Office needs to make a change on a chart on boston.gov, they only have to update the agreed upon spreadsheet. More detailed documentation on this process.(add link)

Making a chart

To create the charts, we use a json schema created an maintained by the authors of Vega/VegaLite. We primarily rely on VegaLite as it is easier to use than Vega. The only time Vega is used is to create a pie chart.

A good place to get started for an overall understanding of the libraries is their docs:

The Vega libraries can do much more than what we've implemented at the City (e.g. create mapsarrow-up-right, box plotsarrow-up-right, multi-view displaysarrow-up-right, treemapsarrow-up-right, etcarrow-up-right.). The charts web component was built and tested for only the following charts:

Chart Type

Vega or VegaLite

VegaLite

VegaLite

Each of the above charts can be built with one selection element as well. The selection element can only be built off one field and will always appear as a drop down box. All available types of charts on a boston.gov test page.arrow-up-right

When developing a chart, it will likely be easiest to start using the Vega/VegaLite Online editorarrow-up-right. Once the chart has largely been built, the COB-chart editorarrow-up-right is helpful to make sure the chart will still work when rendered as a web component and for making sure fonts look okay.

The "boston" section of the schema

The <cob-chart> web component supports an additional section of the schema called "boston". This section supports three inputs specific to our uses cases:

  • "chartID" - string, optional: unique id of the chart

  • "minWidth"- integer, optional: minimum width in pixels of the chart. Due to data constraints, some charts will not be readable on smaller screens. In this case, we can supply a minimum width to the chart and users will be able to horizontal scroll on any screen smaller than the minimum width supplied. Example of this functionality in productionarrow-up-right.

  • "defaultSelection": string, optional: value of a drop down's default selection

Below are examples of how each specific type of chart gets implemented at the City of Boston. Links to example schemas are given with call outs of particularly interesting functionality the chart contains.

Height and Width

The height of the chart defined in the schema will be respected and used when the chart is rendered as a web component on a boston.gov page.

The width of the chart will be overwritten based on the screen size the chart is rendered on if "autosize": "fit" is in the schema. This helps ensure a chart fits on both large and small screens.

Bar Charts

Drop the JSON from the file linked below in the COB chart editorarrow-up-right to see the chart below (chart in productionarrow-up-right):

<cob-chart> simple bar chart.
Bar Chart schema JSON

Good Reads

Ordering the Colors on a Bar Chart

If you want the colored sections of bar charts to display in a specified order, you can use the VegaLite transformarrow-up-right to create a new field in the data. In the example below, this field is called "barOrder".

You can then use that field to order the barsarrow-up-right so that the number of Community-Based Organization seats is always on top.

Sort bars on Bar Chart axis

You can use the "sort" sectionarrow-up-right of the schema or an axis to sort by various metrics. For example, we may want to have the longest bars at the top of a chart on a bar chart.

Bars sorted by "amount".

To achieve that, we add "sort" and define the field, operation, and order of the bars to the axis definition we want sorted.

Line Charts

Drop the JSON from the file linked below in the COB chart editorarrow-up-right to see the chart below (chart in productionarrow-up-right):

<cob-chart> simple line chart.
Line chart schema JSON

Good Reads

Using Lines and Points -

Due to a bugarrow-up-right in the version on VegaLite we're using, defining your own tooltip with a "line" mark will break the chart.

Defining a tooltip when using a line mark will break the chart.

When you are not using a selection, you can get around this by layeringarrow-up-right a line mark and a point mark on top of each other in the chart and defining the tooltip in the point mark's encoding. Use the line chart schema linked above as an example of how to do this.

If you are using a selection, the chart will work if you do not define tooltips, so work with the data owner to ensure field names are appropriate for displaying. An example of this is shown in the "Line Chart with Selection" tab above.

Grouped Bar Charts

Drop the JSON from the file linked below in the COB chart editorarrow-up-right to see the chart below (chart in productionarrow-up-right):

<cob-chart> grouped bar chart.
Grouped bar chart JSON schema

Using Columns

The main difference between a grouped bar chart and a regular bar chart is that we add a "column"arrow-up-right section, where we define the field to group by and style the header, to the schema's "encoding".

The COB web component was not created/tested for supporting "rows"arrow-up-right, we only support grouping by columnarrow-up-right.

Pie Charts

Pie charts are the only chart type the <cob-chart> component supports that use the Vega schemaarrow-up-right.

Drop the JSON from the file linked below in the COB chart editorarrow-up-right to see the chart below (chart in productionarrow-up-right):

<cob-chart> pie chart.
Pie chart schema JSON

Pie Chart Sizing

The height and width on pie charts should pretty much always be set to 200px. This ensures that the chart fits on all screen sizes.

If the height and width are set to more than 200px, the chart will resize to best fit the container it is loaded in, but the center of the chart will not change if the screen is resized, so it may get cut off if the user adjusts their screen size.

Pie charts don't perform well if resized, so their height and width should always be 200px.

Good Reads

Helpful Hints

Using Domain and Range together

Vega supports both a domain an a rangesarrow-up-right an inputs to their "scale" encoding. This means you can assign individual values to specific colors so they stay consistent as a user interacts with them. This is particularly helpful on charts with a selection in which not every selection will have all the values shown.

For example, we use domain and range to ensure the "Explore Spending" chartarrow-up-right on budget.boston.gov always uses the same colors for the seven difference types of Operating Budget spending.

Parse incoming data - no commas in number fields

Data from a URL can be parsed to ensure it is read as the correct data type when Vega reads it. This is a good idea to ensure your chart will perform as expected and any issues with the data input will get turned to null values instead of the entire column being read as a string.

While this is helpful, number fields still need to be formatted without commas in the source data. Even when explicitly parsed as a number, Vega will not read in number fields correctly if there are commas in themarrow-up-right. You'll have to work with departments or the Analytics Team to make sure the csv's getting pushed to s3 do not have commas in numeric fields.

Re-shaping data

Vega and VegaLite support a "fold" transformationarrow-up-right that allows you to reshape your data from wide to longarrow-up-right.

This can be extremely helpful as Departments may often store and/or conceptualize their data in the "wide" format, while charting libraries and data nerds like data in a "long" format.

State aid data in "wide format".
State Aid data in a "long" format.

Now that our data is formatted correctly, we can use the "Type" column to color our chart so we get three lines showing the trends in the different types of State Aid.

Formatting numbers with d3 and calculated fields

Vega and VegaLite both support d3's number formatsarrow-up-right allowing you do things like putting a dollar sign in front of money values and inserting back those commas that you had to tell the data owner to take out.

When working with large numbers, you can use Vega's "calculate" transformarrow-up-right to divide the numbers on an axis by some amount (e.g. a million) so that displaying them on a y-axis becomes easier. You can then use the original field for displaying the amount in tooltips.

Chart with divided y-axis amounts and full amounts in the tooltip.

Known limitations

General Charting Good Reads

Technical Docs

Web Component

The code for the web componentarrow-up-right is stored in Fleet, our patterns library.

Drupal integration

TDB

Last updated

Was this helpful?