Published
Edited
May 16, 2019
Insert cell
md`# Big Data Viz: Analysis Attempt Final: https://observablehq.com/@d3/parallel-sets`
Insert cell
Insert cell
//1. add url for country dataset
countryUrl = "https://gist.githubusercontent.com/dpowers120/cdcdb1273d3a068ae950691a5cb0924b/raw/b6764f880ba05bc949958e86f6b17dc49ed4f1f9/countryNames.csv"
Insert cell
//1. upload countryname dataset

Insert cell
//1. add row to dataset for countrycode -99
testCsv = {
let testcsv = d3.csv(countryUrl, d3.autoType)
return testcsv
}
Insert cell
// define index value
countryCsv1 = {
let unique = Object.keys(z.valueCounts(z.getCol("countryName", testCsv)))
let arrayCombos = []
let countryCsv = []
for (var i in unique){
arrayCombos.push({name: unique[i], index: i})
}
for (var i in testCsv){
let rowTest = testCsv[i]
for (var a in arrayCombos){
let rowCombo = arrayCombos[a]
if (rowCombo.name == rowTest.countryName){
countryCsv.push(rowCombo.index)
}
}
}
return z.addCol("index", countryCsv, testCsv)

}
Insert cell
countryCsv={
for (var i in countryCsv1) {
if (countryCsv1[i].countryName=="UNITED ARAB EMIRATES"){
countryCsv1[i].countryName="UAE"
} else if (countryCsv1[i].countryName=="NETHERLANDS ANTILLES"){
countryCsv1[i].countryName="NETHERLANDS"
} else if (countryCsv1[i].countryName=="CONGO, THE DEMOCRATIC REPUBLIC OF THE"){
countryCsv1[i].countryName="DRC"
} else if (countryCsv1[i].countryName=="HONG KONG, SAR OF CHINA"){
countryCsv1[i].countryName="HONG KONG"
} else if (countryCsv1[i].countryName=="KOREA, DEMOCRATIC PEOPLES REPUBLIC OF"){
countryCsv1[i].countryName="N. KOREA"
} else if (countryCsv1[i].countryName=="KOREA, REPUBLIC OF"){
countryCsv1[i].countryName="S. KOREA"
} else if (countryCsv1[i].countryName=="MACEDONIA, THE FORMER YUGOSLAV REPUBLIC OF"){
countryCsv1[i].countryName="MACEDONIA"
} else if (countryCsv1[i].countryName=="MOLDOVA, REPUBLIC OF"){
countryCsv1[i].countryName="MOLDOVA"
} else if (countryCsv1[i].countryName=="LAO PEOPLES DEMOCRATIC REPUBLIC"){
countryCsv1[i].countryName="LAOS"
} else if (countryCsv1[i].countryName=="Unknown Country"){
countryCsv1[i].countryName="UNKNOWN"
} else if (countryCsv1[i].countryName=="RUSSIAN FEDERATION"){
countryCsv1[i].countryName="RUSSIA"
} else if (countryCsv1[i].countryName=="SYRIAN ARAB REPUBLIC"){
countryCsv1[i].countryName="SYRIA"
} else if (countryCsv1[i].countryName=="UNITED STATES OF AMERICA"){
countryCsv1[i].countryName="UNITED STATES"
} else if (countryCsv1[i].countryName=="TAIWAN, PROVINCE OF CHINA"){
countryCsv1[i].countryName="TAIWAN"
} else if (countryCsv1[i].countryName=="TANZANIA, UNITED REPUBLIC OF"){
countryCsv1[i].countryName="TANZANIA"
} else if (countryCsv1[i].countryName=="MONTENEGRO, PROVINCE OF SERBIA AND MONTENEGRO"){
countryCsv1[i].countryName="MONTENEGRO"
} else if (countryCsv1[i].countryName=="SERBIA, PROVINCE OF SERBIA AND MONTENEGRO"){
countryCsv1[i].countryName="SERBIA"
}
}
return countryCsv1
}
Insert cell
z.filter(r => r.countryCode == "CN", countryCsv)
Insert cell
countryCsv.push({countryCode: "-99", countryName: "Unknown Country", index: "0"})
Insert cell
//check if push worked
countryCsv.slice(251, 254)
Insert cell
//test if index worked
Object.keys(z.valueCounts(z.getCol("index", countryCsv)))
Insert cell
//1. add url for other dataset
traffickingUrl = "https://gist.githubusercontent.com/dpowers120/1889a5540a219e68eadc3c59c47b4799/raw/3cba0769be143641e6abba3cc6ad4f28b4767c9d/Iom_TraffickingData_GlobalDataset_3Sept2018_WorkingFile.csv"
Insert cell
//1. upload other dataset
csvOne = d3.csv(traffickingUrl, d3.autoType, function(d){
return {
origin: d.citizenship,
destination: d.CountryOfExploitation
}
}
)
Insert cell
//1. reformat each row so that origin and destination changed to -99
traffickingCsv = {
let empty = []
for (var i in csvOne){
let row = csvOne[i]
let newOrigin = row.origin
let newDest = row.destination
if (row.origin == "ZZ" || row.origin == "Y1" || row.origin == undefined){
newOrigin = "-99"
}
if (row.destination == "ZZ" || row.destination == "Y1" || row.destination == undefined){
newDest = "-99"
}
empty.push({origin: newOrigin, destination: newDest})
}
return empty
}
Insert cell
// check if worked
z.valueCounts(z.getCol("origin", traffickingCsv))
Insert cell
// check if worked
z.valueCounts(z.getCol("destination", traffickingCsv))
Insert cell
md`## 2.Group CSV and Country, and Add Column Counting Combination`
Insert cell
//group by key combination
groupedTrafficking = {
let grouped = d3.nest()
.key(function(d) {return [d.origin, d.destination]})
.rollup(function(v) { return v.length})
.entries(traffickingCsv)
return grouped
}
Insert cell
//test group of unique combinations
groupedTraffickingTest = {
let grouped = d3.nest()
.key(function(d) {return d.origin})
.key(function(d) {return d.destination})
.rollup(function(v) { return v.length})
.entries(traffickingCsv)
return grouped
}
Insert cell
// test count of unique combinations

{
let countUnique = 0
for (var i in groupedTraffickingTest){
let row = groupedTraffickingTest[i]
let rowVals = row.values
for (var a in rowVals){
countUnique = countUnique + 1
}
}
return countUnique

}
Insert cell
//split into origin/destination
splitTrafficking = {
let empty = []
for (var i in groupedTrafficking){
let row = groupedTrafficking[i]
let split = row["key"].split(",")
let origin = split[0]
let destination = split[1]
empty.push({origin: origin, destination: destination, value: row["value"]})
}
return empty
}
Insert cell
countryCsv
Insert cell
//add country names in as source/target columns
countryTrafficking = {
let empty = []
for (var i in splitTrafficking){ // for each row in splittrafficking
let row = splitTrafficking[i] // set row = to row in splittrafficking dataset
let source = ""
let destination = ""
let gdpRanked = "No Data Available"
// let sourceIndex = ""
// let targetIndex = ""
for (var a in countryCsv){ // for each row in country CSV
let rowCountry = countryCsv[a] // set rowCountry = to row in country csv
if (rowCountry.countryCode == row.origin){ // if row in country dataset is equal to row in country csv
source = titleCase(rowCountry.countryName)
// sourceIndex = rowCountry.index
}
if (rowCountry.countryCode == row.destination){
destination = titleCase(rowCountry.countryName)
// targetIndex = rowCountry.index
}
}
for (var d in gdpRank){
let gdpRow = gdpRank[d]
if (source == gdpRow.Economy){
gdpRanked = gdpRow.Ranking
}
}
empty.push({source: source, target: destination, origin: row.origin, destination: row.destination, value: row.value, gdpRanking: gdpRanked})
}
return empty
}
Insert cell
gdpRank
Insert cell
//errorcheck: if target or source = "", filter
z.filter(r => r["target"] == "" || r["source"] == "", countryTrafficking)
Insert cell
//errorcheck: if target or source = "", filter
z.filter(r => r["target"] == undefined || r["source"] == undefined, countryTrafficking)
Insert cell
md`### 2A. Define Dataset for Internal Trafficking`
Insert cell
//filter dataset into top 20 internal
internalTop20 = {
let empty = []
for (var i in countryTrafficking){
let row = countryTrafficking[i]
if (row.source == row.target && row.source != "Unknown Country") {
empty.push(row)
}
}
return z.slice(0, 20, z.sortByCol("value", "desc", empty))
}
Insert cell
//filter countrytrafficking dataset to top 20 internal
internalFiltered = {
let empty = []
let internalList = z.getCol("source", internalTop20)
for (var i in countryTrafficking){
let row = countryTrafficking[i]
for (var a in internalList){
let internalName = internalList[a]
if (internalName == row.source){
empty.push(row)
}
}
}
return empty
}
Insert cell
z.valueCounts(Object.keys(z.valueCounts((z.getCol("source",internalFiltered)))))
Insert cell
md`### 2b. Define Dataset for External Trafficking`
Insert cell
//filter dataset into top 20 external
externalTop20 = {
let empty = []
for (var i in countryTrafficking){
let row = countryTrafficking[i]
if (row.source != row.target && row.source != "Unknown Country") {
empty.push(row)
}
}
let groupedExternal = d3.nest()
.key(function(d) {return d.source})
.rollup(function(v) {return d3.sum(v, function(d) {return d.value})})
.entries(empty)
return z.slice(0, 20, z.sortByCol("value", "desc", groupedExternal))
}
Insert cell
//filter countrytrafficking dataset to top 20 external
externalFiltered = {
let empty = []
let internalList = z.getCol("key", externalTop20)
for (var i in countryTrafficking){
let row = countryTrafficking[i]
for (var a in internalList){
let internalName = internalList[a]
if (internalName == row.source){
empty.push(row)
}
}
}
return empty
}
Insert cell
md`### 2c. Create GDP Dataset for Sankey`
Insert cell
//read in csv
gdpRank = d3.csv("https://gist.githubusercontent.com/dpowers120/172a9d74c2bea696ca19bf98f7d9ea2f/raw/542c9cfcd3d9b5d43b036da28b07c754a6f68715/worldBankGdp.csv", d3.autoType)
Insert cell
//try to match names to countryTraffickingDataset
traffickGdp = {
let empty = []
let unique = Object.keys(z.valueCounts(z.getCol("source", countryTrafficking)))
for (var i in unique){
let notMatch = "No Data Available"
let row = unique[i]
for (var a in gdpRank){
let gdpRow = gdpRank[a]
if (gdpRow.Economy == row){
notMatch = gdpRow.Ranking
}
}
if (row != "Unknown Country"){
empty.push({countryName: row, gdpRanking: notMatch})
}
}
// let traffickGdpFix = z.addCol("gdpRanking", empty, unique)
// let unmatched = z.filter(r => r.gdpRanking == "No Data Available", traffickGdpFix)
// z.valueCounts(z.getCol("source", unmatched))
return empty
}
Insert cell
// filter traffickGdp to top 20
gdpTop20 = z.slice(0, 20, z.sortByCol("gdpRanking", "asc", traffickGdp))
Insert cell
//filter countrytrafficking dataset to top 20 gdp
gdpTopFiltered = {
let empty = []
let ranks = []
for (var i in countryTrafficking){
let row = countryTrafficking[i]
for (var a in gdpTop20){
let internalName = gdpTop20[a]
if (internalName.countryName == row.source){
empty.push(row)
ranks.push(internalName.gdpRanking)
}
}
}
return z.addCol("gdpRanking", ranks, empty)
}
Insert cell
md`### 2d. Create GDP BOttom Dataset for Sankey`
Insert cell
// filter traffickGdp to bottom 20
gdpBot20 = z.slice(0, 20, z.sortByCol("gdpRanking", "desc", traffickGdp))
Insert cell
//filter countrytrafficking dataset to top 20 gdp
gdpBotFiltered = {
let empty = []
let ranks = []
for (var i in countryTrafficking){
let row = countryTrafficking[i]
for (var a in gdpBot20){
let internalName = gdpBot20[a]
if (internalName.countryName == row.source){
empty.push(row)
ranks.push(internalName.gdpRanking)
}
}
}
return z.addCol("gdpRanking", ranks, empty)
}
Insert cell
md`## 3. Define Node Dataset for Sankey Diagram`
Insert cell
countryTrafficking
Insert cell
// create node dataset
nodesList = {
let arrayLinks = []
let arrayNodes = []
let empty = []
for (var i in countryTrafficking){
let row = countryTrafficking[i]
// arrayLinks.push({source: parseInt(row.sourceIndex), target: parseInt(row.targetIndex), names: [row.source, row.target], value: row.value})
arrayNodes.push({name: row.source})
// if (arrayNodes.includes(row.source)) {
// console.log(123123123)
// arrayNodes.push({name: row.source})
// }
}
// for (var a in countryTrafficking){
// let row = countryTrafficking[a]
// arrayNodes.push({name: row.target})
// }
return arrayNodes
}
Insert cell
nodesListDest = {
let arrayLinks = []
let arrayNodes = []
let empty = []
// for (var i in countryTrafficking){
// let row = countryTrafficking[i]
// // arrayLinks.push({source: parseInt(row.sourceIndex), target: parseInt(row.targetIndex), names: [row.source, row.target], value: row.value})
// arrayNodes.push({name: row.source})
// // if (arrayNodes.includes(row.source)) {
// // console.log(123123123)
// // arrayNodes.push({name: row.source})
// // }
// }
for (var a in countryTrafficking){
let row = countryTrafficking[a]
arrayNodes.push({name: row.target})
}
return arrayNodes
}
Insert cell
//get list of unique nodes in order
nodesListTwo = {
let empty = []
let valsArray = z.valueCounts(z.getCol("name", nodesList))
let listNodes = Object.keys(valsArray)
for (var i in listNodes){
let selected = listNodes[i]
empty.push({name: selected})
}
return empty
}
Insert cell
nodesListTarget = {
let empty = []
let valsArray = z.valueCounts(z.getCol("name", nodesListDest))
let listNodes = Object.keys(valsArray)
for (var i in listNodes){
let selected = listNodes[i]
empty.push({name: selected})
}
return empty
}

Insert cell
nodesListCombined = {
let array = []
array = {origin: nodesListTwo, destination: nodesListTarget}
return array
}
Insert cell
ultimateNodes = nodesListTwo.concat(nodesListTarget)
Insert cell
// add nodes/arrays based on position in nodes dataset
traffickingSankey = {
let arrayLinks = []
for (var i in countryTrafficking){
let row = countryTrafficking[i] // row = each row
let source = ""
let target = ""
let gdpRanking = row.gdpRanking
let names = [row.source, row.target] // names = source, destination for each
let value = row.value // value = numberof people going from a to b
let originList = nodesListCombined["origin"] // originlist = list of origins from node list combined
let targetList = nodesListCombined["destination"] // destination list = list of destinations from node list combined
for (var a in originList){ // for each item in origin list
let selectedNode = originList[a].name // set selectedNode to selected origin in origin list
if (selectedNode == row.source ){ // if selected node is equal to source in row
source = a // source = index in origin list
}
}
for (var g in targetList){ // for each item in array
let targetSelected = targetList[g].name // set selected target to selected target in targetlist
if (targetSelected == row.target){ // if selected target is equal to target in the row
target = g // target = index of target
console.log(target)
}
}

arrayLinks.push({source: parseInt(source), target: parseInt(target) + originList.length, names: names, value: value, gdpRanking: gdpRanking}) // push as source, the source source index; as target, the target index + the length of the originlist; as names, the names array; as values, the value
}
let arrayCombined = {nodes: ultimateNodes, links: arrayLinks}
return arrayCombined
}
Insert cell
md`### 3a. Prepare Internal Dataset for Sankey`
Insert cell
internalFiltered
Insert cell
// create node dataset
nodesListInternal = {
let arrayLinks = []
let arrayNodes = []
let empty = []
for (var i in internalFiltered){
let row = internalFiltered[i]
// arrayLinks.push({source: parseInt(row.sourceIndex), target: parseInt(row.targetIndex), names: [row.source, row.target], value: row.value})
arrayNodes.push({name: row.source})
// if (arrayNodes.includes(row.source)) {
// console.log(123123123)
// arrayNodes.push({name: row.source})
// }
}
// for (var a in countryTrafficking){
// let row = countryTrafficking[a]
// arrayNodes.push({name: row.target})
// }
return arrayNodes
}
Insert cell
nodesListDestInternal = {
let arrayLinks = []
let arrayNodes = []
let empty = []
// for (var i in countryTrafficking){
// let row = countryTrafficking[i]
// // arrayLinks.push({source: parseInt(row.sourceIndex), target: parseInt(row.targetIndex), names: [row.source, row.target], value: row.value})
// arrayNodes.push({name: row.source})
// // if (arrayNodes.includes(row.source)) {
// // console.log(123123123)
// // arrayNodes.push({name: row.source})
// // }
// }
for (var a in internalFiltered){
let row = internalFiltered[a]
arrayNodes.push({name: row.target})
}
return arrayNodes
}
Insert cell
//get list of unique nodes in order
nodesListTwoInternal = {
let empty = []
let valsArray = z.valueCounts(z.getCol("name", nodesListInternal))
let listNodes = Object.keys(valsArray)
for (var i in listNodes){
let selected = listNodes[i]
empty.push({name: selected})
}
return empty
}
Insert cell
nodesListTargetInternal = {
let empty = []
let valsArray = z.valueCounts(z.getCol("name", nodesListDestInternal))
let listNodes = Object.keys(valsArray)
for (var i in listNodes){
let selected = listNodes[i]
empty.push({name: selected})
}
return empty
}

Insert cell
nodesListCombinedInternal = {
let array = []
array = {origin: nodesListTwoInternal, destination: nodesListTargetInternal}
return array
}
Insert cell
ultimateNodesInternal = nodesListCombinedInternal["origin"].concat(nodesListCombinedInternal["destination"])
Insert cell
internalFiltered
Insert cell
// add nodes/arrays based on position in nodes dataset
traffickingSankeyInternal = {
let arrayLinks = []
for (var i in internalFiltered){
let row = internalFiltered[i] // row = each row
let source = ""
let target = ""
let names = [row.source, row.target]
let value = row.value
let gdpRanking = row.gdpRanking
let originList = nodesListCombinedInternal["origin"]
let targetList = nodesListCombinedInternal["destination"]
for (var a in originList){
let selectedNode = originList[a].name
if (row.source == selectedNode){
source = a
console.log("Source:" + a + row.source + selectedNode + " " + originList[0].name)
}
}
for (var g in targetList){ // for each item in array
let targetSelected = targetList[g].name // if selected target
if (targetSelected == row.target){
target = g
}
}
arrayLinks.push({source: parseInt(source), target: parseInt(target) + originList.length, names: names, value: value, gdpRanking: gdpRanking})
}
let arrayCombined = {nodes: ultimateNodesInternal, links: arrayLinks}
return arrayCombined
}
Insert cell
md`### 3B. Prepare External Dataset for Sankey`
Insert cell
// create node dataset
nodesListExternal = {
let arrayLinks = []
let arrayNodes = []
let empty = []
for (var i in externalFiltered){
let row = externalFiltered[i]
// arrayLinks.push({source: parseInt(row.sourceIndex), target: parseInt(row.targetIndex), names: [row.source, row.target], value: row.value})
arrayNodes.push({name: row.source})
// if (arrayNodes.includes(row.source)) {
// console.log(123123123)
// arrayNodes.push({name: row.source})
// }
}
// for (var a in countryTrafficking){
// let row = countryTrafficking[a]
// arrayNodes.push({name: row.target})
// }
return arrayNodes
}
Insert cell
nodesListDestExternal = {
let arrayLinks = []
let arrayNodes = []
let empty = []
// for (var i in countryTrafficking){
// let row = countryTrafficking[i]
// // arrayLinks.push({source: parseInt(row.sourceIndex), target: parseInt(row.targetIndex), names: [row.source, row.target], value: row.value})
// arrayNodes.push({name: row.source})
// // if (arrayNodes.includes(row.source)) {
// // console.log(123123123)
// // arrayNodes.push({name: row.source})
// // }
// }
for (var a in externalFiltered){
let row = externalFiltered[a]
arrayNodes.push({name: row.target})
}
return arrayNodes
}
Insert cell
//get list of unique nodes in order
nodesListTwoExternal = {
let empty = []
let valsArray = z.valueCounts(z.getCol("name", nodesListExternal))
let listNodes = Object.keys(valsArray)
for (var i in listNodes){
let selected = listNodes[i]
empty.push({name: selected})
}
return empty
}
Insert cell
nodesListTargetExternal = {
let empty = []
let valsArray = z.valueCounts(z.getCol("name", nodesListDestExternal))
let listNodes = Object.keys(valsArray)
for (var i in listNodes){
let selected = listNodes[i]
empty.push({name: selected})
}
return empty
}
Insert cell
nodesListCombinedExternal = {
let array = []
array = {origin: nodesListTwoExternal, destination: nodesListTargetExternal}
return array
}
Insert cell
ultimateNodesExternal = nodesListCombinedExternal["origin"].concat(nodesListCombinedExternal["destination"])
Insert cell
// add nodes/arrays based on position in nodes dataset
traffickingSankeyExternal = {
let arrayLinks = []
for (var i in externalFiltered){
let row = externalFiltered[i] // row = each row
let source = ""
let target = ""
let gdpRanking = row.gdpRanking
let names = [row.source, row.target]
let value = row.value
let originList = nodesListCombinedExternal["origin"]
let targetList = nodesListCombinedExternal["destination"]
for (var a in originList){
let selectedNode = originList[a].name
if (selectedNode == row.source ){
source = a
}
}
for (var g in targetList){ // for each item in array
let targetSelected = targetList[g].name // if selected target
if (targetSelected == row.target){
target = g
console.log(target)
}
}
arrayLinks.push({source: parseInt(source), target: parseInt(target) + originList.length, names: names, value: value, gdpRanking: gdpRanking})
}
let arrayCombined = {nodes: ultimateNodesExternal, links: arrayLinks}
return arrayCombined
}
Insert cell
md`### 3c. Prepare Top GDP Data for Visualization`
Insert cell
// create node dataset
nodesListGdpTop = {
let arrayLinks = []
let arrayNodes = []
let empty = []
for (var i in gdpTopFiltered){
let row = gdpTopFiltered[i]
// arrayLinks.push({source: parseInt(row.sourceIndex), target: parseInt(row.targetIndex), names: [row.source, row.target], value: row.value})
arrayNodes.push({name: row.source, gdpRanking: row.gdpRanking})
// if (arrayNodes.includes(row.source)) {
// console.log(123123123)
// arrayNodes.push({name: row.source})
// }
}
// for (var a in countryTrafficking){
// let row = countryTrafficking[a]
// arrayNodes.push({name: row.target})
// }
return arrayNodes
}
Insert cell
nodesListDestGdpTop = {
let arrayLinks = []
let arrayNodes = []
let empty = []
// for (var i in countryTrafficking){
// let row = countryTrafficking[i]
// // arrayLinks.push({source: parseInt(row.sourceIndex), target: parseInt(row.targetIndex), names: [row.source, row.target], value: row.value})
// arrayNodes.push({name: row.source})
// // if (arrayNodes.includes(row.source)) {
// // console.log(123123123)
// // arrayNodes.push({name: row.source})
// // }
// }
for (var a in gdpTopFiltered){
let row = gdpTopFiltered[a]
arrayNodes.push({name: row.target})
}
return arrayNodes
}
Insert cell
//get list of unique nodes in order
nodesListTwoGdpTop = {
let empty = []
let valsArray = z.valueCounts(z.getCol("name", nodesListGdpTop))
let listNodes = Object.keys(valsArray)
for (var i in listNodes){
let selected = listNodes[i]
empty.push({name: selected})
}
return empty
}
Insert cell
nodesListTargetGdpTop = {
let empty = []
let valsArray = z.valueCounts(z.getCol("name", nodesListDestGdpTop))
let listNodes = Object.keys(valsArray)
for (var i in listNodes){
let selected = listNodes[i]
empty.push({name: selected})
}
return empty
}
Insert cell
nodesListCombinedGdpTop = {
let array = []
array = {origin: nodesListTwoGdpTop, destination: nodesListTargetGdpTop}
return array
}

Insert cell
traffickGdp
Insert cell
ultimateNodesGdpTop = {
let nodesListNoGdp = nodesListTwoGdpTop.concat(nodesListTargetGdpTop)
let empty = []
let ranking = "Not Ranked"
for (var i in nodesListNoGdp){
let nodesRow = nodesListNoGdp[i]
for (var a in gdpRank){
let gdpRow = gdpRank[a]
if (gdpRow.Economy == nodesRow.name){
ranking = gdpRow.Ranking
}
}
empty.push(ranking)
}
return z.addCol("gdpRanking", empty, nodesListNoGdp)
}
Insert cell
// add nodes/arrays based on position in nodes dataset
traffickingSankeyGdpTop = {
let arrayLinks = []
for (var i in gdpTopFiltered){
let row = gdpTopFiltered[i] // row = each row
let source = ""
let target = ""
let names = [row.source, row.target]
let value = row.value
let gdpRanking = row.gdpRanking
let originList = nodesListCombinedGdpTop["origin"]
let targetList = nodesListCombinedGdpTop["destination"]
for (var a in originList){
let selectedNode = originList[a].name
if (selectedNode == row.source ){
source = a
}
}
for (var g in targetList){ // for each item in array
let targetSelected = targetList[g].name // if selected target
if (targetSelected == row.target){
target = g
console.log(target)
}
}
arrayLinks.push({source: parseInt(source), target: parseInt(target) + originList.length, names: names, value: value, gdpRanking: gdpRanking})
}
let arrayCombined = {nodes: ultimateNodesGdpTop, links: arrayLinks}
return arrayCombined
}
Insert cell
md`### 3d. Prepare Bottom GDP Data for Visualization`
Insert cell
// create node dataset
nodesListGdpBot = {
let arrayLinks = []
let arrayNodes = []
let empty = []
for (var i in gdpBotFiltered){
let row = gdpBotFiltered[i]
// arrayLinks.push({source: parseInt(row.sourceIndex), target: parseInt(row.targetIndex), names: [row.source, row.target], value: row.value})
arrayNodes.push({name: row.source})
// if (arrayNodes.includes(row.source)) {
// console.log(123123123)
// arrayNodes.push({name: row.source})
// }
}
// for (var a in countryTrafficking){
// let row = countryTrafficking[a]
// arrayNodes.push({name: row.target})
// }
return arrayNodes
}
Insert cell
nodesListDestGdpBot = {
let arrayLinks = []
let arrayNodes = []
let empty = []
// for (var i in countryTrafficking){
// let row = countryTrafficking[i]
// // arrayLinks.push({source: parseInt(row.sourceIndex), target: parseInt(row.targetIndex), names: [row.source, row.target], value: row.value})
// arrayNodes.push({name: row.source})
// // if (arrayNodes.includes(row.source)) {
// // console.log(123123123)
// // arrayNodes.push({name: row.source})
// // }
// }
for (var a in gdpBotFiltered){
let row = gdpBotFiltered[a]
arrayNodes.push({name: row.target})
}
return arrayNodes
}
Insert cell
//get list of unique nodes in order
nodesListTwoGdpBot = {
let empty = []
let valsArray = z.valueCounts(z.getCol("name", nodesListGdpBot))
let listNodes = Object.keys(valsArray)
for (var i in listNodes){
let selected = listNodes[i]
empty.push({name: selected})
}
return empty
}
Insert cell
nodesListTargetGdpBot = {
let empty = []
let valsArray = z.valueCounts(z.getCol("name", nodesListDestGdpBot))
let listNodes = Object.keys(valsArray)
for (var i in listNodes){
let selected = listNodes[i]
empty.push({name: selected})
}
return empty
}
Insert cell
nodesListCombinedGdpBot = {
let array = []
array = {origin: nodesListTwoGdpBot, destination: nodesListTargetGdpBot}
return array
}

Insert cell
ultimateNodesGdpBot = {
let nodesListNoGdp = nodesListTwoGdpBot.concat(nodesListTargetGdpBot)
let empty = []
let ranking = "Not Ranked"
for (var i in nodesListNoGdp){
let nodesRow = nodesListNoGdp[i]
for (var a in gdpRank){
let gdpRow = gdpRank[a]
if (gdpRow.Economy == nodesRow.name){
ranking = gdpRow.Ranking
}
}
empty.push(ranking)
}
return z.addCol("gdpRanking", empty, nodesListNoGdp)
}
Insert cell
// add nodes/arrays based on position in nodes dataset
traffickingSankeyGdpBot = {
let arrayLinks = []
for (var i in gdpBotFiltered){
let row = gdpBotFiltered[i] // row = each row
let source = ""
let target = ""
let names = [row.source, row.target]
let value = row.value
let gdpRanking = row.gdpRanking
let originList = nodesListCombinedGdpBot["origin"]
let targetList = nodesListCombinedGdpBot["destination"]
for (var a in originList){
let selectedNode = originList[a].name
if (selectedNode == row.source ){
source = a
}
}
for (var g in targetList){ // for each item in array
let targetSelected = targetList[g].name // if selected target
if (targetSelected == row.target){
target = g
console.log(target)
}
}
arrayLinks.push({source: parseInt(source), target: parseInt(target) + originList.length, names: names, value: value, gdpRanking: gdpRanking})
}
let arrayCombined = {nodes: ultimateNodesGdpTop, links: arrayLinks}
return arrayCombined
}
Insert cell
md`## 4. Prepare Sankey`
Insert cell
traffickingSankey.nodes.map(d => Object.assign({}, d))
Insert cell
traffickingSankey.nodes
Insert cell
// function colorFunct(dataset) {
// let colorSelect = "#000"
// let oneSet = dataset.nodes
// let testSet = traffickingSankey.nodes.sort(function (a,b) {return d3.descending(a.value, b.value)})
// let hexColor = ""
// let hexOrder = []
// for (var i in testSet){
// let row = testSet[i]
// for (var a in colorCustom){
// let selectName = colorCustom[a]
// if (row.name == selectName.Country){
// hexColor = selectName.Hex
// }
// }
// hexOrder.push(hexColor)
// }
// return hexOrder
// }
Insert cell
// function colorTwo(name) {
// let selectColor = z.filter(r => r.Country == name, colorCustom)
// return d3.scaleOrdinal(selectColor)
// }
Insert cell
// colorTwo("Mexico")
Insert cell
// colorFunct(traffickingSankey)
Insert cell
traffickingSankey
Insert cell
// function toolTipSankey(data)
// {
// $('.d3-tip-nodes').remove(); //clear olds tips
// var chartBox = d3.select("#sankey").node().getBoundingClientRect();
// var margin = {top: 10, right: 10, bottom: 10, left: 20},
// width = chartBox.width - chartBox.left - margin.left - margin.right,
// height = chartBox.height - chartBox.top - margin.top - margin.bottom;
// var linkTooltipOffset = 72,
// nodeTooltipOffset = 130;
// //Tooltip function:
// //D3 sankey diagram with view options (Austin Czarnecki’s Block cc6371af0b726e61b9ab)
// //https://bl.ocks.org/austinczarnecki/cc6371af0b726e61b9ab
// var tipLinks = d3.tip()
// .attr('class', 'd3-tip')
// .offset([-10,0]);

// var tipNodes = d3.tip()
// .attr('class', 'd3-tip d3-tip-nodes')
// .offset([-10, 0]);
// function formatAmount(value) {
// //return val.toLocaleString("en-US", {style: 'currency', currency: "USD"}).replace(/\.[0-9]+/, "");
// return parseFloat(value).toFixed(1) + " trafficking victims";
// };

Insert cell
// colorTraffick = {
// const color = d3.scaleOrdinal(colorFunct(traffickingSankey));
// return name => color(name.replace(/ .*/, ""));
// }
Insert cell
//duplicate nodes - can do that by shifting index - current data + 76
mutable chart = {
const svg = d3.select(DOM.svg(width, height)) // set svg to width and height
.style("background", "#fff") // set background color
.style("width", "100%") // set width
.style("height", "auto"); // set height

const {nodes, links} = sankey({ // use sankey function
nodes: traffickingSankey.nodes, // set nodes to traficking sankey.nodes, and sort by value
links: traffickingSankey.links// set links to traficking sankey.links, and sort by value
});
tooltip

svg.append("g")
.selectAll("rect") // create rectangles that are node shapesco
.data(nodes)
.join("rect")
.attr("x", d => d.x0)
.attr("y", d => d.y0)
.attr("height", d => d.y1 - d.y0)
.attr("width", d => d.x1 - d.x0)
.style("fill", d=>color(d.name))
.append("title")
.text(function(d) {
if (d.name==""){
d.name="Unknown Country"
return (`Unknown Country\n${d.value.toLocaleString()}`)
}
return(`${d.name}\n${d.value.toLocaleString()}`)
});

svg.append("g")
.attr("fill", "none")
.selectAll("g")
.data(links)
.join("path") // create/koin path
.attr("d", d3.sankeyLinkHorizontal())
.attr("stroke", d => color(d.names[0])) // color path
.attr("stroke-width", d => d.width) // set width to dataset width
.style("opacity", .55) // set opacity
.on("mouseover", function(d) {
tooltip.style("visibility", "visible").text(d.names[0] + " to " + d.names[1] + ": " + d.value.toLocaleString() + " persons trafficked.\n" + d.names[0] + " Global GDP Ranking: " + d.gdpRanking)
d3.select(this)
.transition()
.style("opacity", 1.0) // HELP NEEDED HERE - CAN'T GET OPACITY TO TRANSITION
})
.on("mousemove", function(d) {
tooltip.style("top", (d3.event.pageY-10)+"px").style("left",(d3.event.pageX+10)+"px").text(d.names[0] + " to " + d.names[1] + ": " + d.value.toLocaleString() + " persons trafficked.\n" + d.names[0] + " Global GDP Ranking: " + d.gdpRanking)
d3.select(this)
.transition()
.style("opacity", 1.0) // HELP NEEDED HERE - CAN'T GET OPACITY TO TRANSITION
})
.on("mouseout", function(d) {
tooltip.style("visibility", "hidden")
d3.select(this)
.transition()
.style("opacity", 0.55) // HELP NEEDED HERE - CAN'T GET OPACITY TO TRANSITION
})
.style("mix-blend-mode", "multiply");
// .append("title")
// .text(d => `${d.names.join(" to ")}\n${d.value.toLocaleString()}`)
// .attr("font", "20px sans-serif")

svg.append("g")
.selectAll("text")
.data(nodes)
.join("text")
.attr("x", d => d.x0 < width / 2 ? d.x1 + 6 : d.x0 - 6) // define position of text
.attr("y", d => (d.y1 + d.y0) / 2)
.attr("dy", "0.35em")
.attr("text-anchor", d => d.x0 < width / 2 ? "start" : "end")
.text(d => d.name)
.style("font", "10px Avenir") // define text for paths
.style("font-size", d=>`${(d.y1-d.y0) *0.13}px`) // HELP NEEDED HERE - CAN'T GET FONT TO SCALE PROPERLY
.append("tspan")
.attr("fill-opacity", 0.7)
.text(d => ` \n${d.value.toLocaleString()}`);

return svg.node();
}
Insert cell
width = 4000
Insert cell
function fontScale(d) {
return d3.scaleLinear()
.domain([z.min(z.getCol("value", d)), z.max(z.getCol("value", d))])
.range([10, 100])
}
Insert cell
fontScale(12000)
Insert cell
duration = 250
Insert cell
height = 4000
Insert cell
sankey = d3.sankey()
.nodeSort(null)
.linkSort(null)
.nodeWidth(30)
.nodePadding(20)
.extent([[0, 5], [width, height - 5]])
Insert cell
md`### 4a. Top 20 Countries by Total Internal Trafficking`
Insert cell
traffickingSankeyInternal
Insert cell
//duplicate nodes - can do that by shifting index - current data + 76
mutable chartInternal = {
const svg = d3.select(DOM.svg(width, height)) // set svg to width and height
.style("background", "#fff") // set background color
.style("width", "100%") // set width
.style("height", "auto"); // set height

const {nodes, links} = sankey({ // use sankey function
nodes: traffickingSankeyInternal.nodes, // set nodes to traficking sankey.nodes, and sort by value
links: traffickingSankeyInternal.links// set links to traficking sankey.links, and sort by value
});
tooltip

svg.append("g")
.selectAll("rect") // create rectangles that are node shapes
.data(traffickingSankeyInternal.nodes)
.join("rect")
.attr("x", d => d.x0)
.attr("y", d => d.y0)
.attr("height", d => d.y1 - d.y0)
.attr("width", d => d.x1 - d.x0)
.style("fill", d=>color(d.name))
.append("title")
.text(function(d) {
if (d.name==""){
d.name="Unknown Country"
return (`Unknown Country\n${d.value.toLocaleString()}`)
}
return(`${d.name}\n${d.value.toLocaleString()}`)
});

svg.append("g")
.attr("fill", "none")
.selectAll("g")
.data(links)
.join("path") // create/koin path
.attr("d", d3.sankeyLinkHorizontal())
.attr("stroke", d => color(d.names[0])) // color path
.attr("stroke-width", d => d.width) // set width to dataset width
.style("opacity", .55) // set opacity
.on("mouseover", function(d) {
tooltip.style("visibility", "visible").text(d.names[0] + " to " + d.names[1] + ": " + d.value.toLocaleString() + " persons trafficked.\n" + d.names[0] + " Global GDP Ranking: " + d.gdpRanking)
d3.select(this)
.transition()
.style("opacity", 1.0) // HELP NEEDED HERE - CAN'T GET OPACITY TO TRANSITION
})
.on("mousemove", function(d) {
tooltip.style("top", (d3.event.pageY-10)+"px").style("left",(d3.event.pageX+10)+"px").text(d.names[0] + " to " + d.names[1] + ": " + d.value.toLocaleString() + " persons trafficked.\n" + d.names[0] + " Global GDP Ranking: " + d.gdpRanking)
d3.select(this)
.transition()
.style("opacity", 1.0) // HELP NEEDED HERE - CAN'T GET OPACITY TO TRANSITION
})
.on("mouseout", function(d) {
tooltip.style("visibility", "hidden")
d3.select(this)
.transition()
.style("opacity", 0.55) // HELP NEEDED HERE - CAN'T GET OPACITY TO TRANSITION
})
.style("mix-blend-mode", "multiply");
// .append("title")
// .text(d => `${d.names.join(" to ")}\n${d.value.toLocaleString()}`)
// .attr("font", "20px sans-serif")

svg.append("g")
.selectAll("text")
.data(nodes)
.join("text")
.attr("x", d => d.x0 < width / 2 ? d.x1 + 6 : d.x0 - 6) // define position of text
.attr("y", d => (d.y1 + d.y0) / 2)
.attr("dy", "0.35em")
.attr("text-anchor", d => d.x0 < width / 2 ? "start" : "end")
.text(d => d.name)
.style("font", "10px Avenir") // define text for paths
.style("font-size", d=>`${(d.y1-d.y0) *0.13}px`) // HELP NEEDED HERE - CAN'T GET FONT TO SCALE PROPERLY
.append("tspan")
.attr("fill-opacity", 0.7)
.text(d => ` \n${d.value.toLocaleString()}`);

return svg.node();
}
Insert cell
md`### 4b. Top 20 Countries by Total External Trafficking`
Insert cell
//duplicate nodes - can do that by shifting index - current data + 76
mutable chartExternal = {
const svg = d3.select(DOM.svg(width, height)) // set svg to width and height
.style("background", "#fff") // set background color
.style("width", "100%") // set width
.style("height", "auto"); // set height

const {nodes, links} = sankey({ // use sankey function
nodes: traffickingSankeyExternal.nodes, // set nodes to traficking sankey.nodes, and sort by value
links: traffickingSankeyExternal.links// set links to traficking sankey.links, and sort by value
});
tooltip

svg.append("g")
.selectAll("rect") // create rectangles that are node shapes
.data(nodes)
.join("rect")
.attr("x", d => d.x0)
.attr("y", d => d.y0)
.attr("height", d => d.y1 - d.y0)
.attr("width", d => d.x1 - d.x0)
.style("fill", d=>color(d.name))
.append("title")
.text(function(d) {
if (d.name==""){
d.name="Unknown Country"
return (`Unknown Country\n${d.value.toLocaleString()}`)
}
return(`${d.name}\n${d.value.toLocaleString()}`)
});

svg.append("g")
.attr("fill", "none")
.selectAll("g")
.data(links)
.join("path") // create/koin path
.attr("d", d3.sankeyLinkHorizontal())
.attr("stroke", d => color(d.names[0])) // color path
.attr("stroke-width", d => d.width) // set width to dataset width
.style("opacity", .55) // set opacity
.on("mouseover", function(d) {
tooltip.style("visibility", "visible").text(d.names[0] + " to " + d.names[1] + ": " + d.value.toLocaleString() + " persons trafficked.\n" + d.names[0] + " Global GDP Ranking: " + d.gdpRanking)
d3.select(this)
.transition()
.style("opacity", 1.0) // HELP NEEDED HERE - CAN'T GET OPACITY TO TRANSITION
})
.on("mousemove", function(d) {
tooltip.style("top", (d3.event.pageY-10)+"px").style("left",(d3.event.pageX+10)+"px").text(d.names[0] + " to " + d.names[1] + ": " + d.value.toLocaleString() + " persons trafficked.\n" + d.names[0] + " Global GDP Ranking: " + d.gdpRanking)
d3.select(this)
.transition()
.style("opacity", 1.0) // HELP NEEDED HERE - CAN'T GET OPACITY TO TRANSITION
})
.on("mouseout", function(d) {
tooltip.style("visibility", "hidden")
d3.select(this)
.transition()
.style("opacity", 0.55) // HELP NEEDED HERE - CAN'T GET OPACITY TO TRANSITION
})
.style("mix-blend-mode", "multiply");
// .append("title")
// .text(d => `${d.names.join(" to ")}\n${d.value.toLocaleString()}`)
// .attr("font", "20px sans-serif")

svg.append("g")
.selectAll("text")
.data(nodes)
.join("text")
.attr("x", d => d.x0 < width / 2 ? d.x1 + 6 : d.x0 - 6) // define position of text
.attr("y", d => (d.y1 + d.y0) / 2)
.attr("dy", "0.35em")
.attr("text-anchor", d => d.x0 < width / 2 ? "start" : "end")
.text(d => d.name)
.style("font", "10px Avenir") // define text for paths
.style("font-size", d=>`${(d.y1-d.y0) *0.13}px`) // HELP NEEDED HERE - CAN'T GET FONT TO SCALE PROPERLY
.append("tspan")
.attr("fill-opacity", 0.7)
.text(d => ` \n${d.value.toLocaleString()}`);

return svg.node();
}
Insert cell
md`### 4c. Top 20 Origin Countries by GDP`
Insert cell
traffickingSankeyGdpTop
Insert cell
traffickingSankeyGdpTop.links
Insert cell
//duplicate nodes - can do that by shifting index - current data + 76
mutable chartGdpTop = {
const svg = d3.select(DOM.svg(width, height)) // set svg to width and height
.style("background", "#fff") // set background color
.style("width", "100%") // set width
.style("height", "auto"); // set height

const {nodes, links} = sankey({ // use sankey function
nodes: traffickingSankeyGdpTop.nodes, // set nodes to traficking sankey.nodes, and sort by value
links: traffickingSankeyGdpTop.links// set links to traficking sankey.links, and sort by value
});
tooltip

svg.append("g")
.selectAll("rect") // create rectangles that are node shapes
.data(nodes)
.join("rect")
.attr("x", d => d.x0)
.attr("y", d => d.y0)
.attr("height", d => d.y1 - d.y0)
.attr("width", d => d.x1 - d.x0)
.style("fill", d=>color(d.name))
.append("title")
.text(function(d) {
if (d.name==""){
d.name="Unknown Country"
return (`Unknown Country\n${d.value.toLocaleString()}`)
}
return(`${d.name}\n${d.value.toLocaleString()}`)
});

svg.append("g")
.attr("fill", "none")
.selectAll("g")
.data(links)
.join("path") // create/koin path
.attr("d", d3.sankeyLinkHorizontal())
.attr("stroke", d => color(d.names[0])) // color path
.attr("stroke-width", d => d.width) // set width to dataset width
.style("opacity", .55) // set opacity
.on("mouseover", function(d) {
tooltip.style("visibility", "visible").text(d.names[0] + " to " + d.names[1] + ": " + d.value.toLocaleString() + " persons trafficked.\n" + d.names[0] + " Global GDP Ranking: " + d.gdpRanking)
d3.select(this)
.transition()
.style("opacity", 1.0) // HELP NEEDED HERE - CAN'T GET OPACITY TO TRANSITION
})
.on("mousemove", function(d) {
tooltip.style("top", (d3.event.pageY-10)+"px").style("left",(d3.event.pageX+10)+"px").text(d.names[0] + " to " + d.names[1] + ": " + d.value.toLocaleString() + " persons trafficked.\n" + d.names[0] + " Global GDP Ranking: " + d.gdpRanking)
d3.select(this)
.transition()
.style("opacity", 1.0) // HELP NEEDED HERE - CAN'T GET OPACITY TO TRANSITION
})
.on("mouseout", function(d) {
tooltip.style("visibility", "hidden")
d3.select(this)
.transition()
.style("opacity", 0.55) // HELP NEEDED HERE - CAN'T GET OPACITY TO TRANSITION
})
.style("mix-blend-mode", "multiply");
// .append("title")
// .text(d => `${d.names.join(" to ")}\n${d.value.toLocaleString()}`)
// .attr("font", "20px sans-serif")

svg.append("g")
.selectAll("text")
.data(nodes)
.join("text")
.attr("x", d => d.x0 < width / 2 ? d.x1 + 6 : d.x0 - 6) // define position of text
.attr("y", d => (d.y1 + d.y0) / 2)
.attr("dy", "0.35em")
.attr("text-anchor", d => d.x0 < width / 2 ? "start" : "end")
.text(d => d.name)
.style("font", "10px Avenir") // define text for paths
.style("font-size", function(d) {
const f = ((d.y1-d.y0) *0.13< 100)?(d.y1-d.y0) *0.13:100
return `${f}px`})
.append("tspan")
.attr("fill-opacity", 0.7)
.text(d => ` \n${d.value.toLocaleString()}`);

return svg.node();
}
Insert cell
md`### 4d. Bottom Countries by GDP`
Insert cell
//duplicate nodes - can do that by shifting index - current data + 76
mutable chartGdpBot = {
const svg = d3.select(DOM.svg(width, height)) // set svg to width and height
.style("background", "#fff") // set background color
.style("width", "100%") // set width
.style("height", "auto"); // set height

const {nodes, links} = sankey({ // use sankey function
nodes: traffickingSankeyGdpBot.nodes, // set nodes to traficking sankey.nodes, and sort by value
links: traffickingSankeyGdpBot.links// set links to traficking sankey.links, and sort by value
});
tooltip

svg.append("g")
.selectAll("rect") // create rectangles that are node shapes
.data(nodes)
.join("rect")
.attr("x", d => d.x0)
.attr("y", d => d.y0)
.attr("height", d => d.y1 - d.y0)
.attr("width", d => d.x1 - d.x0)
.style("fill", d=>color(d.name))

svg.append("g")
.attr("fill", "none")
.selectAll("g")
.data(links)
.join("path") // create/koin path
.attr("d", d3.sankeyLinkHorizontal())
.attr("stroke", d => color(d.names[0])) // color path
.attr("stroke-width", d => d.width) // set width to dataset width
.style("opacity", .55) // set opacity
.on("mouseover", function(d) {
tooltip.style("visibility", "visible").text(d.names[0] + " to " + d.names[1] + ": " + d.value.toLocaleString() + " persons trafficked.\n" + d.names[0] + " Global GDP Ranking: " + d.gdpRanking)
d3.select(this)
.transition()
.style("opacity", 1.0) // HELP NEEDED HERE - CAN'T GET OPACITY TO TRANSITION
})
.on("mousemove", function(d) {
tooltip.style("top", (d3.event.pageY-10)+"px").style("left",(d3.event.pageX+10)+"px").text(d.names[0] + " to " + d.names[1] + ": " + d.value.toLocaleString() + " persons trafficked.\n" + d.names[0] + " Global GDP Ranking: " + d.gdpRanking)
d3.select(this)
.transition()
.style("opacity", 1.0) // HELP NEEDED HERE - CAN'T GET OPACITY TO TRANSITION
})
.on("mouseout", function(d) {
tooltip.style("visibility", "hidden")
d3.select(this)
.transition()
.style("opacity", 0.55) // HELP NEEDED HERE - CAN'T GET OPACITY TO TRANSITION
})
.style("mix-blend-mode", "multiply")
// .append("title")
// .text(d => `${d.names.join(" to ")}\n${d.value.toLocaleString()}`)
// .attr("font", "20px sans-serif")

return svg.node();
}
Insert cell
md`## Appendix`
Insert cell
d3 = require("d3@5", "d3-sankey@0.12")
Insert cell
z = require('https://bundle.run/zebras@0.0.11')
Insert cell
vegalite = require("@observablehq/vega-lite@0.1")
Insert cell
function titleCase(str) {
// Step 1. Lowercase the string
str = str.toLowerCase() // str = "i'm a little tea pot";
// Step 2. Split the string into an array of strings
.split(' ') // str = ["i'm", "a", "little", "tea", "pot"];
// Step 3. Map over the array
.map(function(word) {
return (word.charAt(0).toUpperCase() + word.slice(1));
/* Map process
1st word: "i'm" => (word.charAt(0).toUpperCase() + word.slice(1));
"i'm".charAt(0).toUpperCase() + "i'm".slice(1);
"I" + "'m";
return "I'm";
2nd word: "a" => (word.charAt(0).toUpperCase() + word.slice(1));
"a".charAt(0).toUpperCase() + "".slice(1);
"A" + "";
return "A";
3rd word: "little" => (word.charAt(0).toUpperCase() + word.slice(1));
"little".charAt(0).toUpperCase() + "little".slice(1);
"L" + "ittle";
return "Little";
4th word: "tea" => (word.charAt(0).toUpperCase() + word.slice(1));
"tea".charAt(0).toUpperCase() + "tea".slice(1);
"T" + "ea";
return "Tea";
5th word: "pot" => (word.charAt(0).toUpperCase() + word.slice(1));
"pot".charAt(0).toUpperCase() + "pot".slice(1);
"P" + "ot";
return "Pot";
End of the map() method */
});

// Step 4. Return the output
return str.join(' '); // ["I'm", "A", "Little", "Tea", "Pot"].join(' ') => "I'm A Little Tea Pot"
}

Insert cell
ajax = require('https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.12.0/lodash.min.js')
Insert cell
Insert cell
// read in color dataset
colorCustom = d3.csv("https://gist.githubusercontent.com/dpowers120/298d1053f49acdfaea93c7f6715fca28/raw/38995eebfcd83cd181227eeee94299dc9415d487/CountriesColorCodes.csv", d3.autoType())
Insert cell
color = {
const color = d3.scaleOrdinal(z.getCol("Country", colorCustom), z.getCol("Hex", colorCustom))
return color
//return name => color(name.replace(/ .*/, ""));
}
Insert cell
{
let oneSet = traffickingSankey.nodes
return z.sortByCol("value", "desc", oneSet)
}
Insert cell
// colorFunct(traffickingSankey)
Insert cell
d3.scaleOrdinal(z.getCol("County", colorCustom), z.getCol("Hex", colorCustom))
Insert cell
name => color(name.replace(/ .*/, ""))
Insert cell
color("Singapore")
Insert cell
//try to match color names to countryTraffickingDataset
colorMatch = {
let empty = []
let unique = Object.keys(z.valueCounts(z.getCol("source", countryTrafficking)))
for (var i in unique){
let notMatch = "No Data Available"
let colorName = ""
let row = unique[i]
for (var a in colorCustom){
let colorRow = colorCustom[a]
if (colorRow.Country == row){
notMatch = colorRow.Hex
colorName = colorRow.name
}
}
// if (row != "Unknown Country"){
empty.push({countryName: row, colorName: colorName, hex: notMatch})
// }
}
let unmatched = z.filter(r => r.hex == "No Data Available", empty)
z.valueCounts(z.getCol("countryName", unmatched))
return unmatched
}
Insert cell
tooltip = d3.select("body")
.append("div")
.style("position", "absolute")
.style("z-index", "1")
.style("visibility", "hidden")
.style("background","white")
.style("opacity","0.6")
.style("padding","5px")
.style("font-family", "'Open Sans', sans-serif")
.style("font-size", "12px");
Insert cell
format = {
const f = d3.format(",.0f");
return d => `${f(d)} TWh`;
}
Insert cell
test = Object.keys(z.valueCounts(z.getCol("source", countryTrafficking)))
Insert cell
test
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