Public
Edited
Oct 22, 2024
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
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
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
Insert cell
function normalize(scores, res = []) {
const max = d3.max(scores);
const min = d3.min(scores);
for (let i = 0; i < scores.length; i++) {
if (max != min) {
res[i] = (scores[i] - min) / (max - min);
} else {
res[i] = scores[i];
}
}

return res;
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
// Copyright 2021 Observable, Inc.
// Released under the ISC license.
// https://observablehq.com/@d3/multi-line-chart
function LineChart(
data,
{
x = ([x]) => x, // given d in data, returns the (quantitative) x-value
y = ([, y]) => y, // given d in data, returns the (categorical) y-value
z = () => 1, // given d in data, returns the (categorical) z-value
title = "", // given d in data, returns the title text
defined, // for gaps in data
curve = d3.curveLinear, // method of interpolation between points
marginTop = 20 + 20 + 10, // top margin, in pixels
marginRight = 30, // right margin, in pixels
marginBottom = 30 + 50, // bottom margin, in pixels
marginLeft = 40 + 40 + 5, // left margin, in pixels
width = 640, // outer width, in pixels
height = 400, // outer height, in pixels
xType = d3.scaleLinear, // type of x-scale
xDomain, // [xmin, xmax]
xRange = [marginLeft, width - marginRight], // [left, right]
yType = d3.scaleLinear, // type of y-scale
yDomain, // [ymin, ymax]
xxDomain, // reversed xDomain to show ranks from top to bottom
yRange = [height - marginBottom, marginTop], // [bottom, top]
yFormat, // a format specifier string for the y-axis
yLabel, // a label for the y-axis
zDomain, // array of z-values
color,
// colors = d3.interpolateBlues, // stroke color of line, as a constant or a function of *z*
strokeLinecap, // stroke line cap of line
strokeLinejoin, // stroke line join of line
strokeWidth = 1.25, // stroke width of line
strokeOpacity = 0.3, // stroke opacity of line
mixBlendMode = "multiply", // blend mode of lines
voronoi, // show a Voronoi overlay? (for debugging)
scores_distribution = [],
rank_boundaries = [],
selected_color_attr = "Research",
selected_categorical_value
} = {}
) {
// Compute values.
const X = d3.map(data, x);
const Y = d3.map(data, y);
const Z = d3.map(data, z);
const O = d3.map(data, (d) => d);
// if (defined === undefined) defined = (d, i) => !isNaN(X[i]) && !isNaN(Y[i]);
if (defined === undefined) defined = (d, i) => !isNaN(X[i]);
const D = d3.map(data, defined);

// console.log(X);

// Compute default domains, and unique the z-domain.
if (xDomain === undefined) xDomain = d3.extent(X);
if (yDomain === undefined) yDomain = Y;
if (xxDomain === undefined) xxDomain = [1, d3.max(X)];

if (zDomain === undefined) zDomain = Z;
zDomain = new d3.InternSet(zDomain);

// const color = d3.scaleSequential(xDomain, colors)

// Omit any data not present in the z-domain.
const I = d3.range(X.length).filter((i) => zDomain.has(Z[i]));

// Construct scales and axes.
const xScale = xType(xDomain, xRange);
const yScale = d3.scalePoint(yDomain, yRange);

const xxScale = xType(xxDomain, xRange);
// const xAxis = d3.axisBottom(xxScale).ticks(width / 80).tickSizeOuter(0);
// const yAxis = d3.axisLeft(yScale).ticks(height / 60, yFormat);

const num_of_ranks = data.length / 2;
const num_of_tick_labels = parseInt(num_of_ranks.toFixed()) / 10;

var ticks = [];
for (var i = 0; i <= num_of_ranks - 1; i += 1) {
ticks.push({ value: i + 1, isVisible: (i + 1) % 20 === 0 });
}
console.log(ticks);
var isMajorTick = function (index) {
return ticks[index].isVisible;
};
var tickValues = ticks.map(function (t) {
return t.value;
});

const xAxis = d3
.axisBottom(xxScale)
.ticks(width / 30)
// .tickValues(tickValues)
// .tickFormat(function (d, i) {
// return isMajorTick(i) ? d : "";
// })
.tickPadding(5)
.tickSize(15);

const yAxis = d3.axisLeft(yScale).ticks(height / 60); //.tickSizeOuter(0);
const score_histogram_axis = d3
.axisTop(xxScale)
.ticks(width / 30)
.tickSize(0)
.tickFormat((d) => "");

// Construct a line generator.
const line = d3
.line()
.defined((i) => D[i])
.curve(curve)
.x((i) => xScale(X[i]))
.y((i) => yScale(Y[i]));

const brush = d3
.brushX()
.extent([
[marginLeft, height - (marginBottom + 30)],
[width - (marginRight - 20), height - (marginBottom - 80)]
])
.on("brush", brushed)
.on("end", ended);

const score_brush = d3
.brushX()
.extent([
[marginLeft - 10, 0],
[width - (marginRight - 20), marginTop + 20]
])
.on("brush", score_brushed)
.on("end", ended);

const svg = d3
.create("svg")
.attr("width", width)
.attr("height", height)
.attr("viewBox", [0, 0, width, height])
.attr("style", "max-width: 100%; height: auto; height: intrinsic;")
.style("-webkit-tap-highlight-color", "transparent")
.on("dblclick", dblclicked);

const text_container = svg
.selectAll(".text_container")
.data(["0"])
.join("g")
.classed("text_container", true);

text_container
.selectAll(".title")
.data([title])
.join("text")
.classed("title", true)
.attr("x", width / 2)
.attr("y", 10)
.attr("text-anchor", "middle")
.style("font-size", "12px")
.text(title);
text_container
.selectAll(".score_high")
.data(["0"])
.join("text")
.classed("score_high", true)
.attr("x", marginLeft)
.attr("y", 7)
.attr("text-anchor", "middle")
.style("font-size", "10px")
.style("font-weight", "bold")
.style("fill", "grey")
.text("high");
text_container
.selectAll(".score_low")
.data(["0"])
.join("text")
.classed("score_low", true)
.attr("x", width - marginRight)
.attr("y", 7)
.attr("text-anchor", "middle")
.style("font-size", "10px")
.style("font-weight", "bold")
.style("fill", "grey")
.text("low");
text_container
.selectAll(".rank_high")
.data(["0"])
.join("text")
.classed("rank_high", true)
.attr("x", marginLeft)
.attr("y", height - 40)
.attr("text-anchor", "middle")
.style("font-size", "10px")
.style("font-weight", "bold")
.style("fill", "grey")
.text("high");
text_container
.selectAll(".rank_low")
.data(["0"])
.join("text")
.classed("rank_low", true)
.attr("x", width - marginRight)
.attr("y", height - 40)
.attr("text-anchor", "middle")
.style("font-size", "10px")
.style("font-weight", "bold")
.style("fill", "grey")
.text("low");

const container = svg
.selectAll(".label-container")
.data(["0"])
.join("g")
.classed("label-container", true)
.attr("display", "none");

svg
.selectAll(".brush")
.data(["0"])
.join("g")
.classed("brush", true)
.call(brush);
svg
.selectAll(".score_brush")
.data(["0"])
.join("g")
.classed("score_brush", true)
.call(score_brush);

// An optional Voronoi display (for fun).
if (voronoi)
svg
.append("path")
.attr("fill", "none")
.attr("stroke", "#ccc")
.attr(
"d",
d3.Delaunay.from(
I,
(i) => xScale(X[i]),
(i) => yScale(Y[i])
)
.voronoi([0, 0, width, height])
.render()
);

const x_axis = svg
.selectAll(".x_axis_g")
.data(["0"])
.join("g")
.attr("id", "x_axis")
.attr("class", "x axis")
.attr("transform", `translate(0,${height - marginBottom})`)
.call(xAxis);

// x_axis
// .selectAll("g")
// .filter(function (d, i) {
// return !isMajorTick(i);
// })
// .classed("minor", true);

svg
.append("g")
.attr("transform", `translate(${marginLeft},0)`)
.style("font", "20px times")
.call(yAxis)
.call((g) => g.select(".domain").remove())
.call(
voronoi
? () => {}
: (g) =>
g
.selectAll(".tick line")
.clone()
.attr("x2", width - marginLeft - marginRight)
.attr("stroke-opacity", 0.1)
)
.call((g) =>
g
.append("text")
.attr("x", -marginLeft)
.attr("y", 10)
.attr("fill", "currentColor")
.attr("text-anchor", "start")
.text(yLabel)
);

svg
.selectAll(".score_histogram_axis")
.data(["0"])
.join("g")
.classed("score_histogram_axis", true)
.attr("transform", `translate(0,${marginTop})`)
.call(score_histogram_axis);

let temp = d3.group(I, (i) => Z[i]);
let temp_values = [...temp.keys()];
let indexes = [...Array(temp_values.length).keys()];

const path_container = svg
.selectAll(".path_container")
.data(["0"])
.join("g")
.classed("path_container", true);

const path = path_container
.attr("fill", "none")
.attr("stroke", "grey")
.attr("stroke-linecap", strokeLinecap)
.attr("stroke-linejoin", strokeLinejoin)
.attr("stroke-width", strokeWidth)
.attr("stroke-opacity", strokeOpacity)
.selectAll("path")
.data(d3.group(I, (i) => Z[i]))
.join("path")
.style("mix-blend-mode", mixBlendMode)
.attr("stroke", function (d, i) {
if (
filtered_data[indexes[i]][selected_color_attr] ===
selected_categorical_value
) {
return color_scale(filtered_data[indexes[i]][selected_color_attr]);
} else {
return "#c0c0c0";
}
})
.attr("d", ([, I]) => line(I))
.on("click", function () {
d3.select(this).classed("selected", true);
mutable on_click = true;
let temp = JSON.stringify(this);
let id = temp.substring(temp.indexOf("[") + 1, temp.indexOf(","));
let subset = temp.substring(temp.indexOf(",") + 1, temp.indexOf("]") + 1);
let rank_index = parseInt(subset.substring(1, subset.indexOf(",")));
let score_index = parseInt(
subset.substring(subset.indexOf(",") + 1, subset.length - 1)
);
highlighted_ids.push(parseInt(id));
clicked_ranks.push(data[rank_index]["value"]);
on_click_ids.push(id);
on_click_rank_indexes.push(rank_index);
on_click_data.push({
id: id,
rank: data[rank_index]["value"],
rank_coord: xScale(data[rank_index]["value"])
});
get_single_label(on_click_data);
});

function get_score_x_coordinates() {
let res = {};
let starting_x_coords_lst = [];
let html_string_1 = path["_groups"][0][0]["outerHTML"].substring(
path["_groups"][0][0]["outerHTML"].indexOf("d")
);
let rank_y1 = html_string_1.substring(
html_string_1.indexOf(",") + 1,
html_string_1.indexOf("L")
);
let score_y1 = html_string_1.substring(
html_string_1.indexOf(",", html_string_1.indexOf("L")) + 1,
html_string_1.indexOf("s", html_string_1.indexOf("L")) - 2
);
for (let i = 0; i < path["_groups"][0].length; i++) {
let html_string = path["_groups"][0][i]["outerHTML"];
starting_x_coords_lst[i] = html_string.substring(
html_string.indexOf("L") + 1,
html_string.indexOf(",", html_string.indexOf("L"))
);
}
return {
coords: starting_x_coords_lst,
rank_y1: parseInt(rank_y1),
score_y1: parseInt(score_y1)
};
}

const scores_dist_values = scores_distribution.map((d) => d.dist);

const scores_dist_scale = d3
.scaleLinear()
.domain([0, d3.max(scores_dist_values)])
.range([50, 10]);

const axis_coords = get_score_x_coordinates();
const coords = axis_coords.coords;
const score_lines_data = scores_distribution;

const score_lines = svg
.selectAll(".score_lines_g")
.data(["0"])
.join("g")
.classed("score_lines_g", true)
.selectAll("line")
.data(score_lines_data)
.classed("score_lines", true)
.join("line")
.attr("x1", (d) => xScale(d.key))
.attr("x2", (d) => xScale(d.key))
.attr("y1", scores_dist_scale(0))
.attr("y2", (d) => scores_dist_scale(d.dist))
.attr("stroke", "grey");

// In the is_brushed function & in is_score_brushed add
// rank_boundaries.classed(...) to set the lines in rank_boundaries
// as "selected"
// - create get_id_by_rank() to get id and then find the value
// of the selected categorical attr if it matches the plot's value
// - set the stroke to be the color of the lines
// On dbclicked --> set the classed "selected" to false
// Also need to add condition in if statement

// const rank_boundary_lines = svg
// .append("g")
// .selectAll("line")
// .data(rank_boundaries)
// .join("line")
// .attr("x1", (d) => xScale(d))
// .attr("x2", (d) => xScale(d))
// .attr("y1", axis_coords.rank_y1)
// .attr("y2", axis_coords.rank_y1 + 10)
// .attr("stroke", "grey");

var selected_ranks = [];
var s_ranks = [];

var on_click_data = [];
var on_click_ids = [];
var on_click_rank_indexes = [];

function get_single_label(lst) {
let coords = lst.map((d) => d.rank_coord);
let ids = lst.map((d) => d.id);
let ranks = lst.map((d) => d.rank);
let coord = height - (marginBottom - 45);
container.attr("display", null);

const containers = container
.selectAll("g")
.data(lst)
.join("g")
.classed("single-label-container", true)
.attr(
"transform",
({ rank_coord }) => `translate(${[rank_coord, coord].join(",")})`
);

containers.selectAll("path").remove();
const boxes = containers
.append("path")
.attr("class", "tooltip")
.attr("fill", "#d58a3c")
.attr("opacity", "0.5");

containers.selectAll("text").remove();
const labels = containers
.append("text")
.data(ranks)
.text((d) => "Rank: " + d)
.attr("class", "tooltip")
.attr("font-family", "sans-serif")
.attr("font-size", 10)
.attr("text-anchor", "middle")
.attr("y", -10)
.attr("x", 0);

const vals = { x: -23, y: -17, height: 19, width: 47 };
boxes.attr(
"d",
`M${-vals.width / 2 - 10}, 5H-5l5,-5l5, 5H${vals.width / 2 + 10}v${
vals.height + 25
}h-${vals.width + 20}z`
);

labels.attr("transform", `translate(0, 33)`);
}

function get_labels(selected_ranks, selection, ranges) {
let x_max = xScale(d3.max(selected_ranks));
let x_min = xScale(d3.min(selected_ranks));

container.attr(
"transform",
`translate(${(x_max + x_min) / 2},${height - (marginBottom - 35)})`
);
container.attr("display", null);

const box = container
.selectAll("path")
.data([,])
.join("path")
.attr("class", "tooltip")
.attr("fill", "#d58a3c")
.attr("opacity", "0.5");

const label = container
.selectAll("text")
.data([,])
.join("text")
.attr("class", "tooltip")
.call((text) =>
text
.selectAll("tspan")
.data(`${ranges}`.split(/\n/))
.join("tspan")
.attr("x", 0)
.attr("y", (_, i) => `${i * 1.1}em`)
.text("Rank ranges: " + ranges[0] + " - " + ranges[1])
)
.attr("font-family", "sans-serif")
.attr("font-size", 10)
.attr("text-anchor", "middle")
.attr("y", -8);

const vals = { x: -55, y: -9, height: 11, width: 110 };
box.attr(
"d",
`M${-vals.width / 2 - 10}, 5H-5l5,-5l5, 5H${vals.width / 2 + 10}v${
vals.height + 25
}h-${vals.width + 20}z`
);
const limitW = xScale(X[data.length - 1]);
const hbw = vals.width / 2 + 10;
const hbh = vals.height / 2 + 10;
const switchHW = limitW - hbw;
const tooltipOver = `M${-hbw},-5H-5l5,5l5,-5H${hbw}v${-hbh * 2}h-${
2 * hbw
}z`;
const tooltipUnder = `M${-hbw},5H-5l5,-5l5,5H${hbw}v${hbh * 2}h-${
2 * hbw
}z`;
const tooltipLeft = `M-5,${-hbh}V-5l5,5l-5,5V${hbh}H${-hbw * 2}V-${hbh}z`;
const tooltipRight = `M5,${-hbh}V-5l-5,5l5,5V${hbh}H${hbw * 2}V-${hbh}z`;
box.attr(
"d",
selection[0] > switchHW
? tooltipLeft
: selection[1] < hbw
? tooltipRight
: tooltipUnder
);
const shiftLabelX =
selection[0] > switchHW ? -hbw : selection[1] < hbw ? hbw : 0;
const shiftLabelY =
selection[0] > switchHW || selection[1] < hbw
? vals.y - vals.height / 2 + 15
: 15 - vals.y;
label.attr("transform", `translate(${shiftLabelX},${shiftLabelY})`);
}

if (unique_highlighted_ids.length != 0) {
path.classed("selected", function (d) {
if (unique_highlighted_ids.includes(d[0])) {
s_ranks.push(X[d[1][0]]);
}
let val = get_selected_categorical_attr_value(d[0], selected_color_attr);
return (
unique_highlighted_ids.includes(d[0]) &&
val === selected_categorical_value
);
});
if (
clicked_ranks.length != 0 &&
clicked_ranks.length === highlighted_ids.length
) {
let c_data = [];
for (let i = 0; i < highlighted_ids.length; i++) {
let rank = get_rank(highlighted_ids[i], data);
c_data.push({
id: highlighted_ids[i],
rank: rank,
rank_coord: xScale(rank)
});
}
setTimeout(get_single_label(c_data), 3000);
} else {
if (s_ranks.length != 0) {
let s_rank_range = d3.extent(s_ranks);
let [init_x, init_y] = [
xScale(s_rank_range[0]),
xScale(s_rank_range[1])
];
setTimeout(get_labels(s_ranks, [init_x, init_y], s_rank_range), 3000);
}
}
}

function score_brushed({ selection }) {
if (selection) {
updateChart_score_brush(selection);
}
}

function updateChart_score_brush(sel, d) {
path.classed("selected", function (d) {
return isBrushed_score_brush(sel, d);
});
}

function isBrushed_score_brush(brush_coords, d) {
let cx = xScale(data[d[1][1]]["value"]);
var x0 = brush_coords[0],
x1 = brush_coords[1];
let val = get_selected_categorical_attr_value(d[0], selected_color_attr);
if (x0 <= cx && cx <= x1) {
highlighted_ids.push(d[0]);
selected_ranks.push(X[d[1][0]]);
}
return x0 <= cx && cx <= x1 && val === selected_categorical_value;
}

function brushed({ selection }) {
if (selection) {
updateChart(selection);
}
}

function updateChart(sel, d) {
path.classed("selected", function (d) {
return isBrushed(sel, d);
});
}

function isBrushed(brush_coords, d) {
let cx = xScale(X[d[1][0]]);
var x0 = brush_coords[0],
x1 = brush_coords[1];
let val = get_selected_categorical_attr_value(d[0], selected_color_attr);
if (x0 <= cx && cx <= x1) {
highlighted_ids.push(d[0]);
selected_ranks.push(X[d[1][0]]);
}
return x0 <= cx && cx <= x1 && val === selected_categorical_value;
}

function ended({ selection }) {
if (selection) {
let ranges = d3.extent(selected_ranks);
get_labels(selected_ranks, selection, ranges);
}
}

function dblclicked(event, d) {
highlighted_ids.length = 0;
selected_ranks.length = 0;
on_click_ids.length = 0;
on_click_rank_indexes.length = 0;
on_click_data.length = 0;
clicked_ranks.length = 0;
mutable on_click = false;
path.classed("selected", false);
container.attr("display", "none");
}

return Object.assign(svg.node(), { value: null });
}
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
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
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
function get_number_of_items_per_score(lst) {
let scores_dict = {};
for (let i = 0; i < lst.length; i++) {
if (scores_dict.hasOwnProperty(lst[i])) {
scores_dict[lst[i]] += 1;
} else {
scores_dict[lst[i]] = 1;
}
}
return scores_dict;
}
Insert cell
Insert cell
function get_sorted_scores_dist(obj) {
let res = [];

let keys = Object.keys(obj);
keys = keys.map((e) => parseFloat(e));
keys = keys.sort(function (a, b) {
return a - b;
});

for (let i = 0; i < keys.length; i++) {
let vals = {};
vals["key"] = keys[i];
vals["dist"] = obj[keys[i]];
res.push(vals);
}
return res;
}
Insert cell
function get_scores_with_ties(arr, threshold) {
let res = [];
for (let i = 0; i < arr.length; i++) {
res[i] = arr[i];
}
for (let i = 0; i < res.length; i++) {
if (res[i] - res[i + 1] <= threshold) {
let delta = res[i] - res[i + 1];
for (let j = i; j < res.length - 1; j++) {
res[j + 1] = res[j + 1] + delta;
}
}
}
return res;
}
Insert cell
Insert cell
function process_scores_with_ties(lst, data, threshold) {
let res = [];
let scores_as_nums = lst.map((d) => parseFloat(d));

let dict = [];
for (let i = 0; i < data.length; i++) {
let obj = {};
obj["id"] = data[i]["id"];
obj["score"] = scores_as_nums[i];
dict.push(obj);
}

dict.sort(function (a, b) {
return b.score - a.score;
});

let sorted_scores = dict.map((d) => d.score);
let scores_with_ties = get_scores_with_ties(sorted_scores, threshold);

for (let i = 0; i < scores_with_ties.length; i++) {
dict[i]["score"] = scores_with_ties[i];
}

dict.sort(function (a, b) {
return a.id - b.id;
});

res = dict.map((d) => d.score);
return res;
}
Insert cell
function get_max_tie(lst) {
let res;
let lst_as_nums = lst.map((d) => parseFloat(d));
let max = d3.max(lst_as_nums);
let min = d3.min(lst_as_nums);

res = max - min;
return res;
}
Insert cell
function get_largest_score_difference(lst) {
let res = [];
let scores_as_nums = lst.map((d) => parseFloat(d));

let dict = [];
for (let i = 0; i < data.length; i++) {
let obj = {};
obj["id"] = data[i]["id"];
obj["score"] = scores_as_nums[i];
dict.push(obj);
}

dict.sort(function (a, b) {
return b.score - a.score;
});

let sorted_scores = dict.map((d) => d.score);

let max = 0;
for (let i = 0; i < sorted_scores.length; i++) {
if (sorted_scores[i] - sorted_scores[i + 1] >= max) {
max = sorted_scores[i] - sorted_scores[i + 1];
}
}

return parseFloat(max.toFixed(3)) + 0.001;
}
Insert cell
Insert cell
ranker_0_lst = get_rankers_by_categorical_values(
ranker_0_selected_scoring_attrs,
selected_categorical_attr,
tie_threshold_0,
scores_dist_parsed_0,
"Ranker 0",
[
GREweight,
TOEFLweight,
UniversityRatingweight,
SOPweight,
LORweight,
CGPAweight,
Researchweight
],
550,
300
)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Ranker_0 = new Ranker(
ranker_0_selected_scoring_attrs,
[
GREweight,
TOEFLweight,
UniversityRatingweight,
SOPweight,
LORweight,
CGPAweight,
Researchweight
],
scores_dist_parsed_0,
1000,
400,
"Ranker 0"
)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
slopedata2 = slopeChartHelperUntiedRank(data_rank2)
Insert cell
function serialize (data) {
let parser = new json2csv.Parser();
let csv = parser.parse(data);
return new Blob([csv], {type: "text/csv"})
}
Insert cell
json2csv = import(
"https://unpkg.com/@json2csv/plainjs@7.0.6/dist/mjs/index.js?module"
)
Insert cell
DOM.download(serialize(slopedata2), null, "Download CSV")
Insert cell
console.log(slopedata2)
Insert cell
Insert cell
max_tie = get_largest_score_difference(Scores)
Insert cell
Scores = ranker_0_scaled_scoring_attrs.map((d) => createScore(d, weights))
Insert cell
Scores_with_tie_threshold = process_scores_with_ties(
Scores,
ranker_0_scoring_attrs_data,
tie_threshold_0
)
Insert cell
normlizedScores = normalize(Scores_with_tie_threshold)
Insert cell
Scores_with_tie_threshold_0 = normalize(
process_scores_with_ties(Scores, ranker_0_scoring_attrs_data, 0)
)
Insert cell
score_values_0 = slopedata2.map(function (d) {
if (d.axis === "score") {
return d["value"];
} else {
return "";
}
})
Insert cell
score_values_filtered_0 = score_values_0.filter((e) => e != "")
Insert cell
scores_dist_0 = get_number_of_items_per_score(score_values_filtered_0)
Insert cell
scores_dist_parsed_0 = get_sorted_scores_dist(scores_dist_0)
Insert cell
function rankings(arr) {
const sorted = [...arr].sort((a, b) => b - a);
return arr.map((x) => sorted.indexOf(x) + 1);
}
Insert cell
function rankings2(scores, ranks1) {
const scores_ids = [];
data_rank.map((d) => scores_ids.push([d.score, d.item.id]));

const sorted = [...scores_ids].sort((a, b) => b[0] - a[0] || a[1] - b[1]);
return scores_ids.map((x) => sorted.indexOf(x) + 1);
}
Insert cell
Insert cell
Ranks = rankings(Scores_with_tie_threshold_0)
Insert cell
Ranks2=rankings2(data_rank)
Insert cell
data_rank = filtered_data.map((item, index) => {
return {
item: item,
rank: Ranks[index],
score_0: Scores_with_tie_threshold_0[index],
score: normlizedScores[index]
};
})
Insert cell
data_rank2 = filtered_data.map((item, index) => {
return {
item: item,
rank: Ranks2[index],
score_0: Scores_with_tie_threshold_0[index],
score: normlizedScores[index]
};
})
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
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
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
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
Ranks_2 = rankings(Scores_with_tie_threshold_0_r2)
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
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
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
Insert cell
Insert cell
Insert cell
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