Public
Edited
Feb 6, 2024
Insert cell
Insert cell
Insert cell
Insert cell
theplot2 = {

const margin = {top: 25, right: 10, bottom: 40, left: 60}
const svg = d3.create("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom);
const x = d3.scaleLinear().rangeRound([0, width]),
y = d3.scaleLinear().rangeRound([height, 0]);

const g = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");



const points = thepoints;

x.domain([0, 100]);
y.domain([20, 180]);

g.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));

g.append("g")
.attr("class", "axis axis--y")
.call(d3.axisLeft(y));

// Add X axis label:
g.append("text")
.attr("text-anchor", "end")
.attr("x", width)
.attr("y", height + margin.top + 10)
.text("X axis title")
.attr("font-size", 12)
.text("Matching-Variable 1");

// Y axis label:
g.append("text")
.attr("text-anchor", "end")
.attr("transform", "rotate(-90)")
.attr("y", -margin.left+20)
.attr("x", 0)
.attr("font-size", 12)
.text("Matching-Variable 2");

thepoints.push({x: 50, y: 100, color: "blue"});
var perimeter = g.append("circle")
.attr("class", "perimeter")
.style("fill", "none")
.style("stroke", "black")
.attr('stroke-dasharray', '7,7')
.attr("cx", x(xc))
.attr("cy", y(yc))
.attr("r", 80);
var circle = g.selectAll(".point")
.data(points)
.enter().append("circle")
.attr("class", "point")
.attr("r", 4)
.attr("cx", function(d) { return x(d.x); })
.attr("cy", function(d) { return y(d.y); })
.style("fill", function(d) { return d.color; });


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


circle.each(function(c, i) {
var curX = c.x;
var curY = c.y;
var mDistance = MahalanobisDistance( curX, curY, xc, yc );

if( curX === xc && curY === yc ) {
d3.select(this)
.style('stroke', 'black')
.style('stroke-width', 2)
.attr('r', 7)
} else
if(mDistance <= caliper && c.color !== thecol) {
d3.select(this)
.style('fill', 'cyan')

}

// Compute the eigenvalues and eigenvectors
var eigenDecomposition = math.eigs(covarianceMatrix);

// Find the largest eigenvalue and its corresponding eigenvector
var eigenvalues = eigenDecomposition.values;
var eigenvectors = eigenDecomposition.vectors;
const semiMajorAxis = Math.sqrt(mDistance * eigenvalues[0]);
const semiMinorAxis = Math.sqrt(mDistance * eigenvalues[1]);

// Draw the ellipse
const svg = d3.select("#svg-container");

svg
.append("ellipse")
.attr("cx", x(xc))
.attr("cy", y(yc))
.attr("rx", x(semiMajorAxis))
.attr("ry", y(semiMinorAxis))
.attr("fill", "none")
.attr("stroke", "blue");
});
circle.on("click", (e, d) => {
mutable xc = d.x
mutable yc = d.y
mutable thecol = d.color;
const distances = points.map(point => ({
point,
distance: Math.sqrt(Math.pow(x(point.x) - x(xc), 2) + Math.pow(y(point.y) - y(yc), 2))
}));
svg
.append("text")
.attr("x", x(70))
.attr("y", y(30)) // Adjust the vertical position as needed
.attr("text-anchor", "middle") // Center the text horizontally
.text(`rx: ${distances}`);

// Filter circles of the opposite color
const oppositeColorDistances = distances.filter(item => item.point.color == 'cyan');

// Sort by distance
oppositeColorDistances.sort((a, b) => a.distance - b.distance);

// Select the five nearest circles
const nearestCircles = oppositeColorDistances.slice(0, 5);

// Draw lines from the clicked circle to the five nearest circles
nearestCircles.forEach(item => {
const selectedCircle = item.point;
g.append("line")
.attr("class", "line")
.attr("x1", x(xc))
.attr("y1", y(yc))
.attr("x2", x(selectedCircle.x))
.attr("y2", y(selectedCircle.y))
.attr("stroke", "black")
.attr("stroke-width", 4)
.attr("stroke-dasharray", "3,3");
});



});

// Adding the horizontal legend above the plotting area
var legend = svg.append("g")
.attr("class", "legend")
.attr("transform", "translate(" + margin.left + "," + (margin.top - 40) + ")");

legend.append("rect")
.attr("class", "legend-bg")
.attr("width", 150)
.attr("height", 40)
.attr("rx", 5)
.attr("ry", 5);

legend.append("circle")
.attr("cx", 20)
.attr("cy", 20)
.attr("r", 5)
.style("fill", "blue");

legend.append("text")
.attr("x", 30)
.attr("y", 25)
.text("Behandlung");

legend.append("circle")
.attr("cx", 100)
.attr("cy", 20)
.attr("r", 5)
.style("fill", "red");

legend.append("text")
.attr("x", 110)
.attr("y", 25)
.text("Kontrolle");

return svg.node();
}
Insert cell
viewof caliper1 = Inputs.range([0, 2], {label: "Distance to the selected point", step: .01, value: .8})

Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
seed = Array.from({length: 400}, (_, i) => i + 1)
Insert cell
Insert cell
thepoints = d3.range(400).map(function(d) {
let x = gaussianRandom(meanX, stdDevX);
let Z = gaussianRandom(0, 1); // Standard normal variable
let y = meanY + correlationFactor * (stdDevY / stdDevX) * (x - meanX) + Z * stdDevY * Math.sqrt(1 - correlationFactor * correlationFactor);

return {
x: x,
y: y,
color: d % 2 === 1 ? "blue" : "red"
};
})
Insert cell
Insert cell
Insert cell
Insert cell
height = 400
Insert cell
width = 500
Insert cell
Insert cell
meanY = 100;
Insert cell
meanX = 50;
Insert cell
stdDevX = 15;
Insert cell
stdDevY = 20;
Insert cell
covXY = correlationFactor * stdDevX * stdDevY;
Insert cell
covarianceMatrix = [
[stdDevX * stdDevX, covXY],
[covXY, stdDevY * stdDevY]
];
Insert cell
det = covarianceMatrix[0][0] * covarianceMatrix[1][1] - covarianceMatrix[0][1] * covarianceMatrix[1][0];
Insert cell
inverseMatrix = [
[covarianceMatrix[1][1] / det, -covarianceMatrix[0][1] / det],
[-covarianceMatrix[1][0] / det, covarianceMatrix[0][0] / det]
];
Insert cell
function MahalanobisDistance(x, y, muX, muY) {
var deltaX = x - muX;
var deltaY = y - muY;
var distanceSquared = (deltaX * inverseMatrix[0][0] + deltaY * inverseMatrix[1][0]) * deltaX +
(deltaX * inverseMatrix[0][1] + deltaY * inverseMatrix[1][1]) * deltaY;

return Math.sqrt(distanceSquared);
}


Insert cell
correlationFactor = 0.6;
Insert cell
function gaussianRandom(mean, stdDev) {
return gaussianRand(mean, stdDev);
}
Insert cell
function gaussianRand(mean, stdDev) {
let rng = seedrandom(seed);
let rng1 = seedrandom(seed2);
let u = 0, v = 0;
while (u === 0) u = Math.random(); // Converting [0,1) to (0,1)
while (v === 0) v = Math.random(); //rng()
let num = Math.sqrt(-2.0 * Math.log(u)) * Math.cos(2.0 * Math.PI * v);

return num * stdDev + mean; // Apply mean and standard deviation
}
Insert cell
math = require('mathjs@9')
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