viewof charge = Inputs.range([1000, 10000], {
value: 3000,
step: 1000,
label: "charge"
})
chart = {
const links = data.links.map((d) => Object.create(d));
const nodes = data.nodes.map((d) => Object.create(d));
const simulation = d3
.forceSimulation(nodes)
.force(
"link",
d3.forceLink(links).id((d) => d.id)
)
.force("charge", d3.forceManyBody().strength(-charge))
.force("x", d3.forceX())
.force("y", d3.forceY());
const svg = d3
.create("svg")
.attr("viewBox", [-width / 2, -height / 2, width, height])
.style("font", "12px sans-serif");
svg
.append("defs")
.selectAll("marker")
.data(nodes.map((n) => n.id))
.join("marker")
.attr("id", (d) => `arrow-${d}`)
.attr("viewBox", "0 -5 10 10")
.attr("refX", 15)
.attr("refY", -2)
.attr("markerWidth", 10)
.attr("markerHeight", 10)
.attr("orient", "auto")
.append("path")
.attr("fill", "grey")
.attr("d", "M0,-5L10,0L0,5");
const link = svg
.append("g")
.attr("fill", "none")
.attr("stroke-width", 1.5)
.selectAll("path")
.data(links)
.join("path")
.attr("stroke", (d) => skillColor(d.Label));
link
.attr("stroke-width", 2)
.attr(
"marker-end",
(d) => `url(${new URL(`#arrow-${d.source.id}`, location)})`
);
const node = svg
.append("g")
.attr("fill", "currentColor")
.attr("stroke-linecap", "round")
.attr("stroke-linejoin", "round")
.selectAll("g")
.data(nodes)
.attr("id", (d) => `g${d.index}`)
.join("g")
.call(drag(simulation));
node
.append("circle")
.attr("stroke", "white")
.attr("stroke-width", 1)
.attr("r", 20)
.attr("stroke-width", (d) => (d.nodeWeight + 2) / 2);
node
.append("text")
.attr("x", 20)
.attr("y", "0.31em")
.text((d) => d.id)
.clone(true)
.lower()
.attr("fill", "none")
.attr("stroke", "white")
.attr("stroke-width", 3);
node
.append("image")
.attr('xlink:href', d=>d.img)
.attr("height", 25)
.attr("width", 25)
.attr("transform", "translate(-13,-13)")
.style("border-radius", 5);
simulation.on("tick", () => {
link.attr("d", linkArc);
node.attr("transform", (d) => `translate(${d.x},${d.y})`);
});
invalidation.then(() => simulation.stop());
return svg.node();
}
nodeColor = ƒ(i)
nodeColor = d3.scaleOrdinal(
data.nodes.map((n) => n.id),
d3.schemeTableau10
)
skillColor = ƒ(i)
skillColor = d3.scaleOrdinal(skills, d3.schemeCategory10)
skills = Array(6) [
0: "R"
1: "presentation"
2: "story telling"
3: "R, SQL"
4: "data cleaning"
5: "statistics"
]
skills = Array.from(new Set(links.map((l) => l.Label)))
linkArc = ƒ(d)
function linkArc(d) {
const r = Math.hypot(d.target.x - d.source.x, d.target.y - d.source.y);
return `
M${d.source.x},${d.source.y}
A${r},${r} 0 0,1 ${d.target.x},${d.target.y}
`;
}
drag = ƒ(simulation)
drag = (simulation) => {
function dragstarted(event, d) {
if (!event.active) simulation.alphaTarget(0.3).restart();
d.fx = d.x;
d.fy = d.y;
}
function dragged(event, d) {
d.fx = event.x;
d.fy = event.y;
}
function dragended(event, d) {
if (!event.active) simulation.alphaTarget(0);
d.fx = null;
d.fy = null;
}
return d3
.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended);
}
data = Object {
nodes: Array(8) [
0: Object {
id: "Nurul"
img: "https://cdn.lorem.space/images/face/.cache/150x150/daniil-lobachev-u3pi6HhSYew-unsplash.jpg"
}
1: Object {
id: "Aiman"
img: "https://cdn.lorem.space/images/face/.cache/150x150/daniil-lobachev-u3pi6HhSYew-unsplash.jpg"
}
2: Object {
id: "Aliah"
img: "https://cdn.lorem.space/images/face/.cache/150x150/daniil-lobachev-u3pi6HhSYew-unsplash.jpg"
}
3: Object {
id: "Asma"
img: "https://cdn.lorem.space/images/face/.cache/150x150/daniil-lobachev-u3pi6HhSYew-unsplash.jpg"
}
4: Object {
id: "Arizal"
img: "https://cdn.lorem.space/images/face/.cache/150x150/daniil-lobachev-u3pi6HhSYew-unsplash.jpg"
}
5: Object {
id: "Syaza"
img: "https://cdn.lorem.space/images/face/.cache/150x150/daniil-lobachev-u3pi6HhSYew-unsplash.jpg"
}
6: Object {
id: "Alif"
img: "https://cdn.lorem.space/images/face/.cache/150x150/daniil-lobachev-u3pi6HhSYew-unsplash.jpg"
}
7: Object {id: "Nabiha", img: "https://cdn.lorem.space/images/face/.cache/150x150/daniil-lobachev-u3pi6HhSYew-unsplash.jpg"}
]
links: Array(13) [
0: Object {source: "Aiman", target: "Aliah", Label: "R"}
1: Object {source: "Aiman", target: "Arizal", Label: "R"}
2: Object {source: "Alif", target: "Aliah", Label: "presentation"}
3: Object {source: "Alif", target: "Asma", Label: "presentation"}
4: Object {source: "Alif", target: "Syaza", Label: "presentation"}
5: Object {source: "Arizal", target: "Nabiha", Label: "story telling"}
6: Object {source: "Arizal", target: "Nurul", Label: "story telling"}
7: Object {source: "Nabiha", target: "Aliah", Label: "R, SQL"}
8: Object {source: "Nabiha", target: "Arizal", Label: "R"}
9: Object {source: "Nurul", target: "Aliah", Label: "R, SQL"}
10: Object {source: "Nurul", target: "Arizal", Label: "R"}
11: Object {source: "Syaza", target: "Aliah", Label: "data cleaning"}
12: Object {source: "Syaza", target: "Nurul", Label: "statistics"}
columns: Array(3) ["source", "target", "Label"]
]
}
data = ({
nodes: nodes_skills.map((n) => {
n.img = "https://cdn.lorem.space/images/face/.cache/150x150/daniil-lobachev-u3pi6HhSYew-unsplash.jpg";
return n;
}),
links
})
nodes_skills = Array(8) [
0: Object {id: "Nurul", img: "https://cdn.lorem.space/images/face/.cache/150x150/daniil-lobachev-u3pi6HhSYew-unsplash.jpg"}
1: Object {id: "Aiman", img: "https://cdn.lorem.space/images/face/.cache/150x150/daniil-lobachev-u3pi6HhSYew-unsplash.jpg"}
2: Object {id: "Aliah", img: "https://cdn.lorem.space/images/face/.cache/150x150/daniil-lobachev-u3pi6HhSYew-unsplash.jpg"}
3: Object {id: "Asma", img: "https://cdn.lorem.space/images/face/.cache/150x150/daniil-lobachev-u3pi6HhSYew-unsplash.jpg"}
4: Object {id: "Arizal", img: "https://cdn.lorem.space/images/face/.cache/150x150/daniil-lobachev-u3pi6HhSYew-unsplash.jpg"}
5: Object {id: "Syaza", img: "https://cdn.lorem.space/images/face/.cache/150x150/daniil-lobachev-u3pi6HhSYew-unsplash.jpg"}
6: Object {id: "Alif", img: "https://cdn.lorem.space/images/face/.cache/150x150/daniil-lobachev-u3pi6HhSYew-unsplash.jpg"}
7: Object {id: "Nabiha", img: "https://cdn.lorem.space/images/face/.cache/150x150/daniil-lobachev-u3pi6HhSYew-unsplash.jpg"}
]
nodes_skills = FileAttachment("nodes_skills.json").json()
links = Array(13) [
0: Object {source: "Aiman", target: "Aliah", Label: "R"}
1: Object {source: "Aiman", target: "Arizal", Label: "R"}
2: Object {source: "Alif", target: "Aliah", Label: "presentation"}
3: Object {source: "Alif", target: "Asma", Label: "presentation"}
4: Object {source: "Alif", target: "Syaza", Label: "presentation"}
5: Object {source: "Arizal", target: "Nabiha", Label: "story telling"}
6: Object {source: "Arizal", target: "Nurul", Label: "story telling"}
7: Object {source: "Nabiha", target: "Aliah", Label: "R, SQL"}
8: Object {source: "Nabiha", target: "Arizal", Label: "R"}
9: Object {source: "Nurul", target: "Aliah", Label: "R, SQL"}
10: Object {source: "Nurul", target: "Arizal", Label: "R"}
11: Object {source: "Syaza", target: "Aliah", Label: "data cleaning"}
12: Object {source: "Syaza", target: "Nurul", Label: "statistics"}
columns: Array(3) ["source", "target", "Label"]
]
links = FileAttachment("Skillset_Mapping.csv").csv({ typed: true })
existingSkills = Object {
website development: 1
UI/UX design: 1
Qlik: 1
R: 1
SQL: 1
Dashboard: 1
Excel: 1
statistics: 1
data cleaning: 1
programming language: 1
presentation: 1
team: 1
leadership: 1
story telling: 1
data charting: 1
}
existingSkills = {
const skillsToShare = Array.from(skillsharedRaw.flatMap(e=>e.SkillsToShare), e=>e?.trim());
const existingSkillsFreq = ({});
for(const skill of skillsToShare){
demandsFreq[skill] = demandsFreq[skill]? demandsFreq[skill] + 1:1;
}
return existingSkillsFreq;
}
Array(19) [
0: "website development"
1: "UI/UX design "
2: "Qlik"
3: "R"
4: "SQL"
5: "Dashboard"
6: "Qlik"
7: " R"
8: "SQL"
9: "Excel"
10: "R"
11: "statistics"
12: "data cleaning"
13: "programming language"
14: " presentation "
15: "team"
16: "leadership"
17: "story telling"
18: "data charting"
]
Array.from(skillsharedRaw.flatMap(e=>e.SkillsToShare))
demandSkillsBarChart = BarChart(demandsFreqData, {
x: d => d.skill,
y: d => d.frequency,
width : 1000,
color: "steelblue"
})
emandSkillsBarChart = BarChart(demandsFreqData, {
x: d => d.skill,
y: d => d.frequency,
width : 1000,
color: "steelblue"
})
demandsFreqData = Array(14) [
0: Object {skill: "presentation", frequency: 3}
1: Object {skill: "python", frequency: 3}
2: Object {skill: "story telling", frequency: 2}
3: Object {skill: "R", frequency: 1}
4: Object {skill: "SQL", frequency: 1}
5: Object {skill: "data cleaning", frequency: 1}
6: Object {skill: "Adobe", frequency: 1}
7: Object {skill: "statistics", frequency: 1}
8: Object {skill: "design", frequency: 1}
9: Object {skill: "julia", frequency: 1}
10: Object {skill: "AWS cloud", frequency: 1}
11: Object {skill: "feature engineering", frequency: 1}
12: Object {skill: " R", frequency: 1}
13: Object {skill: "analytics", frequency: 1}
]
demandsFreqData = {
const demandsFreqData = [];
for(const skill of Object.keys(demandsFreq)){
const tempObject = ({});
tempObject["skill"] = skill;
tempObject["frequency"] = demandsFreq[skill];
demandsFreqData.push(tempObject);
}
return demandsFreqData.sort((a,b)=>(b.frequency-a.frequency));
}
demandsFreq = Object {
R: 4
SQL: 3
presentation: 4
data cleaning: 2
python: 3
Adobe: 1
story telling: 3
statistics: 2
design: 1
julia: 1
AWS cloud: 1
feature engineering: 1
R: 1
analytics: 1
website development: 1
UI/UX design: 1
Qlik: 2
Dashboard: 1
Excel: 1
programming language: 1
team: 1
leadership: 1
data charting: 1
}
demandsFreq = {
const demandsFreq = ({});
for(const skill of demandedSkills){
demandsFreq[skill] = demandsFreq[skill]? demandsFreq[skill] + 1:1;
}
return demandsFreq
}
demandedSkills = Array(19) [
0: "R"
1: "SQL"
2: "presentation"
3: "data cleaning"
4: "python"
5: "Adobe"
6: "story telling"
7: "statistics"
8: "story telling"
9: "python"
10: "presentation"
11: "design"
12: "julia"
13: "python"
14: "AWS cloud"
15: "feature engineering"
16: " R"
17: "presentation"
18: "analytics"
]
emandedSkills =
Array.from(skillsharedRaw.flatMap(e=>e.SkillsToLearn))
skillsharedRaw = Array(8) [
0: Object {Id: "Aliah", Skills to Share: "website development,UI/UX design ", Skills to Learn: "R,SQL,presentation,data cleaning", SkillsToShare: Array(2), SkillsToLearn: Array(4)}
1: Object {
Id: "Nurul"
Skills to Share: "Qlik,R,SQL,Dashboard"
Skills to Learn: "python,Adobe,story telling,statistics"
SkillsToShare: Array(4) ["Qlik", "R", "SQL", "Dashboard"]
SkillsToLearn: Array(4) ["python", "Adobe", "story telling", "statistics"]
}
2: Object {Id: "Nabiha", Skills to Share: "Qlik, R,SQL,Excel", Skills to Learn: "story telling", SkillsToShare: Array(4), SkillsToLearn: Array(1)}
3: Object {Id: "Aiman", Skills to Share: "R", Skills to Learn: "python", SkillsToShare: Array(1), SkillsToLearn: Array(1)}
4: Object {Id: "Syaza", Skills to Share: "statistics,data cleaning,programming language", Skills to Learn: "presentation,design,julia", SkillsToShare: Array(3), SkillsToLearn: Array(3)}
5: Object {Id: "Alif", Skills to Share: " presentation ,team,leadership", Skills to Learn: "python,AWS cloud", SkillsToShare: Array(3), SkillsToLearn: Array(2)}
6: Object {
Id: "Arizal"
Skills to Share: "story telling,data charting"
Skills to Learn: "feature engineering, R"
SkillsToShare: Array(2) ["story telling", "data charting"]
SkillsToLearn: Array(2) ["feature engineering", " R"]
}
7: Object {Id: "Asma", Skills to Learn: "presentation,analytics", SkillsToShare: Array(0), SkillsToLearn: Array(2)}
]
skillsharedRaw = {
const ssr = skillsharedataset.sheet(0, { headers: true, typed:true })
const skillsharedRaw = ssr.map(e=>
{
e.SkillsToShare = e["Skills to Share"]?e["Skills to Share"]?.split(","):[];
e.SkillsToLearn = e["Skills to Learn"]?.split(",");
return e;
});
return skillsharedRaw;
}
skillsharedataset = Workbook {
sheetNames: Array(1) ["Sheet1"]
<prototype>: Workbook {}
}
skillsharedataset = FileAttachment("skillsharedataset.xlsx").xlsx()
height = 571.4285714285714
height = (charge + 1000) / 7
import {[BarChart](https:
import {BarChart} from "@d3/bar-chart"