Published
Edited
Oct 25, 2020
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
data = d3.csv(inspectionsURL, row => {
const date = d3.timeParse("%Y-%m-%d")(row["INSPECTION DATE"]);
const d = {
restaurantID: row["CAMIS"],
boro: row["BORO"],
zip: row["ZIPCODE"],
cuisine: row["CUISINE DESCRIPTION"],
date: date,
violationCode: row["VIOLATION CODE"],
score: +row["SCORE"],
grade: row["GRADE"],
inspectionID: row["INSPECTION ID"]
};
return d;
})
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
function removeDuplicates(array, key) {
let lookup = {};
let newarray = [];
for (let i in array) {
var inspID = array[i]['inspectionID'];
lookup[inspID] = array[i];
}
for(let i in lookup) {
newarray.push(lookup[i]);
}
return newarray;
}
Insert cell
//Function to make bar chart
function makeGradeBar(data, title, xfield, yfield) {
return vl.markBar()
.title(title)
.data(data)
.encode(
vl.x().fieldQ(xfield),
vl.y().fieldN(yfield).sort(vl.field(yfield).order('ascending')),
)
}
Insert cell
// Filter out repeated inspections
deduplicatedData = removeDuplicates(data, 'inspectionID')

Insert cell
{
// Find most common cuisines
const cuisineCount = d3.rollup(deduplicatedData,
v => v.length,
d => d.cuisine)
const cuisineCountArray = Array.from(cuisineCount,
([cuisine, count]) => ({cuisine, count}))
//return cuisineCountArray.sort((a,b) => d3.descending(a.count, b.count)).slice(0,5)
return cuisineCountArray.sort((a,b) => d3.descending(a.count, b.count)).slice(0,5)
}
Insert cell

{
//Filter out uncommon cuisines type of cuisine
const popularCuisines = ["American", "Mexican", "Pizza", "Café/Coffee/Tea", "Chinese"]
const mostCommon = deduplicatedData.filter(obj => popularCuisines.includes(obj.cuisine))
//Change weird grades to other
const grades = ["A", "B", "C"]
for(let i in deduplicatedData) {
if (!grades.includes(deduplicatedData[i].grade)) {
deduplicatedData[i].grade = "Other"
}
}
const americanCuisine = mostCommon.filter(obj => obj.cuisine == 'American')
const americanGradeCount = Array.from(d3.rollup(americanCuisine,
v => v.length,
d => d.grade),
([grade, count]) => ({grade, count}))
const mexicanCuisine = mostCommon.filter(obj => obj.cuisine == 'Mexican')
const mexicanGradeCount = Array.from(d3.rollup(mexicanCuisine,
v => v.length,
d => d.grade),
([grade, count]) => ({grade, count}))
const chineseCuisine = mostCommon.filter(obj => obj.cuisine == 'Chinese')
const chineseGradeCount = Array.from(d3.rollup(chineseCuisine,
v => v.length,
d => d.grade),
([grade, count]) => ({grade, count}))
const pizzaCuisine = mostCommon.filter(obj => obj.cuisine == 'Pizza')
const pizzaGradeCount = Array.from(d3.rollup(pizzaCuisine,
v => v.length,
d => d.grade),
([grade, count]) => ({grade, count}))
const cafeCuisine = mostCommon.filter(obj => obj.cuisine == 'Café/Coffee/Tea')
const cafeGradeCount = Array.from(d3.rollup(cafeCuisine,
v => v.length,
d => d.grade),
([grade, count]) => ({grade, count}))
return vl.vconcat(
makeGradeBar(americanGradeCount, "Health inspection grade distribution for American cuisine", "count", "grade"),
makeGradeBar(mexicanGradeCount, "Health inspection grade distribution for Mexican cuisine", "count", "grade"),
makeGradeBar(chineseGradeCount, "Health inspection grade distribution for Chinese cuisine", "count", "grade"),
makeGradeBar(pizzaGradeCount, "Health inspection grade distribution for Pizza cuisine", "count", "grade"),
makeGradeBar(cafeGradeCount, "Health inspection grade distribution for Cafe cuisine", "count", "grade"), ).render()

//return groupedArray

}
Insert cell
Insert cell
Insert cell
function makeLineChart(data, title, xfield, yfield) {
vl.markLine()
.data(data)
.title(title)
.encode(
vl.x().fieldT(xfield),
vl.y().fieldQ(yfield)
)
}
Insert cell
Insert cell
{
var monthFormat = d3.timeFormat('%Y-%m')
const boroughGrouped = d3.group(deduplicatedData, d => d.boro)
const BronxInspectionsByTime = Array.from(d3.rollup(boroughGrouped.get("Bronx"),
v => v.length,
d => monthFormat(d.date)),
([month, inspections]) => ({month, inspections}))
.sort((a,b) => d3.ascending(a.month, b.month))
const BrooklynInspectionsByTime = Array.from(d3.rollup(boroughGrouped.get("Brooklyn"),
v => v.length,
d => monthFormat(d.date)),
([month, inspections]) => ({month, inspections}))
.sort((a,b) => d3.ascending(a.month, b.month))
const QueensInspectionsByTime = Array.from(d3.rollup(boroughGrouped.get("Queens"),
v => v.length,
d => monthFormat(d.date)),
([month, inspections]) => ({month, inspections}))
.sort((a,b) => d3.ascending(a.month, b.month))
const ManhattanInspectionsByTime = Array.from(d3.rollup(boroughGrouped.get("Manhattan"),
v => v.length,
d => monthFormat(d.date)),
([month, inspections]) => ({month, inspections}))
.sort((a,b) => d3.ascending(a.month, b.month))
const StatenIslandInspectionsByTime = Array.from(d3.rollup(boroughGrouped.get("Staten Island"),
v => v.length,
d => monthFormat(d.date)),
([month, inspections]) => ({month, inspections}))
.sort((a,b) => d3.ascending(a.month, b.month))
//return makeLineChart(BrooklynInspectionsByTime, "Inspections over time in Brooklyn", "month", "inspections")
const BrooklynChart = vl.markLine()
.data(BrooklynInspectionsByTime)
.title("Inspections over time in Brooklyn")
.encode(
vl.x().fieldT("month"),
vl.y().fieldQ("inspections")
)

const BronxChart = vl.markLine()
.data(BronxInspectionsByTime)
.title("Inspections over time in Bronx")
.encode(
vl.x().fieldT("month"),
vl.y().fieldQ("inspections")
)

const QueensChart = vl.markLine()
.data(QueensInspectionsByTime)
.title("Inspections over time in Queens")
.encode(
vl.x().fieldT("month"),
vl.y().fieldQ("inspections")
)

const ManhattanChart = vl.markLine()
.data(ManhattanInspectionsByTime)
.title("Inspections over time in Manhattan")
.encode(
vl.x().fieldT("month"),
vl.y().fieldQ("inspections")
)

const StatenIslandChart = vl.markLine()
.data(StatenIslandInspectionsByTime)
.title("Inspections over time in Staten Island")
.encode(
vl.x().fieldT("month"),
vl.y().fieldQ("inspections")
)

return vl.vconcat(BrooklynChart, BronxChart, QueensChart, ManhattanChart, StatenIslandChart).render()
}
Insert cell
Insert cell
Insert cell
function makeViolationBar(data, title, xfield, yfield) {
return vl.markBar()
.title(title)
.data(data)
.encode(
vl.x().fieldQ(xfield),
vl.y().fieldN(yfield).sort(vl.field(xfield).order('descending')),
)
}
Insert cell
{
const cuisineGrouped = d3.group(data, d => d.cuisine)
const AmericanViolations = Array.from(d3.rollup(cuisineGrouped.get("American"),
v => v.length,
d => violationCodeToDescription.get(d.violationCode)),
([violation, count]) => ({violation, count}))
.sort((a,b) => d3.descending(a.count, b.count)).slice(0,15)

const MexicanViolations = Array.from(d3.rollup(cuisineGrouped.get("Mexican"),
v => v.length,
d => violationCodeToDescription.get(d.violationCode)),
([violation, count]) => ({violation, count}))
.sort((a,b) => d3.descending(a.count, b.count)).slice(0,15)

const ChineseViolations = Array.from(d3.rollup(cuisineGrouped.get("Chinese"),
v => v.length,
d => violationCodeToDescription.get(d.violationCode)),
([violation, count]) => ({violation, count}))
.sort((a,b) => d3.descending(a.count, b.count)).slice(0,15)

const PizzaViolations = Array.from(d3.rollup(cuisineGrouped.get("Pizza"),
v => v.length,
d => violationCodeToDescription.get(d.violationCode)),
([violation, count]) => ({violation, count}))
.sort((a,b) => d3.descending(a.count, b.count)).slice(0,15)

const CafeViolations = Array.from(d3.rollup(cuisineGrouped.get("Café/Coffee/Tea"),
v => v.length,
d => violationCodeToDescription.get(d.violationCode)),
([violation, count]) => ({violation, count}))
.sort((a,b) => d3.descending(a.count, b.count)).slice(0,15)
return vl.vconcat(makeViolationBar(AmericanViolations, "Number of health code violation types for American restaurants", "count", "violation"),
makeViolationBar(MexicanViolations, "Number of health code violation types for Mexican restaurants", "count", "violation"),
makeViolationBar(ChineseViolations, "Number of health code violation types for Chinese restaurants", "count", "violation"),
makeViolationBar(PizzaViolations, "Number of health code violation types for Pizza restaurants", "count", "violation"),
makeViolationBar(CafeViolations, "Number of health code violation types for Cafes", "count", "violation")).render()


}

Insert cell
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