Published
Edited
May 25, 2020
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
md`Before they conducted the experiment the first established the theory behing their experiment. They used psychophysical knowledge to lay out what they believed were the ways that people best interpret graphs. These ideas became their null hypothesis for 2 experiments. The first experiment used 55 subjects and used divided and grouped bar charts, two bars or divisions of the graphs were marked with dots and the participants were asked to estimate what percent of the larger bar or divisions the smaller one made up. The idea behind this was while they both allowed for length comparison, the grouped bar chart also provided the ability for subjects to judge position on a common scale making the estimation more accurate. The 2nd experiment used 54 subjects and compared a bar chart (with 5 bars) and a pie chart (divided into 5 pieces). The participants were told the largest bar or pie piece and then had to estimate the percent the other bars or pieces made up of the largest piece. The idea behind this was to compare the ability to judge position on a common scale (bar chart) with the ability to judge angles (pie chart).`
Insert cell
Insert cell
md`I do, the experiments were very specific and only used bar and pie charts between them and only tested length vs position and position vs angle. You could potentially argue that they just chose to use comparisons that would back their theories, though I doubt that was actually their intention but it does feel like they were seeking for support for their ideas. Generally though I do believe that their ideas come from good reasoning but I'm more convinced by their researched theory section than by the experimentation. `
Insert cell
Insert cell
md`Along with the ability to encode 2 variables and judge them by position, we are also able to extract slope from a scatter plot. Extracting slope uses the elementary perceptual task of direction; we look at the general direction that the points follow and interpret it to understand how they are related to each other.`
Insert cell
Insert cell
barChart = {
const svg = d3.create("svg").attr("viewBox", [0, 0, width, height]);

// title!
svg
.append("text")
.attr("x", width / 2)
.attr("y", 30)
.attr("text-anchor", "middle")
.style("font-size", "22px")
.style("text-decoration", "underline")
.text("Animal Crossing Villager Cats Personality Counts");

// x-axis label
svg
.append("text")
.attr("x", width / 2)
.attr("y", height - 3)
.style("font-size", "16px")
.style("text-anchor", "middle")
.text("Personality");

//Create Y axis label
svg
.append("text")
.attr("x", (height / 2) * -1)
.attr("y", margin.left - 27)
.style("text-anchor", "middle")
.style("font-size", "16px")
.attr("transform", "rotate(-90)")
.text("Count");

svg
.append("g")
.attr("class", "bars")
.attr("fill", "steelblue")
.selectAll("rect")
.data(data)
.join("rect")
.attr("x", d => px(d.key))
.attr("y", d => py(d.value))
.attr("height", d => py(0) - py(d.value))
.attr("width", px.bandwidth());

svg
.append("g")
.attr("class", "x-axis")
.call(pxAxis)
.selectAll("text")
.attr("transform", "translate(-10,0)rotate(-45)")
.style("font-size", "5px")
.style("text-anchor", "end");

svg
.append("g")
.attr("class", "y-axis")
.call(pyAxis);

return svg.node();
}
Insert cell
chart = {
const arcs = pie(data);

const svg = d3
.create("svg")
.attr("viewBox", [-width / 2, -height / 2, width, height]);

// title!
svg
.append("text")
.attr("x", 0)
.attr("y", -230)
.attr("text-anchor", "middle")
.style("font-size", "22px")
.style("text-decoration", "underline")
.text("Animal Crossing Villager Cats Personality Counts");

svg
.append("g")
.attr("stroke", "white")
.selectAll("path")
.data(arcs)
.join("path")
.attr("fill", "pink")
.attr("d", arc)
.append("title")
.text(d => `${d.data.key}: ${d.data.value.toLocaleString()}`);

svg
.append("g")
.attr("font-family", "sans-serif")
.attr("font-size", 12)
.attr("text-anchor", "middle")
.selectAll("text")
.data(arcs)
.join("text")
.attr("transform", d => `translate(${arcLabel.centroid(d)})`)
.call(text =>
text
.append("tspan")
.attr("y", "-0.4em")
.attr("font-weight", "bold")
.text(d => d.data.key)
)
.call(text =>
text
.filter(d => d.endAngle - d.startAngle > 0.25)
.append("tspan")
.attr("x", 0)
.attr("y", "0.7em")
.attr("fill-opacity", 0.7)
.text(d => d.data.value.toLocaleString())
);

return svg.node();
}
Insert cell
chart3 = {
const root = treemap(data);

const svg = d3
.create("svg")
.attr("viewBox", [0, 0, width, height])
.style("font", "10px sans-serif");

// title!
svg
.append("text")
.attr("x", 290)
.attr("y", 15)
.attr("text-anchor", "middle")
.style("font-size", "22px")
.style("text-decoration", "underline")
.text("Animal Crossing Villager Cats Personality Counts");

const node = svg
.selectAll("g")
.data(root.descendants())
.join("g")
.attr("transform", d => `translate(${d.x0},${d.y0})`);

const column = node.filter(d => d.depth === 1);

column
.append("text")
.attr("x", 3)
.attr("y", "-1.7em")
.style("font-weight", "bold")
.text(d => d.data.key);

column
.append("text")
.attr("x", 3)
.attr("y", "-0.5em")
.attr("fill-opacity", 0.7)
.text(d => format(d.value));

const cell = node.filter(d => d.depth === 2);

cell
.append("rect")
.attr("fill", d => color(d.data.key))
.attr("fill-opacity", (d, i) => d.value / d.parent.value)
.attr("width", d => 350)
.attr("height", d => d.y1 - d.y0 - 1);

cell
.append("text")
.attr("x", 3)
.attr("y", "1.1em")
.text(d => d.data.key);

cell
.append("text")
.attr("x", 3)
.attr("y", "2.3em")
.attr("fill-opacity", 0.7)
.text(d => format(d.value));

return svg.node();
}
Insert cell
chart4 = {
const root = treemap(data);

const svg = d3
.create("svg")
.attr("viewBox", [0, 0, width, height])
.style("font", "10px sans-serif");

// title!
svg
.append("text")
.attr("x", 290)
.attr("y", 15)
.attr("text-anchor", "middle")
.style("font-size", "22px")
.style("text-decoration", "underline")
.text("Animal Crossing Villager Cats Personality Counts");

const node = svg
.selectAll("g")
.data(root.descendants())
.join("g")
.attr("transform", d => `translate(${d.x0},${d.y0})`);

const column = node.filter(d => d.depth === 1);

column
.append("text")
.attr("x", 3)
.attr("y", "-1.7em")
.style("font-weight", "bold")
.text(d => d.data.key);

column
.append("text")
.attr("x", 3)
.attr("y", "-0.5em")
.attr("fill-opacity", 0.7)
.text(d => format(d.value));

const cell = node.filter(d => d.depth === 2);

cell
.append("rect")
.attr("fill", d => color2(d.data.value))
.attr("fill-opacity", (d, i) => d.value / d.parent.value)
.attr("width", d => 350)
.attr("height", d => d.y1 - d.y0 - 1);

cell
.append("text")
.attr("x", 3)
.attr("y", "1.1em")
.text(d => d.data.key);

cell
.append("text")
.attr("x", 3)
.attr("y", "2.3em")
.attr("fill-opacity", 0.7)
.text(d => format(d.value));

return svg.node();
}
Insert cell
Insert cell
md`A curve difference chart refers to a line chart that includes two or more lines. The purpose of these charts is to present a comparison between the 2 (or more) lines, however, this comparison relies upon the ability for a person to judge the distance between the 2 curves themselves. This kind of ability uses the elementary perceptual task of percieving length, which is one of the lower accuracy tasks. Instead they proposed using a graph with a line to represent the difference (difference line = line1 - line2) which just requires the reader to judge the position of one line on a scale.`
Insert cell
chart5 = {
const svg = d3.create("svg").attr("viewBox", [0, 0, width, height]);

// title!
svg
.append("text")
.attr("x", width / 2)
.attr("y", 30)
.attr("text-anchor", "middle")
.style("font-size", "22px")
.style("text-decoration", "underline")
.text("Obesity by Year, Mexico & Canada");

// x-axis label
svg
.append("text")
.attr("x", width / 2)
.attr("y", height - 3)
.style("font-size", "16px")
.style("text-anchor", "middle")
.text("Year");

//Create Y axis label
svg
.append("text")
.attr("x", (height / 2) * -1)
.attr("y", margin.left - 27)
.style("text-anchor", "middle")
.style("font-size", "16px")
.attr("transform", "rotate(-90)")
.text("Obesity (%)");

const rule = svg
.append("g")
.append("line")
.attr("y1", height)
.attr("y2", 0)
.attr("stroke", "black");

const serie = svg
.append("g")
.style("font", "bold 10px sans-serif")
.selectAll("g")
.data(series)
.join("g");

serie
.append("path")
.attr("fill", "none")
.attr("stroke-width", 1.5)
.attr("stroke-linejoin", "round")
.attr("stroke-linecap", "round")
.attr("stroke", d => cdcol(d.key))
.attr("d", d => line(d.values));

svg
.append("g")
.attr("class", "x-axis")
.call(cdxAxis);

svg
.append("g")
.attr("class", "y-axis")
.call(cdyAxis);

return svg.node();
}
Insert cell
chart6 = {
const svg = d3.create("svg").attr("viewBox", [0, 0, width, height]);

// title!
svg
.append("text")
.attr("x", width / 2)
.attr("y", 30)
.attr("text-anchor", "middle")
.style("font-size", "22px")
.style("text-decoration", "underline")
.text("Obesity Difference Mexico & Canada");

// x-axis label
svg
.append("text")
.attr("x", width / 2)
.attr("y", height - 3)
.style("font-size", "16px")
.style("text-anchor", "middle")
.text("Year");

//Create Y axis label
svg
.append("text")
.attr("x", (height / 2) * -1)
.attr("y", margin.left - 27)
.style("text-anchor", "middle")
.style("font-size", "16px")
.attr("transform", "rotate(-90)")
.text("Obesity Diff (Canada(%) - Mexico(%))");

svg
.append("path")
.datum(diff)
.attr("fill", "none")
.attr("stroke", "red")
.attr("stroke-width", 1.5)
.attr("d", lin);

svg
.append("g")
.attr("class", "x-axis")
.call(cdxAxis)
.selectAll("text")
.style("font-size", "5px");
svg
.append("g")
.attr("class", "y-axis")
.call(diffyAxis);

return svg.node();
}
Insert cell
Insert cell
Insert cell
dataR = {
let rawData = d3
.csvParse(await FileAttachment("villagers.csv").text())
.filter(function(d) {
return d.species == 'cat';
});

let resultData = rawData.map(d => {
return {
species: d.species,
personality: d.personality,
id: d.id
};
});

return resultData;
}
Insert cell
data = d3
.nest()
.key(function(d) {
return d.personality;
})
.rollup(function(v) {
return v.length;
})
.entries(dataR)
Insert cell
px = d3
.scaleBand()
.domain(data.map(d => d.key))
.range([margin.left, width - margin.right])
.padding(0.1)
Insert cell
pYDomain = [d3.min(data, d => d.value), d3.max(data, d => d.value)]
Insert cell
py = d3
.scaleLinear()
.domain(pYDomain)
.range([height - margin.bottom, margin.top])
.nice()
Insert cell
pxAxis = g =>
g
.attr("transform", `translate(0,${height - margin.bottom})`)
.call(d3.axisBottom(px).tickSizeOuter(0))
Insert cell
pyAxis = g =>
g
.attr("transform", `translate(${margin.left},0)`)
.call(d3.axisLeft(py))
.call(g => g.select(".domain").remove())
Insert cell
arc = d3
.arc()
.innerRadius(0)
.outerRadius(200)
Insert cell
arcLabel = {
const radius = 170;
return d3
.arc()
.innerRadius(radius)
.outerRadius(radius);
}
Insert cell
pie = d3
.pie()
.sort(null)
.value(d => d.value)
Insert cell
color = d3.scaleOrdinal(d3.schemeCategory10).domain(data.map(d => d.key))
Insert cell
color2 = d3.scaleOrdinal(d3.schemeCategory10).domain(data.map(d => d.value))
Insert cell
format = d => d.toLocaleString()
Insert cell
treemap = data =>
d3
.treemap()
.round(true)
.tile(d3.treemapSliceDice)
.size([
width - margin.left - margin.right,
height - margin.top - margin.bottom
])(
d3
.hierarchy(
{
values: d3
.nest()
.key(d => 'cat')
.key(d => d.key)
.entries(data)
},
d => d.values
)
.sum(d => d.value)
)
.each(d => {
d.x0 += margin.left;
d.x1 += margin.left;
d.y0 += margin.top;
d.y1 += margin.top;
})
Insert cell
dataO = {
let rawData = d3
.csvParse(await FileAttachment("obesity-cleaned.csv").text())
.filter(function(d) {
return d.Country == 'Mexico' || d.Country == 'Canada';
})
.filter(function(d) {
return d.Sex == 'Both sexes';
});

let resultData = rawData.map(d => {
return {
country: d.Country,
year: d.Year,
obesity: +d['Obesity (%)'].split(/(\s+)/)[0]
};
});

return resultData;
}
Insert cell
cdXDomain = [d3.min(dataO, d => d.year), d3.max(dataO, d => d.year)]
Insert cell
cdYDomain = [d3.min(dataO, d => d.obesity), d3.max(dataO, d => d.obesity)]
Insert cell
cdy = d3
.scaleLinear()
.domain(cdYDomain)
.range([height - margin.bottom, margin.top])
.nice()
Insert cell
cdx = d3
.scaleLinear()
.domain(cdXDomain)
.range([margin.left, width - margin.right])
.nice()
Insert cell
cdyAxis = g =>
g
.attr("transform", `translate(${margin.left},0)`)
.call(d3.axisLeft(cdy))
.call(g => g.select(".domain").remove())
Insert cell
cdxAxis = g =>
g
.attr("transform", `translate(0,${height - margin.bottom})`)
.call(d3.axisBottom(cdx))
.call(g => g.select(".domain").remove())
Insert cell
series = d3
.groups(dataO, d => d.country)
.map(([key, values]) => {
const v = values[0].value;
return {
key,
values: values.map(({ year, obesity }) => ({ year, obesity }))
};
})
Insert cell
line = d3
.line()
.x(d => cdx(d.year))
.y(d => cdy(d.obesity))
Insert cell
cdcol = d3.scaleOrdinal(d3.schemeCategory10).domain(dataO.map(d => d.country))
Insert cell
series[1].values[1].obesity
Insert cell
diffR = {
var diff = [];
for (var x = 0; x < series[1].values.length; x++) {
var temp = series[0].values[x].obesity - series[1].values[x].obesity;
var dict = { year: +series[0].values[x].year, obd: temp };
diff[x] = dict;
}
return diff;
}
Insert cell
diff = {
let rd = diffR.map(d => {
return {
year: d.year,
obd: d.obd
};
});

return rd;
}
Insert cell
diffYDomain = [d3.min(diff, d => d.obd), d3.max(diff, d => d.obd)]
Insert cell
diffy = d3
.scaleLinear()
.domain(diffYDomain)
.range([height - margin.bottom, margin.top])
.nice()
Insert cell
diffyAxis = g =>
g
.attr("transform", `translate(${margin.left},0)`)
.call(d3.axisLeft(diffy))
.call(g => g.select(".domain").remove())
Insert cell
lin = d3
.line()
.defined(d => !isNaN(d.obd))
.x(d => cdx(d.year))
.y(d => diffy(d.obd))
Insert cell
import { displayCaution } from "@info474/utilities"
Insert cell
margin = ({ top: 50, right: 30, bottom: 50, left: 40 })
Insert cell
Insert cell
d3 = require("d3@5", "d3-array@2")
Insert cell
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