Published
Edited
Jan 11, 2021
Insert cell
Insert cell
Insert cell
Insert cell
// Load the protests.csv data (a File Attachment) into a variable
protests = FileAttachment("protests.csv").csv()
Insert cell
// How many protests are in the dataset?
num_protests = protests.length
Insert cell
Insert cell
// How much information is available about each protest?
num_features = Object.keys(protests[0]).length
Insert cell
Insert cell
Insert cell
// Create an array of the number of attendees in each protest
// (make sure to return a *number* for each element in the array)
num_attendees = protests.map(d => +d.Attendees)
Insert cell
Insert cell
// What is the lowest number of attendees?
min_attendees = d3.min(num_attendees)
Insert cell
Insert cell
// What is the highest number of attendees?
max_attendees = d3.max(num_attendees)
Insert cell
Insert cell
// What is the mean number of attendees?
mean_attendees = d3.mean(num_attendees)
Insert cell
Insert cell
// What is the median number of attendees?
median_attendees = d3.median(num_attendees)
Insert cell
Insert cell
// What is the absolute difference between the mean and median number of attendees?
mean_median_diff = mean_attendees - median_attendees
Insert cell
Insert cell
Insert cell
// Create an array that holds the Location of each protest
locations = protests.map(d => d.Location)
Insert cell
Insert cell
// How many *unique* locations are in the dataset?
num_locations = _.uniqBy(protests, d => d.Location).length
Insert cell
Insert cell
// How many protests occured in Washington?
// (hint: locations that end with "WA")
num_in_wa = protests.filter(d => d.Location.endsWith("WA")).length
Insert cell
Insert cell
// What proportion of protests (number / total) occured in Washington?
prop_in_wa = num_in_wa / protests.length
Insert cell
Insert cell
// How many protests occurred in each state?
// hint: use the d3.rollups method to create an *array of arrays*,
// where each one holds the state abbreviation and the number of protests in that state
// https://observablehq.com/@d3/d3-group
num_by_state = d3.rollups(protests, v => v.length, d => d.Location.slice(-2))
Insert cell
Insert cell
// What was the highest number of protests that occured in a single state?
highest_in_a_state = d3.max(num_by_state, d => d[1])
Insert cell
Insert cell
// Which state (two letter abbreviation) had the highest number of protests?
// hint: use the two variables calculated above
state_most_protests = num_by_state.filter(
d => d[1] === highest_in_a_state
)[0][0]
Insert cell
Insert cell
Insert cell
// Create an array that holds the Date of each protest
// You should convert the string in the original dataset to a proper date object using the Date() function
dates = protests.map(d => new Date(d.Date))
Insert cell
Insert cell
// What is the most recent date in the dataset?
most_recent = d3.max(dates)
Insert cell
Insert cell
// What is the earliest date in the dataset?
earliest = d3.min(dates)
Insert cell
Insert cell
// How many protests occurred in 2020?
// hint: use the getFullYear() method
num_in_2020 = dates.map(d => d.getFullYear()).filter(d => d === 2020).length
Insert cell
Insert cell
// How many protests occurred in 2019?
num_in_2019 = dates.map(d => d.getFullYear()).filter(d => d === 2019).length
Insert cell
Insert cell
// How many protests occurred in July (of any year)?
// Hint: you can use date.toLocaleDateString("default", { month: "long" }) to get the month name
num_in_july = dates
.map(d => d.toLocaleDateString("default", { month: "long" }))
.filter(d => d === "July").length
Insert cell
Insert cell
// How many protest occured each month?
// hint: use the d3.rollups method to create an *array of arrays*,
// where each one holds the month name and the number of protests in that month
by_month = d3.rollups(
dates,
v => v.length,
d => d.toLocaleDateString("default", { month: "long" })
)
Insert cell
Insert cell
// Which month had the highest number of protests?
month_most_protests = by_month.filter(
d => d[1] === d3.max(by_month.map(d => d[1]))
)[0][0]
Insert cell
Insert cell
Insert cell
// How many different purposes are listed in the dataset?
// (the number of unique values of the `Event (legacy; see tags)` attribute)
num_purposes = _.uniqBy(protests, d => d["Event (legacy; see tags)"]).length
Insert cell
Insert cell
// That's quite a few -- if you look at the array, you'll notice
// a common pattern for each purpose. It's listed as:
// SOME_PURPOSE (additiona_detail)
// To get a higher level summary, create an array of `high_level_purposes` by
// extracting *everything before the first parenthesis* in each purpose ("Event (legacy; see tags)")
// You should return an array equal to the length of the protests dataset
high_level_purposes = protests.map(
d => d["Event (legacy; see tags)"].split("(")[0]
)
Insert cell
Insert cell
// Which high-level purpose was the most common?
// Hint, you may want to open a JavaScript statement to write multiple lines of code,
// Or try out d3.greatest with d3.rollups
// https://observablehq.com/@d3/d3-least
most_common_purpose = d3.greatest(
d3.rollups(high_level_purposes, v => v.length, d => d)
)[0]
Insert cell
Insert cell
Insert cell
import { check_answer, displayCaution } with {
answers
} from "@uw-info474/utilities"
Insert cell
answers = await FileAttachment("answers.json").json({ typed: true })
Insert cell
new Date(answers.earliest)
Insert cell
d3 = require("d3")
Insert cell
_ = require("lodash")
Insert cell
REPLACE_ME = undefined
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more