Public
Edited
Feb 29, 2024
Importers
Insert cell
Insert cell
Insert cell
Insert cell
DEFAULT_N = 10000
Insert cell
import {
dist,
distValue,
kde,
to,
exponential,
normalInterval
} with { DEFAULT_N } from "@huw/dist"
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
viewof selfGuidedDepressionSMD = dist`${normalInterval(0.15, 0.31, {
p: 0.95
})}`
Insert cell
Insert cell
Insert cell
viewof socialDesirabilityDiscount = dist`0.7 to 0.9`
Insert cell
Insert cell
viewof publicationDiscount = dist`0.75 to 0.9`
Insert cell
Insert cell
viewof scaleDiscount = dist`0.7 to 0.85`
Insert cell
Insert cell
Insert cell
viewof effectSizeAdjustment = Inputs.range([0.1, 2.0], {
label: "Effect size adjustment",
value: 1
})
Insert cell
viewof selfGuidedDepressionSMDDiscounted = dist`${selfGuidedDepressionSMD} * ${socialDesirabilityDiscount} * ${publicationDiscount} * ${scaleDiscount} * ${effectSizeAdjustment}`
Insert cell
Insert cell
Insert cell
viewof expertLifeSatisfactionStdev = dist`(1.9 to 2.7) * 0.6 + 1.86 * 0.4`
Insert cell
Insert cell
viewof depressionToLifeSatisfaction = dist`0.7 to 1`
Insert cell
Insert cell
viewof selfGuidedWellby = dist`${selfGuidedDepressionSMDDiscounted} * ${expertLifeSatisfactionStdev} * ${depressionToLifeSatisfaction}`
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
viewof retentionAdjustment = Inputs.range([0.1, 2.0], {
label: "Retention adjustment",
value: 1
})
Insert cell
viewof mentalHealthAppRetention = dist`${exponential(
1 / 0.04
)} * ${retentionAdjustment}`
Insert cell
Insert cell
Insert cell
viewof perUserWellby = dist`${selfGuidedWellby} * ${mentalHealthAppRetention}`
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
viewof acquisitionCostAdjustment = Inputs.range([0.1, 2], { label: "CPI adjustment", value: 1 })
Insert cell
viewof marketingCostPerDownload = dist`(0.5 to 6) * ${acquisitionCostAdjustment}`
Insert cell
Insert cell
Insert cell
Insert cell
{
const data = [
{ Name: "Headspace", Employees: 1200, Downloads: 70_000_000 },
{ Name: "Calm", Employees: 400, Downloads: 135_000_000 },
{ Name: "Breeze", Employees: 20, Downloads: 2_000_000 },
{ Name: "BetterHelp", Employees: 5000, Downloads: 80_000_000 },
{ Name: "Paired", Employees: 250, Downloads: 8_000_000 },
{ Name: "Insight Timer", Employees: 350, Downloads: 10_000_000 },
{ Name: "Balance", Employees: 57, Downloads: 8_000_000 },
{ Name: "Shmoody", Employees: 5, Downloads: 1_000_000 },
{ Name: "Daylio", Employees: 5, Downloads: 20_000_000 },
{ Name: "Bearable", Employees: 7, Downloads: 600_000 }
];

return Plot.plot({
x: { type: "log", grid: true },
y: { type: "log", grid: true },
marks: [
Plot.dot(data, {
x: "Employees",
y: "Downloads",
fill: "black",
channels: { Name: "Name" },
tip: true
}),
Plot.linearRegressionY(data, { x: "Employees", y: "Downloads" })
]
});
}
Insert cell
Insert cell
viewof downloadsPerEmployee = dist`25000 to 2500000`
Insert cell
viewof employeesPerDownloadAdjustment = Inputs.range([0.1, 2], { label: "Employees per download adjustment", value: 1 })
Insert cell
viewof employeesPerDownload = dist`(1 / ${downloadsPerEmployee}) * ${employeesPerDownloadAdjustment}`
Insert cell
Insert cell
viewof costPerEmployeeAdjustment = Inputs.range([0.1, 2], {
label: "Cost per employee adjustment",
value: 1
})
Insert cell
viewof costPerEmployee = dist`(25000 to 250000) * ${costPerEmployeeAdjustment}`
Insert cell
viewof developmentCostPerDownload = dist`${employeesPerDownload} * ${costPerEmployee}`
Insert cell
Insert cell
Insert cell
viewof totalCostPerDownload = dist`(${marketingCostPerDownload} + ${developmentCostPerDownload}) * (1.1 to 1.5)`
Insert cell
Insert cell
mentalHealthAppCostEffectiveness = distValue`${perUserWellby} / ${totalCostPerDownload} * 1000`
Insert cell
Insert cell
plot = {
const density = [...kde.density1d(mentalHealthAppCostEffectiveness)];

const nearestQuantilesInDensity = [0.5]
.map((p) => d3.quantile(mentalHealthAppCostEffectiveness, p))
.map((q) => ({
i: d3.bisectCenter(
density.map((d) => d.x),
q
),
q
}))
.map(({ q, i }) => ({ x: q, y: density[i].y }));

return Plot.plot({
y: { ticks: 0, label: "Density Estimate" },
x: {
domain: [
d3.min(mentalHealthAppCostEffectiveness),
d3.max([d3.quantile(mentalHealthAppCostEffectiveness, 0.97), 70])
],
label: "Cost-Effectivess (WELLBYs/US$1000)"
},
color: { legend: true },
height: 256,
width,
marks: [
Plot.areaY(density, { x: "x", y: "y", fillOpacity: 0.1 }),
Plot.lineY(density, { x: "x", y: "y" }),
Plot.ruleY([0]),
Plot.ruleX(
[
{ Name: "GiveDirectly", "Cost-Effectiveness": 8 },
{ Name: "AMF", "Cost-Effectiveness": 70 },
{ Name: "StrongMinds", "Cost-Effectiveness": 17 }
],
{ x: "Cost-Effectiveness", stroke: "Name", tip: true }
),
Plot.ruleX(nearestQuantilesInDensity, {
x: "x",
y2: "y",
strokeDasharray: [5, 3]
}),
Plot.axisX(),
Plot.axisX(
nearestQuantilesInDensity.map(({ x }) => x),
{ textStroke: "#fff", textStrokeWidth: 5 }
),
Plot.crosshairX(density, { x: "x", y: "y" })
]
});
}
Insert cell
Insert cell
Insert cell
Insert cell
dist`${mentalHealthAppCostEffectiveness}`
Insert cell
Inputs.bind(
Inputs.range([0.1, 2], { label: "Hiring adjustment" }),
viewof employeesPerDownloadAdjustment
)
Insert cell
Insert cell
Insert cell
Inputs.bind(Inputs.range([0.1, 2], { label: "Salary adjustment" }), viewof costPerEmployeeAdjustment)
Insert cell
Insert cell
Inputs.bind(Inputs.range([0.1, 2], { label: "CPI adjustment" }), viewof acquisitionCostAdjustment)
Insert cell
Insert cell
Insert cell
Inputs.bind(
Inputs.range([0.1, 2], { label: "Retention adjustment" }),
viewof retentionAdjustment
)
Insert cell
Insert cell
Inputs.bind(
Inputs.range([0.1, 2], { label: "Effect size adjustment" }),
viewof effectSizeAdjustment
)
Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more