Public
Edited
Apr 8
1 fork
Insert cell
Insert cell
sleepData = ({
HeartDisease: { Yes: 6.2, No: 7.0 },
KidneyDisease: { Yes: 6.6, No: 7.1 },
SkinCancer: { Yes: 5.8, No: 7.2 }
})

Insert cell
statsData = ({
HeartDisease: { t_stat: 4.96, p_value: "< 0.0001" },
KidneyDisease: { t_stat: 2.42, p_value: "0.0155" },
SkinCancer: { t_stat: 19.79, p_value: "< 0.0001" }
})

Insert cell
Insert cell

// Creating charts
chartGrid = {
const margin = { top: 50, right: 20, bottom: 60, left: 60 };
const width = 250 - margin.left - margin.right;
const height = 250 - margin.top - margin.bottom;

const svg = d3.create("svg")
.attr("width", 800)
.attr("height", 300);

// Data and bar chart formatting
const diseases = Object.keys(sleepData);
const barColors = { Yes: "#e63946", No: "#457b9d" };

diseases.forEach((disease, i) => {
const group = svg.append("g")
.attr("transform", `translate(${(i % 3) * 260 + margin.left}, ${margin.top})`);

const data = Object.entries(sleepData[disease]).map(([group, value]) => ({
group, value
}));

const x = d3.scaleBand()
.domain(data.map(d => d.group))
.range([0, width])
.padding(0.4);

const y = d3.scaleLinear()
.domain([0, d3.max(data, d => d.value) + 1])
.range([height, 0]);

// Title
group.append("text")
.attr("x", width / 2)
.attr("y", -20)
.attr("text-anchor", "middle")
.style("font-size", "16px")
.style("font-weight", "bold")
.text(disease.replace(/([A-Z])/g, ' $1').trim());

// Axes
group.append("g")
.attr("transform", `translate(0,${height})`)
.call(d3.axisBottom(x));

group.append("g")
.call(d3.axisLeft(y).ticks(5));

// Axis labels
group.append("text")
.attr("x", width / 2)
.attr("y", height + 40)
.attr("text-anchor", "middle")
.style("font-size", "12px")
.text("Has Disease?");

group.append("text")
.attr("transform", "rotate(-90)")
.attr("y", -40)
.attr("x", -height / 2)
.attr("text-anchor", "middle")
.style("font-size", "12px")
.text("Sleep Time (hours)");

// Tooltip
const tooltip = d3.select(DOM.element("div"))
.style("position", "absolute")
.style("pointer-events", "none")
.style("background", "#fff")
.style("padding", "6px 10px")
.style("font", "13px sans-serif")
.style("border", "1px solid #ccc")
.style("box-shadow", "0px 0px 6px rgba(0,0,0,0.1)")
.style("border-radius", "4px")
.style("opacity", 0);

svg.node().appendChild(tooltip.node());

// Bars
group.selectAll(".bar")
.data(data)
.join("rect")
.attr("x", d => x(d.group))
.attr("y", d => y(d.value))
.attr("width", x.bandwidth())
.attr("height", d => height - y(d.value))
.attr("fill", d => barColors[d.group])
.on("mouseover", function(event, d) {
tooltip.style("opacity", 1)
.html(`<strong>${d.group}</strong>: ${d.value.toFixed(2)} hrs`);
})
.on("mousemove", function(event) {
tooltip
.style("left", (event.pageX + 10) + "px")
.style("top", (event.pageY - 30) + "px");
})
.on("mouseout", function() {
tooltip.style("opacity", 0);
});

// Stats summary (t and p)
const stats = statsData[disease];
group.append("text")
.attr("x", width / 2)
.attr("y", height + 55)
.attr("text-anchor", "middle")
.style("font-size", "11px")
.style("fill", "#555")
.text(`t = ${stats.t_stat}, p = ${stats.p_value}`);
});

return svg.node();
}

Insert cell
viewof diseaseSelect = Inputs.select(
Object.keys(sleepData),
{ label: "Choose a disease:", value: "HeartDisease" }
)
Insert cell
md`**Statistical Summary for ${diseaseSelect}:**
- t-statistic = ${statsData[diseaseSelect].t_stat}
- p-value = ${statsData[diseaseSelect].p_value}
- ${(() => {
const { t_stat, p_value } = statsData[diseaseSelect];
const numericP = typeof p_value === "string" && p_value.includes("<")
? 0.0001
: parseFloat(p_value);

if (numericP < 0.05) {
const direction = sleepData[diseaseSelect].Yes < sleepData[diseaseSelect].No ? "less" : "more";
return `There is a **statistically significant** difference in sleep duration. People with ${diseaseSelect.replace(/([A-Z])/g, ' $1').trim()} sleep **${direction}** on average than those without.`;
} else {
return `There is **no statistically significant difference** in sleep duration between people with and without ${diseaseSelect.replace(/([A-Z])/g, ' $1').trim()}.`;
}
})()}`

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