Published
Edited
Apr 22, 2022
Insert cell
# Final Project - Group 13 - Emmanuel Navas
Insert cell
If one of the graphs appear empty please reload the page to fix the problem.
Insert cell
<div style="
background: #fff;
display: grid;
height: ${screen.height/ screen.width * 250}vw;
grid-template-areas:
'a''b' 'c';
grid-gap: 5 px;
">
<div name="a" style="grid-area:b;border:solid 1px #ccc;text-align: left">${viewof VanAges}</div>
<div name="a" style="grid-area:a;border:solid 1px #ccc;text-align: right">${viewof VanServices}</div>
<div name="b" style="grid-area:a;border:solid 1px #ccc;text-align: left">${viewof MentalHealthVan}</div>
<div name="b" style="grid-area:c;border:solid 1px #ccc;text-align: center">${viewof Income}</div>
</div>`
Insert cell
brush = vl.selectInterval().encodings('x').resolve('global');
Insert cell
MentalHealth Map
Insert cell
viewof MentalHealthVan = {

let width = 500;
let container = DOM.element('div', { style: `width:${width}px;height:${width/1.5}px` });
yield container;
let map = L.map(container);

let baseLayer = L.tileLayer(cartoLight, {
attribution: cartoAttr,
subdomains: 'abcd',
maxZoom: 15,
minZoom: 0
}).addTo(map);

let geojsonMarkerOptions = {
radius: 5,
fillColor: "#1a93ff",
color: "##1a93ff",
weight: 1,
opacity: 1,
fillOpacity: 0.4
};

let VanAreasLayer = L.geoJson(VanAreas, {style: neighbourhoodStyle, onEachFeature: featureEvents})
.bindPopup(d => d.feature.properties.NAME)
.addTo(map);

let MentalHealthArea = L.geoJSON(MentalHealthVanc, {
pointToLayer: (feature,latlng) => {
return L.circleMarker(latlng, geojsonMarkerOptions);
}})
.bindPopup(function (Layer) {
return Layer.feature.properties.TAXONOMY_NAME + '<br> Address: ' + Layer.feature.properties.STREET_NUMBER + '<br> Neighborhood: ' + Layer.feature.properties.CITY;
})

.addTo(map);

map.on('click', () =>
mutable nHood = null
);


map.fitBounds(MentalHealthArea.getBounds());
map.fitBounds(VanAreasLayer.getBounds());

}
Insert cell
//We are writing the event listener function for each feature in our geojson layer
//when each of these events are fired, a callback function is triggered
//more interaction (such as hover) is covered here: https://leafletjs.com/SlavaUkraini/examples/choropleth/

function featureEvents(feature, layer) {
layer.on({
click: whenClicked, //callback functions
});
}
Insert cell
//We update our data in the function using mutable. This overrides observables defaults so we can push data from within //function scope globally
whenClicked = (event) => {
mutable nHood = event.target.feature.properties.NAME
}
Insert cell
mutable nHood = null
Insert cell
function neighbourhoodStyle(){
return {
fillColor: '#999999',
weight: 2,
opacity: .5,
color: 'white',
dashArray: '3',
fillOpacity: 0.2,
}};
Insert cell
mapSelection = {
if(nHood == null ){
return Array.from(new Set(VanAge.map(d => d.Location))) //Set is a new datastructure in ES6 -> only unique values
} else {
return [nHood]
}
}
Insert cell
Vancouver Area Ages
Insert cell
click = vl.selectPoint().encodings('color');
Insert cell
viewof VanAges = {
const name = vl.markBar()
.data(VanAge)
.transform(vl.filter({'and':
[click, {'field': 'Location', 'oneOf': mapSelection}]}))
.select(click)
.encode(
vl.x().fieldQ('Population').bin({extent : [0,15000]}),
vl.y().fieldN('Location'),
vl.color().value('lightgray').if(click, vl.color().fieldN('Age')),
vl.color().fieldN('Age').scale({scheme: 'magma'}), //colors
vl.column().fieldO('Age').spacing(10), //try using row instead of column and see what happens
vl.tooltip().fieldQ('Population')
)
// .params(brush)
.width(100) //the width here corresponds to the size of each individual bar chart
return vl.hconcat(name).render()

}
Insert cell
Vancouver Mental Health Services
Insert cell
viewof VanServices = {
const name= vl.markBar()
.data(ListServices)
.encode(
vl.x().fieldQ("Amount").bin({step :5}),
vl.y().count(),
vl.color().fieldN('name').scale({scheme: 'plasma'})

)
.width(200)
return vl.hconcat(name).render()
}
Insert cell
Vancouver Income divided by Area
Insert cell
viewof Income = {
const IncomeGraph = vl.markCircle({stroke: 'black', strokeWidth: 1, opacity: .75}) //we want each of the circles to have a border so we can see overlaps
.data(FinalIncome)
.transform(
vl.calculate('datum.Amount').as('Number of people'),
vl.filter({'and':
[click, {'field': 'Location', 'oneOf': mapSelection}]}))
.select(click)
.encode(
vl.x().fieldQ('Number of people'),
vl.y().fieldN('Income'),
vl.color().fieldN('Location'),
vl.color().value('lightgray').if(click, vl.color().fieldN('Location')),
vl.size().fieldQ('Amount'),
vl.tooltip().fieldQ('Amount')
)
.width(600)
.height(400)
return vl.hconcat(IncomeGraph).render()

}
Insert cell
----------------DATA------------------
Insert cell
Vancouver Mental Health Services Data
Insert cell
FullList = {
let my_object = {};
let my_object1 = {};
let my_object2 = {};
let my_object3 = {};
let my_object4 = {};
let my_object5 = {};
let my_object6 = {};
let my_object7 = {};
let my_object8 = {};
let my_object9 = {};
let my_object10 = {};
let my_object11 = {};
let my_object12 = {};
let my_object13 = {};
let my_object14 = {};
let my_object15 = {};
let my_object16 = {};
let my_object17 = {};
let my_object18 = {};
let my_object19 = {};
let my_object20 = {};
let my_object21 = {};
let my_object22 = {};
let my_object23 = {};
// load data into object
my_object.name = MentalVan[0].TAXONOMY_NAME;
my_object.Amount = MentalVan.length;
my_object.coordinates = MentalVan.LATITUDE, MentalVan.LONGITUD;

my_object1.name = MentalVan1[0].TAXONOMY_NAME;
my_object1.Amount = MentalVan1.length;

my_object2.name = MentalVan2[0].TAXONOMY_NAME;
my_object2.Amount = MentalVan2.length;

my_object3.name = MentalVan3[0].TAXONOMY_NAME;
my_object3.Amount = MentalVan3.length;

my_object4.name = MentalVan4[0].TAXONOMY_NAME;
my_object4.Amount = MentalVan4.length;

my_object5.name = MentalVan5[0].TAXONOMY_NAME;
my_object5.Amount = MentalVan5.length;

my_object6.name = MentalVan6[0].TAXONOMY_NAME;
my_object6.Amount = MentalVan6.length;

my_object7.name = MentalVan7[0].TAXONOMY_NAME;
my_object7.Amount = MentalVan7.length;

my_object8.name = MentalVan8[0].TAXONOMY_NAME;
my_object8.Amount = MentalVan8.length;

my_object9.name = MentalVan9[0].TAXONOMY_NAME;
my_object9.Amount = MentalVan9.length;

my_object10.name = MentalVan10[0].TAXONOMY_NAME;
my_object10.Amount = MentalVan10.length;

my_object11.name = MentalVan11[0].TAXONOMY_NAME;
my_object11.Amount = MentalVan11.length;

my_object12.name = MentalVan12[0].TAXONOMY_NAME;
my_object12.Amount = MentalVan12.length;

my_object13.name = MentalVan13[0].TAXONOMY_NAME;
my_object13.Amount = MentalVan13.length;

my_object14.name = MentalVan14[0].TAXONOMY_NAME;
my_object14.Amount = MentalVan14.length;

my_object15.name = MentalVan15[0].TAXONOMY_NAME;
my_object15.Amount = MentalVan15.length;

my_object16.name = MentalVan16[0].TAXONOMY_NAME;
my_object16.Amount = MentalVan16.length;

my_object17.name = MentalVan17[0].TAXONOMY_NAME;
my_object17.Amount = MentalVan17.length;

my_object18.name = MentalVan18[0].TAXONOMY_NAME;
my_object18.Amount = MentalVan18.length;

my_object19.name = MentalVan19[0].TAXONOMY_NAME;
my_object19.Amount = MentalVan19.length;

my_object20.name = MentalVan20[0].TAXONOMY_NAME;
my_object20.Amount = MentalVan20.length;

my_object21.name = MentalVan21[0].TAXONOMY_NAME;
my_object21.Amount = MentalVan21.length;

my_object22.name = MentalVan22[0].TAXONOMY_NAME;
my_object22.Amount = MentalVan22.length;

my_object23.name = MentalVan23[0].TAXONOMY_NAME;
my_object23.Amount = MentalVan23.length;


// push the object to Array
ListServices.push(my_object);
ListServices.push(my_object1);
ListServices.push(my_object2);
ListServices.push(my_object3);
ListServices.push(my_object4);
ListServices.push(my_object5);
ListServices.push(my_object6);
ListServices.push(my_object7);
ListServices.push(my_object8);
ListServices.push(my_object9);
ListServices.push(my_object10);
ListServices.push(my_object11);
ListServices.push(my_object12);
ListServices.push(my_object13);
ListServices.push(my_object14);
ListServices.push(my_object15);
ListServices.push(my_object16);
ListServices.push(my_object17);
ListServices.push(my_object18);
ListServices.push(my_object19);
ListServices.push(my_object20);
ListServices.push(my_object21);
ListServices.push(my_object22);
ListServices.push(my_object23);

return ListServices;
}
Insert cell
MentalVan= HealthDataFilter.filter(function(d){
return d.SV_TAXONOMY == "RX-8450.8000" })
Insert cell
MentalVan1= HealthDataFilter.filter(function(d){
return d.SV_TAXONOMY == "RF-3300" })
Insert cell
MentalVan2= HealthDataFilter.filter(function(d){
return d.SV_TAXONOMY == "RP-1400.8000-050" })
Insert cell
MentalVan3= HealthDataFilter.filter(function(d){
return d.SV_TAXONOMY == "LH-5000.0600" })
Insert cell
MentalVan4= HealthDataFilter.filter(function(d){
return d.SV_TAXONOMY == "TJ-3000.8000" })
Insert cell
MentalVan5= HealthDataFilter.filter(function(d){
return d.SV_TAXONOMY == "PH-6100" })
Insert cell
MentalVan6= HealthDataFilter.filter(function(d){
return d.SV_TAXONOMY == "RF-2000" })
Insert cell
MentalVan7= HealthDataFilter.filter(function(d){
return d.SV_TAXONOMY == "PN-8100.5000" })
Insert cell
MentalVan8= HealthDataFilter.filter(function(d){
return d.SV_TAXONOMY == "YF-5000.0500" })
Insert cell
MentalVan9= HealthDataFilter.filter(function(d){
return d.SV_TAXONOMY == "PN-8100.5000" })
Insert cell
MentalVan10= HealthDataFilter.filter(function(d){
return d.SV_TAXONOMY == "RP-1400.8000-020.21" })
Insert cell
MentalVan11= HealthDataFilter.filter(function(d){
return d.SV_TAXONOMY == "PN-8100.4500-900" })
Insert cell
MentalVan12= HealthDataFilter.filter(function(d){
return d.SV_TAXONOMY == "PN-8100.6500-650" })
Insert cell
MentalVan13= HealthDataFilter.filter(function(d){
return d.SV_TAXONOMY == "PN-8100.0200" })
Insert cell
MentalVan14= HealthDataFilter.filter(function(d){
return d.SV_TAXONOMY == "RP-1400.8000-020" })
Insert cell
MentalVan15= HealthDataFilter.filter(function(d){
return d.SV_TAXONOMY == "RX-8450.8100" })
Insert cell
MentalVan16= HealthDataFilter.filter(function(d){
return d.SV_TAXONOMY == "YF-8000.1800" })
Insert cell
MentalVan17= HealthDataFilter.filter(function(d){
return d.SV_TAXONOMY == "YF-5000.1700-100" })
Insert cell
MentalVan18= HealthDataFilter.filter(function(d){
return d.SV_TAXONOMY == "RP-1400.8000-020.15" })
Insert cell
MentalVan19= HealthDataFilter.filter(function(d){
return d.SV_TAXONOMY == "RP-1400.8000-020.18" })
Insert cell
MentalVan20= HealthDataFilter.filter(function(d){
return d.SV_TAXONOMY == "RP-1400.8000-020.05" })
Insert cell
MentalVan21= HealthDataFilter.filter(function(d){
return d.SV_TAXONOMY == "RP-1400.8000-650" })
Insert cell
MentalVan22= HealthDataFilter.filter(function(d){
return d.SV_TAXONOMY == "RX-1700" })
Insert cell
MentalVan23= HealthDataFilter.filter(function(d){
return d.SV_TAXONOMY == "YF-5000" })
Insert cell
ListServices = []
Insert cell
HealthDataFilter = MentalHealth.filter(function(d){
return d.CITY == "Vancouver" })
Insert cell
MentalHealth = FileAttachment("healthlinkbc-mhsu-health-services.csv").csv()
Insert cell
MentalHealthVanc = FileAttachment("mental-health.geojson").json()
Insert cell
Data of Vancouver divided by Areas
Insert cell
VanAreas = FileAttachment("VanAreas.json").json()
Insert cell
Data set for the AGE in Vancouver divided by Area
Insert cell
// the following gives me a list of only the group of ages in the data
AgeList = {
let my_object = {};
let my_object1 = {};
let my_object2 = {};
let my_object3 = {};
let my_object4 = {};

// load data into object
my_object.name = VanAge[26].Age;
my_object1.name = VanAge[54].Age;
my_object2.name = VanAge[74].Age;
my_object3.name = VanAge[104].Age;
my_object4.name = VanAge[124].Age;

// push the object to Array
age.push(my_object);
age.push(my_object1);
age.push(my_object2);
age.push(my_object3);
age.push(my_object4);


return age;
}
Insert cell
VanAgeMap = test.map(d=> {
var a = d;
a.Population =+ d.Population;

return a;


})
Insert cell
test = FileAttachment("AgeDataTst.csv").csv()
Insert cell
VanAge = FileAttachment("CensusAgeDataFiltered - Hoja 1.csv").csv()
Insert cell
age = []
Insert cell
Data set for the income in Vancouver divided by Area
Insert cell
VanIncomeMap = VanIncome.map(d=> {
var a = d;
a.Amount =+ d.Amount;

return a;


})
Insert cell
VanIncome = FileAttachment("CensusIncomeData - Hoja 1.csv").csv()
Insert cell
test1= VanIncomeMap.filter(function(d){
return d.Location != "Vancouver CMA" })
Insert cell
FinalIncome= test1.filter(function(d){
return d.Location != "Vancouver CSD" })
Insert cell
----------------Imports-----------------------
Insert cell
import {howto, altplot} from "@d3/example-components"
Insert cell
import {Legend, Swatches} from "@d3/color-legend"
Insert cell
import {howto} from "@d3/example-components"
Insert cell
import {toc} from "@nebrius/indented-toc"
Insert cell
import {howto, altplot} from "@d3/example-components"
Insert cell
import {GroupedBarChart} from "@d3/grouped-bar-chart"
Insert cell
<link href='${resolve('leaflet@1.2.0/dist/leaflet.css')}' rel='stylesheet' />
Insert cell
VegaLite = require('vega-lite@2.0.0-beta.2/build/vega-lite.min.js')
Insert cell
Vegalite = require("@observablehq/vega-lite@0.2")
Insert cell
vegalite = require("@observablehq/vega-lite@0.1")
Insert cell
d3 = require('d3@7')
Insert cell
L = require('leaflet@1.2.0')
Insert cell
cartoLight = "https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}@2x.png"
Insert cell
cartoAttr = `&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>, &copy; <a href="https://carto.com/attributions">CARTO</a>`
Insert cell
Resources

The code for this notebook came from the different IAT 355 tutorials:
https://observablehq.com/collection/@krispybird/iat-355-s22-tutorials-exercises

And the following observable notebook to further understand the leaflet:
https://observablehq.com/@lilpeasant/introduction-to-leaflet-and-d3

The code that help me create the Object array: ListServices:
https://stackoverflow.com/questions/40250139/push-object-into-array

I found very useful code and examples in these collection of notebooks
https://observablehq.com/@d3/gallery

Data Set

The Vancouver Data set Are came from the IAT 355 7th tutorial:
https://observablehq.com/@krispybird/iat355-tutorial-7-maps-geocoding-with-leaflet-tutorial?collection=@krispybird/iat-355-s22-tutorials-exercises

The Mental Health Data Resources data Set came from:
https://catalogue.data.gov.bc.ca/dataset/mental-health-and-substance-use-health-services

Mental health disorders:
https://data.world/vizzup/mental-health-depression-disorder-data/workspace/file?filename=Mental+health+Depression+disorder+Data.xlsx

Vancouver Census:
https://opendata.vancouver.ca/explore/dataset/census-local-area-profiles-2016/information/

Insert cell
_______________________________________________________________________
Insert cell
# A5 extra code, tests, other possible visualizations etc
Insert cell
//A5 --- I have chosen the following three graphs as my visualizations( one graph missing). The top left Graph represents the map of Vancouver divided by area in which we can also see the exact location of the different Mental services in Canada. With that visualization I addressed the question of how are the services distributed around Vancouver. The top right graph connects to the top left since it represents the amount of services in Vancouver, how many of each services exist.(unfortunately i haven't been able to link them through a common variable since the map uses Area while the other has only coordinates which I am still trying to use to connect both visualizations). The Bottom graph show the age distribution in the different Vancouver Areas. That visualization help to identify if there is a connection between age and the location of the different services. The last visualization (to be inserted) is to identify if the population income in the area had an effect on the location of the different services. I have a small trouble due to the different compatibility of data sources an I am still struggling to combine them through a common denominator which is turning to be a bit harder than I thought.
Insert cell
//import {DonutChart} from "@emmanuel-bel/a4_first_project_visualizations"
Insert cell
//Plot.barY(VanAge, {x: "Age", y: "Population"}).plot()
Insert cell
//chart1 = GroupedBarChart(VanAgeMap, {
// x: d => d.Location,
// y: d => d.Population / 1e6,
// z: d => d.Age,
// xDomain: d3.groupSort(VanAgeMap, D => d3.sum(D, d => -d.Population), d => d.Location).slice(0, 6), // top 6
// yLabel: "↑ Population (thousands)",
// zDomain: age.name,
// colors: d3.schemeSpectral[age.length],
// width: 900,
// height: 500
//})
Insert cell
//viewof VanAges1 = {
// const name = vl.markBar()
// .data(FinalVanAge)
//.transform(vl.filter({'and':
// [brush, {'field': 'Location', 'oneOf': mapSelection}]}))
// .select(click)
// .encode(
// vl.x().fieldQ('Population').bin({extent : [0,15000]}),
// vl.y().fieldN('Location'),
// vl.color().value('lightgray').if(click, vl.color().fieldN('Age')),
// vl.color().fieldN('Age').scale({scheme: 'plasma'}), //colors
// vl.column().fieldO('Age').spacing(10) , //try using row instead of column and see what happens
// vl.tooltip().fieldQ('Population')
// )
// .width(80) //the width here corresponds to the size of each individual bar chart
// .height(300)
//return vl.hconcat(name).render()

//}
Insert cell
//chart = DonutChart(ListServices, {
// name: d => d.name,
// value: d => d.Amount,
// width,
// height: 500
//})
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