Published
Edited
Feb 20, 2021
Insert cell
md`# Roller Coaster Assignment Part 2`
Insert cell
md`Authors: Claire Zhu, Andrew Chung

Inforviz Spring 2021
`
Insert cell
md`## Questions

The questions we would like to ask based on our visualization and for others' designs.

Q1: Do custom rollercoasters tend to be more exciting, intense, and/or nasueating than their non-custom counterparts?

Q2: How do excitement, intensity, and nausea vary by roller coaster type?

Q3: Which roller coaster types cause the most excitement, intensity, and nausea on average?
`
Insert cell
Type JavaScript, then Shift-Enter. Ctrl-space for more options. Arrow ↑/↓ to switch modes.

Insert cell
md`## Data Preperation
`
Insert cell
import {vl} from '@vega/vega-lite-api'
Insert cell
import {printTable} from '@uwdata/data-utilities'
Insert cell
d3 = require('d3')
Insert cell
import {Scrubber} from "@mbostock/scrubber"
Insert cell
fileContents = FileAttachment("rollercoasters_paired_assignment.csv")
Insert cell
stat = d3.csvParse(await fileContents.text(), d3.autoType)
Insert cell
printTable(stat.slice(0,10))
Insert cell
cd_stat = stat.filter(d => d.custom_design === 1)
Insert cell
notcd_stat = stat.filter(d => d.custom_design === 0)
Insert cell
stat.forEach(function (element) {
if (element.custom_design === 1){
element.excitement2 = element.excitement*(1)
}
else{
element.excitement2 = element.excitement*(-1)
}
})
Insert cell
stat.forEach(function (element) {
if (element.custom_design === 1){
element.intensity2 = element.intensity*(1)
}
else{
element.intensity2 = element.intensity*(-1)
}
})
Insert cell
stat.forEach(function (element) {
if (element.custom_design === 1){
element.nausea2 = element.nausea*(1)
}
else{
element.nausea2 = element.nausea*(-1)
}
})
Insert cell
printTable(stat.slice(0,10))
Insert cell
md`## Visualization
`
Insert cell
{
const n_avg_line1 = vl.markBar({strokeWidth: 1, opacity: 0.5})
.encode(
vl.x().average("excitement2"),
vl.y().fieldN("rollercoaster_type").sort(['Hypercoaster','Wooden Roller Coaster','Inverted Roller Coaster','Looping Roller Coaster','Vertical Drop Coaster', 'Mine Train Coaster','Corkscrew Roller Coaster', 'Mini Roller Coaster', 'Wooden Wild Mouse', 'Twister Coaster', 'Compact Inverted Coaster','Spiral Coaster']),
vl.color().fieldN("custom_design").scale({
domain: ['0', '1'],
range: ['#77BB55','#9955bb']
}),
vl.tooltip().average("excitement2"),
);

const n_avg1 = vl.markPoint({filled: true, opacity: 1, size: 100})
.encode(
vl.x().average("excitement2"),
vl.y().fieldN("rollercoaster_type").sort(['Hypercoaster','Wooden Roller Coaster','Inverted Roller Coaster','Looping Roller Coaster','Vertical Drop Coaster', 'Mine Train Coaster','Corkscrew Roller Coaster', 'Mini Roller Coaster', 'Wooden Wild Mouse', 'Twister Coaster','Compact Inverted Coaster', 'Spiral Coaster']),
vl.color().fieldN("custom_design").scale({
domain: ['0', '1'],
range: ['#77BB55','#9955bb']
}),
vl.tooltip().average("excitement2"),
);
const n_all1 = vl.markPoint({filled: false, opacity: 0.3, size: 75})
.encode(
vl.x().fieldQ("excitement2").title('Average Excitement'),
vl.y().fieldN("rollercoaster_type").sort(['Hypercoaster','Wooden Roller Coaster','Inverted Roller Coaster','Looping Roller Coaster','Vertical Drop Coaster', 'Mine Train Coaster','Corkscrew Roller Coaster', 'Mini Roller Coaster', 'Wooden Wild Mouse', 'Twister Coaster','Compact Inverted Coaster', 'Spiral Coaster']).title('Roller Coaster Type'),
vl.color().fieldN("custom_design").scale({
domain: ['0', '1'],
range: ['#77BB55','#9955bb']
}).title("Custom Design"),
);

return vl.layer(n_avg_line1, n_avg1, n_all1)
.data(stat)
.title("Average Excitement, Intensity, and Nasuea by RC Type (All Values Positive)")
.width(800)
.height(300)
.render()
}
Insert cell
{
const n_avg_line2 = vl.markBar({strokeWidth: 1, opacity: 0.5})
.encode(
vl.x().average("intensity2"),
vl.y().fieldN("rollercoaster_type").sort(['Inverted Roller Coaster', 'Wooden Roller Coaster', 'Hypercoaster', 'Mine Train Coaster', 'Vertical Drop Coaster', 'Looping Roller Coaster','Corkscrew Roller Coaster', 'Mini Roller Coaster', 'Wooden Wild Mouse', 'Compact Inverted Coaster', 'Stand Up Roller Coaster', 'Twister Coaster']),
vl.color().fieldN("custom_design").scale({
domain: ['0', '1'],
range: ['#77BB55','#9955bb']
}),
vl.tooltip().average("intensity2")
);
const n_avg2 = vl.markPoint({filled: true, opacity: 1, size: 100})
.encode(
vl.x().average("intensity2"),
vl.y().fieldN("rollercoaster_type").sort(['Inverted Roller Coaster', 'Wooden Roller Coaster', 'Hypercoaster', 'Mine Train Coaster', 'Vertical Drop Coaster', 'Looping Roller Coaster','Corkscrew Roller Coaster', 'Mini Roller Coaster', 'Wooden Wild Mouse', 'Compact Inverted Coaster', 'Stand Up Roller Coaster', 'Twister Coaster']),
vl.color().fieldN("custom_design"),
vl.tooltip().average("intensity2"),
);
const n_all2 = vl.markPoint({filled: false, opacity: 0.3, size: 75})
.encode(
vl.x().fieldQ("intensity2").title('Average Intensity'),
vl.y().fieldN("rollercoaster_type").sort(['Inverted Roller Coaster', 'Wooden Roller Coaster', 'Hypercoaster', 'Mine Train Coaster', 'Vertical Drop Coaster', 'Looping Roller Coaster','Corkscrew Roller Coaster', 'Mini Roller Coaster', 'Wooden Wild Mouse', 'Compact Inverted Coaster', 'Stand Up Roller Coaster', 'Twister Coaster']).title('Roller Coaster Type'),
vl.color().fieldN("custom_design").scale({
domain: ['0', '1'],
range: ['#77BB55','#9955bb']
}).title("Custom Design")
);

return vl.layer(n_avg_line2, n_avg2, n_all2)
.data(stat)
.width(800)
.height(300)
.render()
}
Insert cell
{
const n_avg_line3 = vl.markBar({strokeWidth: 1, opacity: 0.5})
.encode(
vl.x().average("nausea2"),
vl.y().fieldN("rollercoaster_type").sort(['Inverted Roller Coaster', 'Wooden Roller Coaster', 'Mine Train Coaster', 'Hypercoaster', 'Mini Roller Coaster', 'Looping Roller Coaster', 'Compact Inverted Coaster', 'Vertical Drop Coaster', 'Corkscrew Roller Coaster', 'Stand Up Roller Coaster', 'Wooden Wild Mouse', 'Twister Coaster', 'Dinghy Slide', 'Spiral Coaster']),
vl.color().fieldN("custom_design").scale({
domain: ['0', '1'],
range: ['#77BB55','#9955bb']
}),
vl.tooltip().average("nausea2"),
);
const n_avg3 = vl.markPoint({filled: true, opacity: 1, size: 100})
.encode(
vl.x().average("nausea2"),
vl.y().fieldN("rollercoaster_type").sort(['Inverted Roller Coaster', 'Wooden Roller Coaster', 'Mine Train Coaster', 'Hypercoaster', 'Mini Roller Coaster', 'Looping Roller Coaster', 'Compact Inverted Coaster', 'Vertical Drop Coaster', 'Corkscrew Roller Coaster', 'Stand Up Roller Coaster', 'Wooden Wild Mouse', 'Twister Coaster', 'Dinghy Slide', 'Spiral Coaster']),
vl.color().fieldN("custom_design"),
vl.tooltip().average("nausea2")
);
const n_all3 = vl.markPoint({filled: false, opacity: 0.3, size: 75})
.encode(
vl.x().fieldQ("nausea2").title('Average Nausea'),
vl.y().fieldN("rollercoaster_type").sort(['Inverted Roller Coaster', 'Wooden Roller Coaster', 'Mine Train Coaster', 'Hypercoaster', 'Mini Roller Coaster', 'Looping Roller Coaster', 'Compact Inverted Coaster', 'Vertical Drop Coaster', 'Corkscrew Roller Coaster', 'Stand Up Roller Coaster', 'Wooden Wild Mouse', 'Twister Coaster', 'Dinghy Slide', 'Spiral Coaster']).title('Roller Coaster Type'),
vl.color().fieldN("custom_design").scale({
domain: ['0', '1'],
range: ['#77BB55','#9955bb']
}).title("Custom Design")
);

return vl.layer(n_avg_line3, n_avg3, n_all3)
.data(stat)
.width(800)
.height(300)
.render()
}
Insert cell
{
const n_avg_line1 = vl.markBar({strokeWidth: 1, opacity: 0.5})
.encode(
vl.x().average("excitement2").scale({domain: [-10, 10]}),
vl.y().fieldN("rollercoaster_type").sort(['Hypercoaster','Wooden Roller Coaster','Inverted Roller Coaster','Looping Roller Coaster','Vertical Drop Coaster', 'Mine Train Coaster','Corkscrew Roller Coaster', 'Mini Roller Coaster', 'Wooden Wild Mouse', 'Twister Coaster', 'Compact Inverted Coaster','Spiral Coaster']),
vl.color().fieldN("custom_design").scale({
domain: ['0', '1'],
range: ['#77BB55','#9955bb']
}),
vl.tooltip().average("excitement2"),
);

const n_avg1 = vl.markPoint({filled: true, opacity: 1, size: 100})
.encode(
vl.x().average("excitement2"),
vl.y().fieldN("rollercoaster_type").sort(['Hypercoaster','Wooden Roller Coaster','Inverted Roller Coaster','Looping Roller Coaster','Vertical Drop Coaster', 'Mine Train Coaster','Corkscrew Roller Coaster', 'Mini Roller Coaster', 'Wooden Wild Mouse', 'Twister Coaster','Compact Inverted Coaster', 'Spiral Coaster']),
vl.color().fieldN("custom_design").scale({
domain: ['0', '1'],
range: ['#77BB55','#9955bb']
}),
vl.tooltip().average("excitement2"),
);
const n_all1 = vl.markPoint({filled: false, opacity: 0.3, size: 75})
.encode(
vl.x().fieldQ("excitement2").title('Average Excitement'),
vl.y().fieldN("rollercoaster_type").sort(['Hypercoaster','Wooden Roller Coaster','Inverted Roller Coaster','Looping Roller Coaster','Vertical Drop Coaster', 'Mine Train Coaster','Corkscrew Roller Coaster', 'Mini Roller Coaster', 'Wooden Wild Mouse', 'Twister Coaster','Compact Inverted Coaster', 'Spiral Coaster']).title('Roller Coaster Type'),
vl.color().fieldN("custom_design").scale({
domain: ['0', '1'],
range: ['#77BB55','#9955bb']
}).title("Custom Design"),
);

const n_avg_line2 = vl.markBar({strokeWidth: 1, opacity: 0.5})
.encode(
vl.x().average("intensity2"),
vl.y().fieldN("rollercoaster_type").sort(['Inverted Roller Coaster', 'Wooden Roller Coaster', 'Hypercoaster', 'Mine Train Coaster', 'Vertical Drop Coaster', 'Looping Roller Coaster','Corkscrew Roller Coaster', 'Mini Roller Coaster', 'Wooden Wild Mouse', 'Compact Inverted Coaster', 'Stand Up Roller Coaster', 'Twister Coaster']),
vl.color().fieldN("custom_design").scale({
domain: ['0', '1'],
range: ['#77BB55','#9955bb']
}),
vl.tooltip().average("intensity2")
);
const n_avg2 = vl.markPoint({filled: true, opacity: 1, size: 100})
.encode(
vl.x().average("intensity2"),
vl.y().fieldN("rollercoaster_type").sort(['Inverted Roller Coaster', 'Wooden Roller Coaster', 'Hypercoaster', 'Mine Train Coaster', 'Vertical Drop Coaster', 'Looping Roller Coaster','Corkscrew Roller Coaster', 'Mini Roller Coaster', 'Wooden Wild Mouse', 'Compact Inverted Coaster', 'Stand Up Roller Coaster', 'Twister Coaster']),
vl.color().fieldN("custom_design"),
vl.tooltip().average("intensity2"),
);
const n_all2 = vl.markPoint({filled: false, opacity: 0.3, size: 75})
.encode(
vl.x().fieldQ("intensity2").title('Average Intensity'),
vl.y().fieldN("rollercoaster_type").sort(['Inverted Roller Coaster', 'Wooden Roller Coaster', 'Hypercoaster', 'Mine Train Coaster', 'Vertical Drop Coaster', 'Looping Roller Coaster','Corkscrew Roller Coaster', 'Mini Roller Coaster', 'Wooden Wild Mouse', 'Compact Inverted Coaster', 'Stand Up Roller Coaster', 'Twister Coaster']).title('Roller Coaster Type'),
vl.color().fieldN("custom_design").scale({
domain: ['0', '1'],
range: ['#77BB55','#9955bb']
}).title("Custom Design")
);
const n_avg_line3 = vl.markBar({strokeWidth: 1, opacity: 0.5})
.encode(
vl.x().average("nausea2").scale({domain: [-10, 10]}),
vl.y().fieldN("rollercoaster_type").sort(['Inverted Roller Coaster', 'Wooden Roller Coaster', 'Mine Train Coaster', 'Hypercoaster', 'Mini Roller Coaster', 'Looping Roller Coaster', 'Compact Inverted Coaster', 'Vertical Drop Coaster', 'Corkscrew Roller Coaster', 'Stand Up Roller Coaster', 'Wooden Wild Mouse', 'Twister Coaster', 'Dinghy Slide', 'Spiral Coaster']),
vl.color().fieldN("custom_design").scale({
domain: ['0', '1'],
range: ['#77BB55','#9955bb']
}),
vl.tooltip().average("nausea2"),
);
const n_avg3 = vl.markPoint({filled: true, opacity: 1, size: 100})
.encode(
vl.x().average("nausea2"),
vl.y().fieldN("rollercoaster_type").sort(['Inverted Roller Coaster', 'Wooden Roller Coaster', 'Mine Train Coaster', 'Hypercoaster', 'Mini Roller Coaster', 'Looping Roller Coaster', 'Compact Inverted Coaster', 'Vertical Drop Coaster', 'Corkscrew Roller Coaster', 'Stand Up Roller Coaster', 'Wooden Wild Mouse', 'Twister Coaster', 'Dinghy Slide', 'Spiral Coaster']),
vl.color().fieldN("custom_design"),
vl.tooltip().average("nausea2")
);
const n_all3 = vl.markPoint({filled: false, opacity: 0.3, size: 75})
.encode(
vl.x().fieldQ("nausea2").title('Average Nausea'),
vl.y().fieldN("rollercoaster_type").sort(['Inverted Roller Coaster', 'Wooden Roller Coaster', 'Mine Train Coaster', 'Hypercoaster', 'Mini Roller Coaster', 'Looping Roller Coaster', 'Compact Inverted Coaster', 'Vertical Drop Coaster', 'Corkscrew Roller Coaster', 'Stand Up Roller Coaster', 'Wooden Wild Mouse', 'Twister Coaster', 'Dinghy Slide', 'Spiral Coaster']).title('Roller Coaster Type'),
vl.color().fieldN("custom_design").scale({
domain: ['0', '1'],
range: ['#77BB55','#9955bb']
}).title("Custom Design")
);

return vl.data(stat)
.title({
text: "Average Excitement, Intensity, Nasuea by Rollercoaster Type (all values positive)",
anchor: "middle",
fontSize: 14
})
.vconcat(
vl.layer(n_avg_line1, n_avg1, n_all1).width(700).height(250),
vl.layer(n_avg_line2, n_avg2, n_all2).width(700).height(250),
vl.layer(n_avg_line3, n_avg3, n_all3).width(700).height(250)
)
.render()


}

Insert cell
md`## Justification

Our initial sketches for Part 1 of the assignment had a lot of overlaps in terms of we both looked at the differences in custom-designed and not custom-designed roller coasters, as well as what elements would affect the level of excitement. Therefore for the joint visualization we decided to further explore how different a roller coasters' three major metrics are based on the given dataset - Excitement, Intensity, and Nausea - by roller coaster type, differentiated by cutom-design decisions.

We recoded the not custom-designed data <element.custom_design === 0> to go in the opposite direction, and made sure all metrics were on the same 0~10 scale, so that we can see a clear, side-by-side comparison for each metric. The visualization mainly highlighted the average values with bar charts, but we also decided to display the whole sets of data in the background so the viewers can understand the overall data spread. The rank of display, demonstrated by the tornado format, is different for each metric as well, because we wanted to show what are the most exciting/intense/nauseating types of roller coasters based on rider feedback.

With a simple and clear layout of our final visualization, we're able to answer the previous three questions based on the above design decisions, and also inform the viewers of some interesting facts about roller coasters.
`
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