Public
Edited
Apr 30
Insert cell
Insert cell
viewof select = Inputs.select(
["iris-1@6.csv","Wine.csv"],
{
label: "Select a dataset"
}
)
Insert cell
data = FA(select).csv()
Insert cell
Insert cell
features = data.columns.filter(d=>d!='class')
Insert cell
//escala de banda
anchorpointScale = d3.scalePoint().domain(data.columns).range([0,2*Math.PI])
Insert cell
anchor_points = {
let a =[];
features.forEach( d => a.push(
{
'name': d,
'x':Math.cos(anchorpointScale(d)),
'y':Math.sin(anchorpointScale(d))
}
));
return a
}
Insert cell
//normalize data
new_data = {
const escalas = features.map( d =>d3.extent(data.map(e => (e[d]))))
const values = data.map((d,j) => {
return features.map((u,i)=>
{
d[u] = ((d[u])-escalas[i][0]) / (escalas[i][1]-escalas[i][0])
return d[u]
}
)}
)
return values;
}
Insert cell
margin = {return {top: 50, right: 50, bottom: 50, left: 50};}
Insert cell
space =400
Insert cell
Scala = d3.scaleLinear().domain([-1,1]).range([0,space])
Insert cell
{data.map((d,i)=>{
let fe = features.map(e=>d[e]);
let suma = d3.sum(fe);
let Xs = anchor_points.map(e=>e.x);
let Ys = anchor_points.map(e=>e.y);
d['x'] = d3.sum(Xs.map((e,j) => e * fe[j])) / suma;
d['y'] = d3.sum(Ys.map((e,j) => e * fe[j])) / suma;

})}
Insert cell
Array.from(new Set(data.map(d=>d.class)))
Insert cell
color('Iris-setosa')
Insert cell
color =d3.scaleOrdinal(d3.schemeTableau10)
.domain(Array.from(new Set(new_data.map(d=>d.class))))
Insert cell
{
const r = (space / 2) - 50;
const svg = d3.create('svg')
.attr('width',space)
.attr('height',space);

const g = svg.append('g')
.attr('transform',`translate(${space/2},${space/2})`);

// circulo grande
g.append("circle").
attr('cx',0).
attr('cy',0).
attr("r",r)
.attr('fill','none')
.attr('stroke','gray');

// puntos rojos
g.selectAll(".axis").
data(anchor_points)
.join('circle')
.attr('cx',d=>d.x*r)
.attr('cy',d=>d.y*r)
.attr('r',10).attr('fill','red');

// puntos datos
const datag = svg.append('g').attr('transform',`translate(${space/2},${space/2})`);
datag.selectAll('.dot')
.data(data).
join("circle").
attr('class','dot')
.attr('cx',d=>r*d.x)
.attr('cy',d=>r*d.y)
.attr('r',4)
.attr('fill',d=>color(d.class))
.attr('stroke','white');
return svg.node()
}
Insert cell
{
const r = (space / 2) - 50;
const svg = d3.create('svg')
.attr('width',space)
.attr('height',space);

const g = svg.append('g')
.attr('transform',`translate(${space/2},${space/2})`);

// circulo grande
g.append("circle").
attr('cx',0).
attr('cy',0).
attr("r",r)
.attr('fill','none')
.attr('stroke','gray');

// puntos rojos
g.selectAll(".axis").
data(anchor_points)
.join('circle')
.attr('cx',d=>d.x*r)
.attr('cy',d=>d.y*r)
.attr('r',10).attr('fill','red');

// puntos datos
const datag = svg.append('g').attr('transform',`translate(${space/2},${space/2})`);
datag.selectAll('.dot')
.data(data).
join("circle").
attr('class','dot')
.attr('cx',d=>r*d.x)
.attr('cy',d=>r*d.y)
.attr('r',4)
.attr('fill',d=>color(d.class))
.on("mouseenter", mouseEnter)
.on("mouseleave", mouseLeave)
.attr('stroke','white');


const tooltip = svg.append('g')
.attr('visibility', 'hidden');
const tooltipHeight = 2;
// agregar un rectángulo al tooltip que servirá como fondo
const tooltipRect = tooltip.append('rect')
.attr('fill', 'black')
.attr('rx', 5)
.attr('height', tooltipHeight);
// agregar un texto al tooltip que mostrará la etiqueta
const tooltipText = tooltip.append('text')
.attr('fill', 'red')
.attr('font-family', 'sans-serif')
.attr('font-size', 12)
.attr('y', 6) // margen desde el borde superior del rectángulo
.attr('x', 7) // margen desde el borde izquierdo del rectángulo
.attr('dominant-baseline', 'hanging');

function mouseEnter(event, d) {
console.log(d)
// cambiar de tamaño el círculo
d3.select(this)
.attr('r', 4 * 2);
// actualizar el texto del tooltip y obtener su ancho
tooltipText.text(d.class);
const labelWidth = tooltipText.node().getComputedTextLength();
tooltipRect.attr('width', labelWidth + 6);
// mover el tooltip a la posición del círculo (con un pequeño desplazamiento)
// y hacerlo visible
const xPos = d.x ;
const yPos = d.y ;

tooltip.attr('transform', `translate(${xPos},${yPos})`)
.attr('visibility', 'visible');
}
// manejar el evento cuando el mouse sale de un círculo
function mouseLeave(event, d) {
d3.select(this)
.attr('r', 4)
// ocultar el tooltip
tooltip
.attr('visibility', 'hidden');
}

return svg.node()
}

Insert cell
Insert cell
new_data
Insert cell
anchor_points.map(d=>{
d.xsc = d.x;
d.ysc = d.y;
})
Insert cell
const axes = features.map((col, j) => {
const angle = 2 * Math.PI * j / new_data.length;
return {
name: col,
angle: angle,
x: Math.cos(angle),
y: Math.sin(angle)
};
})

Insert cell
selections
Insert cell
Select a data source…
Type SQL, then Shift-Enter. Ctrl-space for more options.

Insert cell
Insert cell
// Your Code
Insert cell
Insert cell
d3 = require("d3@7")
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