Public
Edited
Apr 11, 2023
1 fork
Insert cell
Insert cell
d3 = require("d3@6")
Insert cell
data = FileAttachment("emissions_vehicle_join_adjweights_2023@1.csv").csv()
Insert cell
bardata = FileAttachment("bardata - Sheet1.csv").csv()
Insert cell
margin = ({top: 10, right: 30, bottom: 30, left: 60})

Insert cell
width = 600
Insert cell
height = 350
Insert cell
years_list = ["2000", "2023"]
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
fullType_choice1 = findType(selectYear1)
Insert cell
fullType_choice2 = findType(selectYear2)
Insert cell
fullMake_choice1 = findMake(selectType1, selectYear1)
Insert cell
fullMake_choice2 = findMake(selectType2, selectYear2)
Insert cell
fullModel_choice1 = findModel(selectMake1, selectType1, selectYear1)
Insert cell
fullModel_choice2 = findModel(selectMake2, selectType2, selectYear2)
Insert cell
fullConfig_choice1 = findConfig(selectModel1, selectMake1, selectType1, selectYear1)
Insert cell
fullConfig_choice2 = findConfig(selectModel2, selectMake2, selectType2, selectYear2)
Insert cell
Insert cell
viewof selectYear1 = Inputs.select(["Select Year"].concat(years_list), {label: "1) Year"})
Insert cell
viewof selectType1 = Inputs.select(["Select Type"].concat(fullType_choice1), {label: "2) Type"})
Insert cell
viewof selectMake1 = Inputs.select(["Select Make"].concat(fullMake_choice1), {label: "3) Make"})
Insert cell
viewof selectModel1 = Inputs.select(["Select Model"].concat(fullModel_choice1), {label: "4) Model"})
Insert cell
viewof selectConfig1 = Inputs.select([null].concat(fullConfig_choice1), {label: "5) Configuration", format: x => {if (x !== null) {return x.Config} else {return "Select Configuration"}}})
Insert cell
// vehicle1_min = {
// if (selectConfig1 !== null) {
// if ((Math.round(selectConfig1.totalkg / 5000) * 5000 - selectConfig1.totalkg) < 0) {
// return Math.round(selectConfig1.totalkg / 5000) * 5000
// } else {
// return (Math.round(selectConfig1.totalkg / 5000) * 5000) - 5000
// }
// } else {
// return null
// }
// }
Insert cell
Insert cell
viewof selectYear2 = Inputs.select(["Select Year"].concat(years_list), {label: "1) Year"})
Insert cell
viewof selectType2 = Inputs.select(["Select Type"].concat(fullType_choice2), {label: "2) Type"})
Insert cell
viewof selectMake2 = Inputs.select(["Select Make"].concat(fullMake_choice2), {label: "3) Make"})
Insert cell
viewof selectModel2 = Inputs.select(["Select Model"].concat(fullModel_choice2), {label: "4) Model"})
Insert cell
viewof selectConfig2 = Inputs.select([null].concat(fullConfig_choice2), {label: "5) Configuration", format: x => {if (x !== null) {return x.Config} else {return "Select Configuration"}}})
Insert cell
datalist = {var total = []
for (let i = 0; i < data.length; i++) {
total.push(Number(data[i].totalkg))
}
return total
}
Insert cell
(Math.round(Math.max.apply(Math,datalist) / 5000) * 5000 / 5000)
Insert cell
Insert cell
chart = {

const svg = d3.select(DOM.svg(width+margin.left+margin.right,
height+margin.top+margin.bottom))

const max_domain = Math.round(Math.max.apply(Math,datalist) / 5000) * 5000
const ticks = max_domain / 5000

const container = svg
.append("svg")
.attr("width", width + margin.left*+ margin.right)
.attr("height", height + margin.top + margin.bottom*3)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.bottom + ")")

// X axis: scale and draw:
const x = d3.scaleLinear()
.range([0, width-30])
.domain([0, max_domain])
// .domain([0, d3.max(data, function(d) { return +d.totalkg }) + 3000]) // can use this instead of 1000 to have the max of data: d3.max(data, function(d) { return +d.price })
container.append("g")
.attr("transform", `translate(0, ${height-20})`)
.call(d3.axisBottom(x))
.call(g => g.append("text")
.attr("x", width - 90)
.attr("y", 25)
.attr("fill", "black")
.attr("text-anchor", "start")
.text("Emissions (kg CO2e) →"));


// container.append("g")

// set the parameters for the histogram
const histogram = d3.histogram()
.value(function(d) { return d.totalkg; }) // I need to give the vector of value
.domain(x.domain()) // then the domain of the graphic
.thresholds(ticks)//x.ticks(40)); // then the numbers of bins

// And apply this function to data to get the bins
const bins = histogram(data);

const fullbins = histogram(bardata);

// Y axis: scale and draw:
const y = d3.scaleLinear()
.range([height-20, 10]);
y.domain([0, d3.max(bins, function(d) { return d.length; })]); // d3.hist has to be called before the Y axis obviously
container.append("g")
.attr("transform", `translate(${width}), 0`)
.call(d3.axisLeft(y));

container.append("g")
.attr("transform", `translate(${width}), 0`)
.call(d3.axisLeft(y))
.call(g => g.append("text")
.attr("x", -60)
.attr("y", 5)
.attr("fill", "black")
.attr("text-anchor", "start")
.text("↑ Number of Vehicles"))



container.selectAll("rect")
.data(bins)
.enter()
.append("rect")
.attr("x", 1)
.attr("transform", function(d) { return `translate(${x(d.x0)} , ${y(d.length)})`})
.attr("width", function(d) { return x(d.x1) - x(d.x0) -1})
.attr("height", function(d) { return height-20 - y(d.length); })
.style("fill", "#46b5b5")
.style("opacity", 0.8)
// .on('mouseover', function(d, i){
// d3.select(this)
// .transition()
// .style("stroke", "black")
// })
// .on('mouseout', function(d,i){
// d3.select(this)
// .transition()
// .style("stroke", "none")
// })

// const tooltipDiv = container.select(".tooltip");

// if (vehicle1_min !== null && vehicle1_min === vehicle2_min) {
// const spec_bars = container//.selectAll(".bar")
// // .data(bardata)
// // .enter()
// .append("rect")
// .attr("x", function(d) { return x(vehicle1_min); })
// .attr("y", function(d) { return 10; })
// .attr("width", x(5000))
// .attr("height", function(d) { return y(0) - 10; })
// .style("fill", "gray")
// .style("opacity", 0.5)
// .style("stroke", "white")
// container.append("text")
// .attr('x', x(vehicle1_min + 1750))
// .attr('y', 30)
// .style("font", "16px sans-serif")
// .style("font-weight", 900)
// .style("fill", "red")
// .style("opacity", 0.6)
// .text('1')
// container.append("text")
// .attr('x', x(vehicle2_min + 1750))
// .attr('y', 50)
// .style("font", "16px sans-serif")
// .style("font-weight", 900)
// .style("fill", "blue")
// .style("opacity", 0.6)
// .text('2')

if (selectConfig1 !== null) {
if ((Math.round(selectConfig1.totalkg / 5000) * 5000 - selectConfig1.totalkg) < 0) {
var vehicle1_min = Math.round(selectConfig1.totalkg / 5000) * 5000
} else {
var vehicle1_min = (Math.round(selectConfig1.totalkg / 5000) * 5000) - 5000
}
} else {
var vehicle1_min = null
}

// } else {
if (vehicle1_min !== null) {
const spec_bars = container//.selectAll(".bar")
// .data(bardata)
// .enter()
.append("rect")
.attr("x", function(d) { return x(vehicle1_min); })
.attr("y", function(d) { return 10; })
.attr("width", x(5000))
.attr("height", function(d) { return y(0) - 10; })
.style("fill", "gray")
.style("opacity", 0.5)
.style("stroke", "white")
container.append("text")
.attr('x', x(vehicle1_min + 1750))
.attr('y', 30)
.style("font", "16px sans-serif")
.style("font-weight", 900)
.style("fill", "red")
.style("opacity", 0.6)
.text(`${x.linearwidth}`)
}
// if (vehicle2_min !== null) {
// const spec_bars2 = container//.selectAll(".bar")
// // .data(bardata)
// // .enter()
// .append("rect")
// .attr("x", function(d) { return x(vehicle2_min); })
// .attr("y", function(d) { return 10; })
// .attr("width", x(5000))
// .attr("height", function(d) { return y(0) - 10; })
// .style("fill", "gray")
// .style("opacity", 0.5)
// .style("stroke", "white")
// container.append("text")
// .attr('x', x(vehicle2_min + 1750))
// .attr('y', 30)
// .style("font", "16px sans-serif")
// .style("font-weight", 900)
// .style("fill", "blue")
// .style("opacity", 0.6)
// .text('2')
// }
// }



//Add title
const title = container
.append('text')
.attr('x', -5)
//.attr('y', height+margin.bottom+margin.top)
.attr('y', -10)
.style("font", "16px sans-serif")
.style("font-weight", 900)
.text('2000 and 2023 Vehicle Lifetime Emission Comparison')


// const spec_bars = container.selectAll(".bar")
// .data(bardata)
// .enter()
// .append("rect")
// .attr("x", function(d) { return x(d.min); })
// .attr("y", function(d) { return 10; })
// .attr("width", x(2000))
// .attr("height", function(d) { return y(0) - 10; })
// .style("fill", "white")
// .style("opacity", 0)
// // .style("stroke", "black")
// .on('mouseover', function(d, i){
// d3.select(this).transition().style("opacity", 0.6);
// mutable selectedBin = i;
// })
// .on('mouseout', function(d,i){
// d3.select(this)
// .transition()
// // .style("stroke", "none")
// .style("opacity", 0)
// mutable selectedBin = null;
// })



return svg.node();
}
Insert cell
[1, 2, 3]
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