Public
Edited
Mar 6, 2024
1 fork
1 star
Insert cell
demography_file = FileAttachment("anes_timeseries_2020_csv_20220210.csv")

Insert cell
demography_file_text = demography_file.text()
Insert cell
d3_demography_file = d3.csvParse(demography_file_text,d3.autoType)
Insert cell
transformedData = {
// Load your data using the FileAttachment feature of Observable
const rawData = d3_demography_file;
// Process the raw data to transform it according to your needs
const data = rawData.map(d => ({
religion: d.V201200,
// groupReligion: d.V201458x,
politicalPreference:d.V201021
}));
return data; // This makes `transformedData` available to other cells
}

Insert cell
embed = require("vega-embed@5")
Insert cell
viewof sankey = embed({
$schema: "https://vega.github.io/schema/vega/v5.2.json",
height: 300,
width: 600,
data: [
{
name: "rawData",
values: [
{ key: { stk1: "aa", stk2: "cc" }, doc_count: 7 },
{ key: { stk1: "aa", stk2: "bb" }, doc_count: 4 },
{ key: { stk1: "bb", stk2: "aa" }, doc_count: 8 },
{ key: { stk1: "bb", stk2: "bb" }, doc_count: 6 },
{ key: { stk1: "bb", stk2: "cc" }, doc_count: 3 },
{ key: { stk1: "cc", stk2: "aa" }, doc_count: 9 }
],
transform: [
{ type: "formula", expr: "datum.key.stk1", as: "stk1" },
{ type: "formula", expr: "datum.key.stk2", as: "stk2" },
{ type: "formula", expr: "datum.doc_count", as: "size" }
]
},
{
name: "nodes",
source: "rawData",
transform: [
{
type: "filter",
expr: "!groupSelector || groupSelector.stk1 == datum.stk1 || groupSelector.stk2 == datum.stk2"
},
{ type: "formula", expr: "datum.stk1+datum.stk2", as: "key" },
{ type: "fold", fields: ["stk1", "stk2"], as: ["stack", "grpId"] },
{
type: "formula",
expr: "datum.stack == 'stk1' ? datum.stk1+' '+datum.stk2 : datum.stk2+' '+datum.stk1",
as: "sortField"
},
{
type: "stack",
groupby: ["stack"],
sort: { field: "sortField", order: "descending" },
field: "size"
},
{ type: "formula", expr: "(datum.y0+datum.y1)/2", as: "yc" }
]
},
{
name: "groups",
source: "nodes",
transform: [
{
type: "aggregate",
groupby: ["stack", "grpId"],
fields: ["size"],
ops: ["sum"],
as: ["total"]
},
{
type: "stack",
groupby: ["stack"],
sort: { field: "grpId", order: "descending" },
field: "total"
},
{ type: "formula", expr: "scale('y', datum.y0)", as: "scaledY0" },
{ type: "formula", expr: "scale('y', datum.y1)", as: "scaledY1" },
{
type: "formula",
expr: "datum.stack == 'stk1'",
as: "rightLabel"
},
{
type: "formula",
expr: "datum.total/domain('y')[1]",
as: "percentage"
}
]
},
{
name: "destinationNodes",
source: "nodes",
transform: [{ type: "filter", expr: "datum.stack == 'stk2'" }]
},
{
name: "edges",
source: "nodes",
transform: [
{ type: "filter", expr: "datum.stack == 'stk1'" },
{
type: "lookup",
from: "destinationNodes",
key: "key",
fields: ["key"],
as: ["target"]
},
{
type: "linkpath",
orient: "horizontal",
shape: "diagonal",
sourceY: { expr: "scale('y', datum.yc)" },
sourceX: { expr: "scale('x', 'stk1') + bandwidth('x')" },
targetY: { expr: "scale('y', datum.target.yc)" },
targetX: { expr: "scale('x', 'stk2')" }
},
{
type: "formula",
expr: "range('y')[0]-scale('y', datum.size)",
as: "strokeWidth"
},
{
type: "formula",
expr: "datum.size/domain('y')[1]",
as: "percentage"
}
]
}
],
scales: [
{
name: "x",
type: "band",
range: "width",
domain: ["stk1", "stk2"],
paddingOuter: 0.05,
paddingInner: 0.95
},
{
name: "y",
type: "linear",
range: "height",
domain: { data: "nodes", field: "y1" }
},
{
name: "color",
type: "ordinal",
range: "category",
domain: { data: "rawData", field: "stk1" }
},
{
name: "stackNames",
type: "ordinal",
range: ["Source", "Destination"],
domain: ["stk1", "stk2"]
}
],
axes: [],
marks: [
{
type: "path",
name: "edgeMark",
from: { data: "edges" },
clip: true,
encode: {
update: {
stroke: [
{
test: "groupSelector && groupSelector.stack=='stk1'",
scale: "color",
field: "stk2"
},
{ scale: "color", field: "stk1" }
],
strokeWidth: { field: "strokeWidth" },
path: { field: "path" },
strokeOpacity: {
signal:
"!groupSelector && (groupHover.stk1 == datum.stk1 || groupHover.stk2 == datum.stk2) ? 0.9 : 0.3"
},
zindex: {
signal:
"!groupSelector && (groupHover.stk1 == datum.stk1 || groupHover.stk2 == datum.stk2) ? 1 : 0"
},
tooltip: {
signal:
"datum.stk1 + ' → ' + datum.stk2 + ' ' + format(datum.size, ',.0f') + ' (' + format(datum.percentage, '.1%') + ')'"
}
},
hover: { strokeOpacity: { value: 1 } }
}
},
{
type: "rect",
name: "groupMark",
from: { data: "groups" },
encode: {
enter: {
fill: { scale: "color", field: "grpId" },
width: { scale: "x", band: 1 }
},
update: {
x: { scale: "x", field: "stack" },
y: { field: "scaledY0" },
y2: { field: "scaledY1" },
fillOpacity: { value: 0.6 },
tooltip: {
signal:
"datum.grpId + ' ' + format(datum.total, ',.0f') + ' (' + format(datum.percentage, '.1%') + ')'"
}
},
hover: { fillOpacity: { value: 1 } }
}
},
{
type: "text",
from: { data: "groups" },
interactive: false,
encode: {
update: {
x: {
signal:
"scale('x', datum.stack) + (datum.rightLabel ? bandwidth('x') + 8 : -8)"
},
yc: { signal: "(datum.scaledY0 + datum.scaledY1)/2" },
align: { signal: "datum.rightLabel ? 'left' : 'right'" },
baseline: { value: "middle" },
fontWeight: { value: "bold" },
text: {
signal:
"abs(datum.scaledY0-datum.scaledY1) > 13 ? datum.grpId : ''"
}
}
}
},
{
type: "group",
data: [
{
name: "dataForShowAll",
values: [{}],
transform: [{ type: "filter", expr: "groupSelector" }]
}
],
encode: {
enter: {
xc: { signal: "width/2" },
y: { value: 30 },
width: { value: 80 },
height: { value: 30 }
}
},
marks: [
{
type: "group",
name: "groupReset",
from: { data: "dataForShowAll" },
encode: {
enter: {
cornerRadius: { value: 6 },
fill: { value: "#f5f5f5" },
stroke: { value: "#c1c1c1" },
strokeWidth: { value: 2 },
height: { field: { group: "height" } },
width: { field: { group: "width" } }
},
update: { opacity: { value: 1 } },
hover: { opacity: { value: 0.7 } }
},
marks: [
{
type: "text",
interactive: false,
encode: {
enter: {
xc: { field: { group: "width" }, mult: 0.5 },
yc: {
field: { group: "height" },
mult: 0.5,
offset: 2
},
align: { value: "center" },
baseline: { value: "middle" },
fontWeight: { value: "bold" },
text: { value: "Show All" }
}
}
}
]
}
]
},
{
type: "rect",
from: { data: "nodes" },
encode: {
enter: {
stroke: { value: "#000" },
strokeWidth: { value: 2 },
width: { scale: "x", band: 1 },
x: { scale: "x", field: "stack" },
y: { field: "y0", scale: "y" },
y2: { field: "y1", scale: "y" }
}
}
}
],
signals: [
{
name: "groupHover",
value: {},
on: [
{
events: "@groupMark:mouseover",
update:
"{stk1:datum.stack=='stk1' && datum.grpId, stk2:datum.stack=='stk2' && datum.grpId}"
},
{ events: "mouseout", update: "{}" }
]
},
{
name: "groupSelector",
value: false,
on: [
{
events: "@groupMark:click!",
update:
"{stack:datum.stack, stk1:datum.stack=='stk1' && datum.grpId, stk2:datum.stack=='stk2' && datum.grpId}"
},
{
events: [
{ type: "click", markname: "groupReset" },
{ type: "dblclick" }
],
update: "false"
}
]
}
]
});

Insert cell
viewof scatterPlot = embed({
// Assume transformedData is ready to use

// "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
description: "A visualization of the relationship between religious factors and political preferences.",
data: {values: await transformedData}, // Make sure to await the Promise if transformedData is from an async operation
vconcat: [
{
name: "religion",
repeat: {
column: ["religion"], // Adjusted for the mapped data
row: ["politicalPreference"]
},
spec: {
height: 150,
mark: { type: "point", stroke: "blue" },
selection: {
brush: { type: "interval", resolve: "global", encodings: ["x", "y"] }
},
encoding: {
x: { field: { repeat: "column" }, type: "nominal" },
y: { field: { repeat: "row" }, type: "nominal" },
}
}
}
// Add more concatenations as needed
]
}
)

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