Public
Edited
Oct 25, 2022
Insert cell
md`# Results Malnutrition Act Cleaned Up`
Insert cell
duns = Boolean(1)
Insert cell
viewof dd3 = Inputs.text({label: "Enter your tax bill: ", placeholder: "Enter a tax bill", value: 10000})
Insert cell
chart = circle_chart(packWithMapChildren, false, "International development and humanitarian assistance")
// chart = circle_chart(packWithMapChildren, false, '37799178')
Insert cell
packWithMapChildren = d3.pack()
.size([width - 2, height - 2])
.padding(2)
(d3.hierarchy(d3.rollup(all_data, D => d3.sum(D, d => d["value"]) , ...[d => d.budget_function, d=> d.budget_subfunction, d => d.federal_account_name]))
// (d3.hierarchy(d3.rollup(combined_award_info, D => d3.sum(D, d => d["value"]) , ...[d => d.Org_type,
// d =>d.recipient_duns]))
.sum(([, value]) => value)
.sort((a, b) => b.value - a.value))


Insert cell
d3.rollup(all_data, D => d3.sum(D, d => d["value"]) , ...[d =>d.budget_function, d =>d.budget_subfunction])
Insert cell
chart_hum = circle_chart(packWithMapChildren_hum, true, 'Agency for International Development')
Insert cell

packWithMapChildren_hum = d3.pack()
.size([width - 2, height - 2])
.padding(2)
(d3.hierarchy(d3.rollup(awards_budget, D => d3.sum(D, d => d["value"]) , ...[d =>d.awarding_agency_name, d =>d.federal_account_name, d=> d.recipient_name]))
// (d3.hierarchy(d3.rollup(combined_award_info, D => d3.sum(D, d => d["value"]) , ...[d => d.Org_type,
// d =>d.recipient_duns]))
.sum(([, value]) => value)
.sort((a, b) => b.value - a.value))
Insert cell
(d3.hierarchy(d3.rollup(awards_budget, D => d3.sum(D, d => d["value"]) , ...[d => d.budget_function, d =>d.agency_name, d =>d.federal_account_name]))
// (d3.hierarchy(d3.rollup(combined_award_info, D => d3.sum(D, d => d["value"]) , ...[d => d.Org_type,
// d =>d.recipient_duns]))
.sum(([, value]) => value)
.sort((a, b) => b.value - a.value))
Insert cell
chart2 = circle_chart(packWithMapChildren2, true, '37799178')
Insert cell
packWithMapChildren2 = d3.pack()
.size([width - 2, height - 2])
.padding(10)
// (d3.hierarchy(d3.rollup(all_data, D => d3.sum(D, d => d["value"]) , ...[d =>d.agency_name, d =>d.federal_account_name]))
(d3.hierarchy(d3.rollup(combined_award_info, D => d3.sum(D, d => d["value"]) , ...[d => d.Org_type,
d =>d.recipient_duns, d=> d.agency_name]))
.sum(([, value]) => value)
.sort((a, b) => b.value - a.value))


Insert cell
(d3.hierarchy(d3.rollup(combined_award_info, D => d3.sum(D, d => d["value"]) , ...[d => d.Org_type,
d =>d.recipient_duns, d=> d.agency_name]))
.sum(([, value]) => value)
.sort((a, b) => b.value - a.value))

Insert cell
extra_info = FileAttachment("extra_info_recipient@4.csv").csv()
Insert cell
function circle_chart(root, duns, highlight_me){
//colors used
var background_color = "#f2f3f4"
var highlight_color = "#D79922"
var outline_color = "#4056A1"
var center_circle_color = "#C5CBE3"
var font_color = '#303C6C'
var extra_highlight_color = '#56a140'
var fontsize = d3.scaleSqrt()
.domain([0, 150])
.range([5, 20])
.clamp(false)

let focus = root;
let view;

var current_title = "Click to Zoom"
const svg = d3.create("svg")
.attr("viewBox", `-${width / 2} -${height /(2)} ${width} ${height}`)
.style("display", "block")
.style("margin", "0 0px")
.style("background", background_color)
//.style("cursor", "pointer")
.on("mouseover", (event) => (svgMouseOut(event, root)))

// tooltip + styling
const toolTip = d3.select("body")
.append("div")
.attr("class", "toolTip")
.style("position", "absolute")
.style("display", "none")
.style("border-radius", "1px")
.style("width", width/3)
.style("height", "auto")
.style("background", background_color)
.style("padding", "0px")
.style("border", "1px solid #DDD")
.style("font-size", "1.1rem")
.style("text-align", "left")

//https://stackoverflow.com/questions/149055/how-to-format-numbers-as-currency-strings
// Create our number formatter.
var formatter = new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD',
notation: 'compact',
// These options are needed to round to whole numbers if that's what you want.
//minimumFractionDigits: 0, // (this suffices for whole numbers, but will print 2500.10 as $2,500.1)
//maximumFractionDigits: 0, // (causes 2500.99 to be printed as $2,501)
});

var startTime;
var endTime;
const node = svg.append("g")
.selectAll("circle")
//.data(root)
.data(root.descendants().slice(1))
.join("circle")
.attr("fill", d => d.children ? background_color : toTitleCase(String(d.data[0])) == toTitleCase(String(recipientdrop)) ? highlight_color : center_circle_color)
.attr("stroke", d=> d.children ? highlight_color : toTitleCase(String(d.data[0])) == toTitleCase(String(recipientdrop)) ? highlight_color : outline_color)
.attr("stroke-width", 2)
.on("mouseover", (event, d) => (leafMouseOver(event, d), event.stopPropagation()))
.on("mouseout", (event, d) => (leafMouseOut(event, d), event.stopPropagation()))
.on("click", (event, d) => focus !== d ? (zoom(d)) : console.log(d))
.on("touchstart", (event, d) => focus !== d ? (leafMouseOver(event, d)) : console.log(d))
.on("touchend", (event, d) => focus !== d ? (leafMouseOut(event, d), zoom(d)) : console.log(d))

// show tooltip on mousehover
function leafMouseOver(event, d){
d3.selectAll('.toolTip').style("display", "none" )
d3.select(event.target).attr("stroke-width", 10)
// d3.select(event.target).attr("stroke", highlight_color)
console.log(d)
var formated_money =parseFloat(d.value)*parseFloat(dd3)/8992408699023
var formated_money = formatter.format(formated_money)
var raw_money = formatter.format(parseFloat(d.value))
var descendents = d.ancestors().map(d => (d.data[0])).join(' -> ')

if (duns == true) {
var extra_info_duns = extra_info
.filter(function(e, i) { return e.recipient_duns == d.data[0]})
var Reason = extra_info_duns.length == 0 ? "none": extra_info_duns[0]["Reason_in_list"]
var Name = extra_info_duns.length == 0 ? "none": extra_info_duns[0]["recipient_name"]
var Link = extra_info_duns.length == 0 ? "none": extra_info_duns[0]["Link"]
var info_blurb = extra_info_duns.length == 0 ? "none": extra_info_duns[0]["blurb"]
var html_test = extra_info_duns.length == 0 ?
`<b> ${toTitleCase(String(d.data[0]))} </b> <br>
Your taxes provide : <strong> ${formated_money} </strong><br>
Total money : <strong> ${raw_money} </strong><br>`:
`<b>${toTitleCase(Name)}</b> <br>
Your taxes provide : <strong> ${formated_money} </strong><br>
Total money : <strong> ${raw_money} </strong><br>
<strong>${Reason}</strong><br>
Blurb from <a href =${Link}>link</a>: ${info_blurb}`
} else {
var html_test = `<b>${toTitleCase(String(d.data[0]))}</b> <br>
Your taxes provide : <strong> ${formated_money} </strong><br>
Total money : <strong> ${raw_money} </strong><br>`
}
toolTip
// .style("left", (width - d3.select(event.target).attr("cx")) < width/3 ? event.pageX - width/3 + "px": event.pageX + "px")
.style("left", 0)
.style("top", event.pageY + 10 + "px")
.style("display", "block")
.html(html_test)
}
function svgMouseOut(event, d){
d3.selectAll('.toolTip').style("display", "none" )
d3.selectAll('.title_desc').style("display", "none" )
}
function leafMouseOut(event, d){
// d3.select(event.target).attr("stroke", d=> d.children ? highlight_color : d.data[0] == highlight_me ? highlight_color : outline_color)
d3.select(event.target).attr("stroke-width", d=> d.data[0] == highlight_me ? 3 : 1)
//toolTip.style("display", "none" );
}
function get_name(d){
if (duns == true){
var extra_info_duns = extra_info
.filter(function(e, i) { return e.recipient_duns == d})
var name = extra_info_duns.length == 0 ? toTitleCase(d).substring(0, 25) : toTitleCase(extra_info_duns[0].recipient_name.substring(0, 20))
} else {
name = toTitleCase(d).substring(0, 25)
}
return name

}

function get_award(d){
if (duns == true){
var extra_info_duns = extra_info
.filter(function(e, i) { return e.recipient_duns == d})
console.log(extra_info_duns)
var name = extra_info_duns.length == 0 ? outline_color : extra_info_duns[0].Reason_in_list=="Nobel Prize Laureate"? extra_highlight_color : extra_info_duns[0].Reason_in_list==""? outline_color : highlight_color
} else {
name = outline_color
}
return name
}
node
.attr("stroke", d => get_award(d.data[0]))
const label = svg.append("g")
.style("font", "10px sans-serif")
.attr("text-anchor", "middle")
.selectAll("text")
.data(root.descendants())
.join("text")
.text(d => get_name(String(d.data[0])))
const node_international_affairs = node
//.attr("test", d => console.log(d.descendants().map(d => (d.data[0]))))
.filter(function(d, i) { return d.data[0] == "International Affairs: Budget Function" })
.filter(function(d, i) { return i == 0 })


// if (first_item === recipientdrop) {
zoom(root);
// }

// else {
// node_international_affairs
// .each(function(d) {
// zoom(d); // d is datum
// temp_highlight(recipientdrop)
// })
// }


function temp_highlight(highlight_this){

// node_international_affairs
// .each(function(d) {
// zoom(d) // d is datum
// })
const node_selected = node
.filter(function(d, i) { return d.data[0] == highlight_this})

node_selected
.attr("stroke-width", 5)
.attr('stroke-opacity', 1)
.attr('stroke', highlight_color)
}
function zoomTo(v) {
function grandparent_fun(d){
var grandparent_root = false
if (d.parent == null | duns == false){
var grandparent_root = false
} else {
var grandparent_root = d.parent.parent == focus
}
return grandparent_root
}
const k = width / v[2];
view = v;
//keep labels above circle so can have multipe labeling
label.attr("transform", d => d == focus & duns == true ? `translate(-${0}, -${height })` : d.parent ==focus & duns == true ? `translate(${(d.x - v[0]) * k},${(d.y - v[1]) * k + d.r *k})`:`translate(${(d.x - v[0]) * k},${(d.y - v[1]) * k })`)
.attr("font-size", d => fontsize(d.r * k))
// .style("fill-opacity", d =>d.parent == focus ? 1 : d == focus && d != root ? .9 : 0)
.style("display", d => fontsize(d.r * k) < 10 ? "none": (d.parent == focus |grandparent_fun(d) ) ? "inline" : "none")
// .style("display", d => fontsize(d.r * k) < 10 ? "none":"inline" )
node.attr("transform", d => `translate(${(d.x - v[0]) * k},${(d.y - v[1]) * k})`);
node.attr("r", d => d.r * k)

}
function zoom(d) {

const focus0 = focus;
if (d != focus && d.height == 0){
d = d.parent.parent
}
if (d != focus && d.height == 1){
d = d.parent
}
focus = d;
current_title = focus.data[0]
console.log(current_title)
if (focus0 !=focus | focus == root){
zoomTo([focus.x, focus.y, focus.r * 2])}
}

// var title1 = svg.append("text")
// .attr("x", width / 2 - 100)//`-${width / 2} - 200`)
// .attr("y", -height /2 + 100 )//`-${height / 2} - 200`)
// .attr("text-anchor", "middle")
// .style("cursor", "pointer")
// .style("font-size", "18px")
// // .on("click", (event, d) => (temp_highlight(), event.stopPropagation()) )
// .attr('font-weight', 500)
// .style("display", d => recipientdrop != first_item ? "inline" : "none")
// .text("Highlight Selected")
// .on("mouseover", (event, d) => (d3.select(event.target).style("font-weight", "bold"), temp_highlight(), event.stopPropagation()) )
// .on("mouseout", (event, d) => d3.select(event.target).style("font-weight", "normal"))
var title2 = svg.append("text")
.attr("x", width / 2 - 100)//`-${width / 2} - 200`)
.attr("y", -height /2 + 50 )//`-${height / 2} - 200`)
.attr("text-anchor", "middle")
.style("cursor", "pointer")
.style("font-size", "18px")
// .on("click", (event, d) => (zoom(root), event.stopPropagation()) )
.attr('font-weight', 600)
.text("Zoom Out")
.on("mouseover", (event, d) => (d3.select(event.target).style("font-weight", 900)))
.on("click", (event, d) => ( zoom(root), event.stopPropagation()))
.on("mouseout", (event, d) => d3.select(event.target).style("font-weight", 600))
temp_highlight(highlight_me)
temp_highlight("482156317")
return svg.node();
}
Insert cell
Insert cell
Insert cell
recip_list = ["735229481", "37799178", "79623820", "482156317", "613831580", "963636951", "226500650", "40054827"].concat(recipient_list)
Insert cell
Insert cell
awards_budget = all_data.filter(d => d.awarding_agency_name !='No awards given')
Insert cell
// all_data = combine_agencies_recipients(csv_breakdown_awards, csv_account_balances)
Insert cell
Insert cell
width = 932
Insert cell
height = width
Insert cell
import {select} from "@jashkenas/inputs"
Insert cell
format = d3.format(",d")
Insert cell
function onlyUnique(value, index, self) {
return self.indexOf(value) === index;
}
Insert cell
Insert cell
function toshorten(str) {

return str.substring(0,24) + "..."
}
Insert cell
color = d3.scaleLinear()
.domain([0, 5])
.range(["hsl(152,80%,80%)", "hsl(228,30%,40%)"])
.interpolate(d3.interpolateHcl)
Insert cell
Type JavaScript, then Shift-Enter. Ctrl-space for more options. Arrow ↑/↓ to switch modes.

Insert cell
viewof recipientdrop = select({
title: "Recipients",
description: "Select which which recipient to highlight (most funds recieved first)",

options:[first_item].concat(recip_list).map((d) => ({value: d, label:d.substring(0,30)})) ,
value: "repo"
})
Insert cell
first_item = "Select One"
Insert cell
import {Treemap} from "@d3/treemap"
Insert cell
import {DuckDBClient} from '@cmudig/duckdb'
Insert cell
client2 = DuckDBClient.of([
await FileAttachment("fy2021_award.parquet"),
await FileAttachment("fy2021_pa.parquet"),
await FileAttachment("extra_info_recipient.parquet")
])
Insert cell

recipient_list = recipient_table.map(function (el) { return el.recipient_duns.toString() })
Insert cell
client2
SELECT COALESCE(SUM(transaction_obligated_amount), 0) as value, COALESCE(recipient_duns, 0) as recipient_duns
FROM fy2021_award
GROUP BY recipient_duns
ORDER BY COALESCE(SUM(transaction_obligated_amount), 0) DESC
limit 21





Insert cell
Insert cell
Insert cell
d3 = require("d3@6")
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