Public
Edited
Mar 12
1 fork
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
authPaths = Array.from(topics.entries()).flatMap((d) =>
[...new Set(d[1].list.map((d) => d.term))].flatMap((p) =>
[{ path: d[0] + "/" + p , freq: undefined }].concat(
Object.entries(phraseAuthors[p] ?? { "": 0 }).map((a) => ({
path: d[0] + "/" + p + "/" + a[0],
last: a[0],
freq: a[1]
}))
)
)
).filter(d=>d.freq>0)

Insert cell
Insert cell
Insert cell
Insert cell
console.log(graph)
Insert cell
graph = {
let header = `
rankdir = "TB";
ranksep = "0.2";
nodesep = "0.1";
concentrate = "true";
outputorder = "edgesfirst";
ratio = "auto";
size = "16,10";
edge[arrowsize="0.75", penwidth="0.25"]
graph[bgcolor = "transparent" ]`

let nodestyle = `node [
shape="box", margin="0.1,0", style="filled,rounded,bold",
color="#e17892", fillcolor="white", labelfontcolor="white",
fontcolor="#000000", fontname= Arial
]`
let edgestyle = `edge [color="#dddddd", style="", fontname= Arial]`

// all years
let years = Array.from(nodes.values())
let range = [
2 * Math.floor(Math.min(...years.map(d=>d.first)) / 2),
2 * Math.ceil(Math.max(...years.map(d=>d.last)) / 2)
]

/*let groups = Object.entries(
Object.groupBy(Array.from(nodes.entries()), (d) => d[1].last)
)*/
let groups = Object.entries(
Object.groupBy(
Array.from(nodes.entries()),
d => Math.round(d[1].mid) // Math.round(d[1].mid*2)/2
)
).sort((a,b)=>parseFloat(a[0]) -parseFloat(b[0]))
// selected years
range = [
parseInt(groups.at(0)[0]),
parseInt(groups.at(-1)[0])
]

let timeline = `node [fontsize=20, shape = box, fontname= Arial, fontsize = 14]; edge [/*style=invis*/penwidth=4];` //
timeline = timeline + "\n" +
Array.from({length:range[1]-range[0]},(_,i)=>' '+(i+range[0]) + ' -> ' + (i+range[0]+1)).join("\n")
// code for 'half years' -> needs rounded groups also (see above)
// Array.from({length:(range[1]-range[0])*2},(_,i)=>' "'+((i/2)+range[0]) + '" -> "' + ((i/2)+range[0]+0.5)+'"')
//.map((d,i,f)=> !/\.5"$/.test(f[i-1]) ? d + 'node [style=""]' : d + 'node [style=invis]' )
//.join("\n")

let filtered = coWordEdges
.filter((d) => nodes.has(d.src) && nodes.has(d.tgt))
//.filter(d=> d.till <= nodes.get(d.tgt).first && d.from <= nodes.get(d.src).last)
let edgelist =
// prune edges using group slicing
Object.values(Object.groupBy(filtered,d=>d.src)).map(d=>d.slice(0,4)).flat()
.map((d) => ` "${d.src}" -> "${d.tgt}" [weight=${Math.pow(d.weight,0.5)}, penwidth=${Math.pow(d.weight,0.25)}, opacity=0.1, dir=none]`)
.join("\n")
return `digraph timeline {
${header}

${timeline}

${nodestyle}
${groups.map((d) => `{ rank=same; ${[d[0], d[1].map((d) => '"' + d[0] + '"').join(" ")].join(" ")}; }`).join("\n")}

${edgestyle}
${edgelist}

${''/*
"Gardner" -> "Lambert" [weight=2.8284271247461903, penwidth=1.6817928305074292, opacity=0.1, dir=none, label="Influenced"]
"Gardner" -> "Scarcella" [weight=3, penwidth=1.7320508075688772, opacity=0.1, dir=none, label="Mentorship"]
"Lambert" -> "Carroll" [weight=2, penwidth=1.414213562373095, opacity=0.1, dir=none, label="Collaboration"]
"Selinker" -> "Scarcella" [weight=3, penwidth=1.7320508075688772, opacity=0.1, dir=none, label="Foundational Work"]
"Hatch" -> "Scarcella" [weight=3.4641016151377544, penwidth=1.8612097182041991, opacity=0.1, dir=none, label="Key Collaboration"]
"Krashen" -> "Scarcella" [weight=7.483314773547883, penwidth=2.735564799734761, opacity=0.1, dir=none, label="Major Influence"]
"Dulay" -> "Burt" [weight=4.123105625617661, penwidth=2.0305431848689306, opacity=0.1, dir=none, label="Shared Research"]
"Schumann" -> "Seliger" [weight=1.7320508075688772, penwidth=1.3160740129524924, opacity=0.1, dir=none, label="Theoretical Alignment"]
"Swain" -> "Scarcella" [weight=2.449489742783178, penwidth=1.5650845800732873, opacity=0.1, dir=none, label="Conceptual Contribution"]
"Fröhlich" -> "Scarcella" [weight=1.7320508075688772, penwidth=1.3160740129524924, opacity=0.1, dir=none, label="Direct Influence"]*/}

}`.replaceAll('\n','')
}
Insert cell
Insert cell
coWordEdges = {

let dict = Object.groupBy(
prep.flatMap(({ authors, keyphrase, year }) =>
authors.flatMap((a) =>
keyphrase.map((p) => [canonical[p], { last: a.last.replace(/\-\'/g,''), year }])
)
),
(d) => d[0]
);
let filt = Object.values(dict)
.map((arr) => arr.map((d) => d[1]))
.map((arr) =>
arr.map((x) =>
arr
.map((y) => [x, y])
.filter(
(d) =>
//Math.abs(d[0]?.year - d[1]?.year) > 1 &&
d[0].year <= d[1].year
&&d[0].last != d[1].last
)
.map((d) => ({
src: d[0].last,
from: d[0].year,
tgt: d[1].last,
till: d[1].year
}))
)
)
.flat(2);

let edges = Object.values(Object.groupBy(filt, (d) => d.src + "_" + d.tgt))
.map((d) => ({ ...d[0], weight: d.length }))
.filter((d) => d.weight > 1 || d.src != "Krashen" || d.tgt != "Krashen")
//.filter(d=> d.src != "Krashen" /*&& d.tgt != "Krashen"*/)
.sort((a, b) => a.from - b.from);
return edges;

}

Insert cell
Insert cell
Insert cell
phraseAuthors = {

let keep = new Set(
Object.entries(
Object.groupBy(
prep.flatMap((d) => d.authors.map((d) => d.last)),
(d) => d
)
)
.filter((d) => d[1].length > 1)
.sort((a, b) => b[1].length - a[1].length)
.map((d) => d[0])
);

let also = new Set(
prep
.flatMap((d) =>
d.authors.flatMap((a) => d.keyphrase.map((d) => [d, a.last]))
)
.filter((d) => counts.get(canonical[d[0]]).freq > 6)
.map((d) => d[1])
);

// return prep.map( ({authors,keyphrase})=>Object.fromEntries(authors.map(a=>[a.last,keyphrase])))
// return prep.flatMap( ({authors,keyphrase})=> authors.map(a=> ({[a.last]:keyphrase})))

return Object.fromEntries(
Object.entries(
Object.groupBy(
prep
.flatMap(({ authors, keyphrase }) =>
authors.flatMap((a) => keyphrase.map((p) => [canonical[p], a.last]))
)
.filter((d) => keep.has(d[1]) || also.has(d[1])),
(d) => d[0]
)
).map((d) => [
d[0],
Object.fromEntries(
Object.entries(Object.groupBy(d[1], (d) => d[1]))
.map((d) => [d[0], d[1].length])
.sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0]))
)
])
);
}

Insert cell
Insert cell
Insert cell
argdownHeader = `===
model:
removeTagsFromText: true
mode: loose
color:
colorScheme: iwanthue-red-roses
relationColors:
support: "#dddddd"
attack: "#dddddd"
undercut: "#dddddd"
contrary: "#dddddd"
contradictory: "#dddddd"
entails: "#dddddd"

dot:
statement:
minWidth: 0
margin: "0.05,0"
title:
font: helvetica
fontSize: 16
bold: false
text:
font: argvu
fontSize: 20
argument:
title:
font: argvu
fontSize: 20
bold: true
text:
font: argvu
fontSize: 20
graphVizSettings:
rankdir: LR
ranksep: 0
nodesep: 0.15
concentrate: true
outputorder: edgesfirst
===`
Insert cell
dot`digraph shells {
rankdir = "TB";
ranksep = "0";
nodesep = "0.1";
concentrate = "false";
outputorder = "edgesfirst";
ratio = "auto";
size = "10,10";
edge[arrowsize="0.75", penwidth="0.5"]
graph[bgcolor = "transparent" ]

node [fontsize=20, shape = box, fontname= Arial, fontsize = 14];
1972 -> 1976;
1976 -> 1978;
1978 -> 1980;
1980 -> 1982;
1982 -> 1984;
1984 -> 1986;
1986 -> 1988;
1988 -> 1990;
1990 -> future;

node [shape="box", margin="0.1,0", style="filled,rounded,bold", color="#e17892", fillcolor="white", labelfontcolor="white", fontcolor="#000000", type="statement-map-node"]
{ rank=same; 1976 Mashey Bourne; }
{ rank=same; 1978 Formshell csh; }
{ rank=same; 1980 esh vsh; }
{ rank=same; 1982 ksh "System-V"; }
{ rank=same; 1984 v9sh tcsh; }
{ rank=same; 1986 "ksh-i"; }
{ rank=same; 1988 KornShell Perl rc; }
{ rank=same; 1990 tcl Bash; }
{ rank=same; "future" POSIX "ksh-POSIX"; }

edge [color="#dddddd"]
Thompson -> Mashey;
Thompson -> Bourne;
Thompson -> csh;
csh -> tcsh;
Bourne -> ksh;
Bourne -> esh;
Bourne -> vsh;
Bourne -> "System-V";
Bourne -> v9sh;
v9sh -> rc;
Bourne -> Bash;
"ksh-i" -> Bash;
KornShell -> Bash;
esh -> ksh;
vsh -> ksh;
Formshell -> ksh;
csh -> ksh;
KornShell -> POSIX;
"System-V" -> POSIX;
ksh -> "ksh-i";
"ksh-i" -> KornShell;
KornShell -> "ksh-POSIX";
Bourne -> Formshell;

edge [style=invis];
1984 -> v9sh -> tcsh ;
1988 -> rc -> KornShell;
//Formshell -> csh;
//KornShell -> Perl;
}`

Insert cell
Insert cell
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