Public
Edited
Feb 3, 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
Plot.plot({
padding: 0,
color: {
type: "Sequential",
scheme: "RdPu",
legend: true,
range: [0, 0.7]
},
marks: [
Plot.cell(corr_data, {
x: (d) => d.x,
y: (d) => d.y,
fill: "value",
inset: 0.5
}),
Plot.text(corr_data, {
x: (d) => d.x,
y: (d) => d.y,
text: (d) => d.value?.toFixed(3), fill: "black", title: "title"
})
]
})

Insert cell
console.log(typeof reducedDataformain[0].IMDB_Rating);
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
import {Swatches} from "@d3/color-legend"
Insert cell
viewof radius = Inputs.range([0, 936000000], {step: 18740000, value: 8, label: "radius"})
Insert cell
Plot.plot({
width: 928,
height: 928,
// inset: 10,
marginLeft: 90,
x: { type: "linear" },
y: { type: "linear" },
color: {scheme: "BuPu"},
marks: [
Plot.hexagon(
data,
Plot.hexbin(
{fill: "count"},
{
// binWidth: 12,
x: "Meta_score",
y: "Gross",
fill: "#ccc",
stroke: "#000",
strokeWidth: 0.75
}
)
)
]
})
Insert cell
d3formain = require("d3@7", "d3-hexbin@0.2")
Insert cell
reducedDataformain = dataformain.map(movie => ({
Gross: movie.Gross,
i_general: movie.i_general,
}));
Insert cell
dataforrr = {
const categories = {
"No inclusivo": ["pants-fire", "false", "mostly-false"],
"Moderadamente inclusivo": ["barely-true"],
"Muy inclusivo": ["half-true", "mostly-true", "true"]
};

const data = d3.csvParse(await FileAttachment("df_merged.csv").text(), ({ speaker: name, ruling: category, count: value }) => {
for (const [inclusiveCategory, inclusiveValues] of Object.entries(categories)) {
if (inclusiveValues.includes(category)) {
return { name, category: inclusiveCategory, value: +value };
}
}
return null;
});

// Normalize absolute values to percentage.
d3.rollup(data, group => {
const sum = d3.sum(group, d => d.value);
for (const d of group) d.value /= sum;
}, d => d.name);

return Object.assign(data, {
negative: "No inclusivo",
positive: "Muy inclusivo",
negatives: ["No inclusivo", "Moderadamente inclusivo"],
positives: ["Muy inclusivo"]
});
}

Insert cell
chart = {

// Assign a valence to each category.
const categories = new Map([].concat(
newArrayConCategorias.map(d => [d.name, d.category])
));

// Compute the bias = sum of negative values for each candidate.
const bias = d3.sort(
d3.rollup(newArrayConCategorias, v => d3.sum(v, d => d.score * (d.category === "No inclusivo" ? -1 : 1)), d => d.name),
([, a]) => a
);

// Specify the chart’s dimensions, with a space of height 33px for each candidate.
const width = 928;
const marginTop = 40;
const marginRight = 30;
const marginBottom = 0;
const marginLeft = 80;
const height = bias.length * 33 + marginTop + marginBottom;

// Prepare the stack; the values are stacked from the inside out, starting with more
// moderate values (“mostly false”, “half true”), and ending with the extreme values.
const series = d3.stack()
.keys(categories.keys())
.value(([, value], name) => categories.get(name) === "No inclusivo" ? -1 * value : value)
.offset(d3.stackOffsetDiverging)
(d3.rollup(newArrayConCategorias, data => d3.rollup(data, ([d]) => d.score, d => d.name), d => d.name));

// Construct the scales.
const x = d3.scaleLinear()
.domain(d3.extent(series.flat(2)))
.rangeRound([marginLeft, width - marginRight])

const y = d3.scaleBand()
.domain(bias.map(([name]) => name))
.rangeRound([marginTop, height - marginBottom])
.padding(2 / 33)

const color = d3.scaleOrdinal()
.domain(categories.keys())
.range(d3.schemeSpectral[categories.size])

// A function to format a percentage, used both on the axis and in the tooltips.
const formatValue = ((format) => (x) => format(Math.abs(x)))(d3.format(".0%"));

// Create the SVG container.
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height])
.attr("style", "max-width: 100%; height: auto; font: 10px sans-serif;");

// Append a rect for each value, with a tooltip.
svg.append("g")
.selectAll("g")
.data(series)
.join("g")
.attr("fill", d => color(d.key))
.selectAll("rect")
.data(d => d.map(v => Object.assign(v, {key: d.key})))
.join("rect")
.attr("x", d => x(d[0]))
.attr("y", ({data: [name]}) => y(name))
.attr("width", d => x(d[1]) - x(d[0]))
.attr("height", y.bandwidth())
.append("title")
.text(({key, data: [name, value]}) => `${name}
${formatValue(value.get(key))} ${key}`);

// Create the axes.
svg.append("g")
.attr("transform", `translate(0,${marginTop})`)
.call(d3.axisTop(x)
.ticks(width / 80)
.tickFormat(formatValue)
.tickSizeOuter(0))
.call(g => g.select(".domain").remove())
.call(g => g.append("text")
.attr("x", x(0) + 20)
.attr("y", -24)
.attr("fill", "currentColor")
.attr("text-anchor", "start")
.text("No inclusivo"))
.call(g => g.append("text")
.attr("x", x(0) - 20)
.attr("y", -24)
.attr("fill", "currentColor")
.attr("text-anchor", "end")
.text("Inclusivo"));

svg.append("g")
.call(d3.axisLeft(y).tickSizeOuter(0))
.call(g => g.selectAll(".tick").data(bias).attr("transform", ([name, min]) => `translate(${x(min)},${y(name) + y.bandwidth() / 2})`))
.call(g => g.select(".domain").attr("transform", `translate(${x(0)},0)`));

// Return the color scale as a property of the node, for the legend.
return Object.assign(svg.node(), {scales: {color}});
}

Insert cell
newArrayConCategorias = newArray.map(entry => ({
name: entry.Genre,
score: entry.Meta_score,
category: aproximarCategoria(parseFloat(entry.i_general))
}));
Insert cell
function aproximarCategoria(valor) {
if (valor < 2) {
return "No inclusivo";
} else if (valor < 4) {
return "Poco inclusivo";
} else if (valor < 6) {
return "Moderadamente inclusivo";
} else if (valor < 8) {
return "Muy inclusivo";
} else {
return "Extremadamente inclusivo";
}
}

Insert cell
Insert cell
dataformain = FileAttachment("df_merged.csv").csv()
Insert cell
Insert cell
Insert cell
Insert cell
data2 = FileAttachment("dsV0 (5)@1.csv").csv()
Insert cell
data2.forEach(item => {
item.Gross = Number(item.Gross);
item.Gross = Number(item.IMDB_Rating);
item.Gross = Number(item.Meta_score);
});
Insert cell
console.log(typeof data[0].IMDB_Rating);
Insert cell
d3 = require("d3@6")
Insert cell
Insert cell
plotGrossIndex = {
return Plot.plot({
title: "Inclusivity vs Gross",
style: "overflow: visible;",
width: 1100,
height: 700,
y: {
grid: true,
domain: [0, 1000000000], // Define el rango mínimo y máximo
tickFormat: d => `${d / 1000}K` // Formatea los ticks para mostrarlos en miles
},
x: {
domain: [0, 10], // Asumiendo que i_general varía entre 0 y 10
},
symbol: { legend: true }, // Habilita la leyenda para los símbolos, si es aplicable
color: {
legend: true, // Habilita la leyenda para los colores, mostrando los géneros
},
marks: [
Plot.ruleY([0]),
Plot.dot(data, {x: "i_general", y: "Gross", stroke: "Genre"}) // Usa las marcas directamente sin .plot()
]
});
}

Insert cell
plotIMDBIndex = {
return Plot.plot({
title: "Inclusivity vs IMDB Rating",
style: "overflow: visible;",
width: 1100,
height: 700,
y: {
grid: true,
domain: [7.5, 10], // Define el rango mínimo y máximo
},
x: {
domain: [0, 10], // Asumiendo que i_general varía entre 0 y 10
},
symbol: { legend: true }, // Habilita la leyenda para los símbolos, si es aplicable
color: {
legend: true, // Habilita la leyenda para los colores, mostrando los géneros
},
marks: [
Plot.ruleY([0]),
Plot.dot(data, {x: "i_general", y: "IMDB_Rating", stroke: "Genre"}) // Usa las marcas directamente sin .plot()
]
});
}
Insert cell
Plot.plot({
label: null,
marginLeft: 60,
width:1200,
height: 600,
grid: true,
r: {range: [0, 40]},
marks: [
Plot.dot(medianGrossPerGenreInclusivity , Plot.group({r: "median_gross"}, {x: "Genre", y: "i_general_rang", stroke: "red"}))
]
})
Insert cell
inclusivity_types = ["","",""]
Insert cell
viewof inclusivity_type = Inputs.select([""].concat(stateNames), {label: "Home state"})
Insert cell
Sscc = {

const sortedDomain = medianGrossPerGenreInclusivity
.map(d => d.i_general_rang) // Extraemos los rangos
.filter((value, index, self) => self.indexOf(value) === index) // Eliminamos duplicados
.sort((a, b) => b.localeCompare(a)); // Ordenamos de manera descendente

const radius = d3.scaleSqrt().domain(d3.extent(medianGrossPerGenreInclusivity, d=> d.median_gross)).range([0,100])
function obtenirRadi(gross)
{
if(gross < 20000000) return 10;
else if(gross < 50000000) return 20;
else if(gross < 72738914.75) return 30;
else return 50;
}


const plot = Plot.plot({
title: "Money made by movie category per inclusivity range",
marginBottom:50,
marginTop:50,
width: 1200,
height: 900,
grid: true,
x: { label: "Movie Genre" },
y: { label: "Inclusivity Index",
domain: sortedDomain,
padding: 0.1 },
r: { range:[10,50]},
color: { legend: true },
marks: [
Plot.dot(medianGrossPerGenreInclusivity, {
x: "Genre",
y: "i_general_rang",
r: "median_gross", // Usa la función para el radio
fill: "#F1948A",

}),
Plot.text(medianGrossPerGenreInclusivity, {
x: "Genre",
y: "i_general_rang",
text: d => `$${d.median_gross}`, // Formatea el valor de median_gross para mostrarlo como texto
fontSize: 20,
})
]
});

return plot;
}
Insert cell
medianGrossValues = medianGrossPerGenreInclusivity.map(d => d.median_gross).sort((a, b) => a - b);
Insert cell

function calculatePercentile(arr, percentile) {
const index = percentile / 100 * (arr.length - 1);
if (Math.floor(index) === index) {
return arr[index];
} else {
const lower = arr[Math.floor(index)];
const upper = arr[Math.ceil(index)];
return lower + (upper - lower) * (index - Math.floor(index));
}
}


Insert cell
q1 = calculatePercentile(medianGrossValues, 25);
Insert cell
q2 = calculatePercentile(medianGrossValues, 50); // Mediana

Insert cell
q3 = calculatePercentile(medianGrossValues, 75);
Insert cell
maxGross = medianGrossValues[medianGrossValues.length - 1];
Insert cell
medianGrossPerGenreInclusivity = {
// Asumiendo que 'data' es tu array de objetos cargado en Observable

// Definimos los rangos para i_general
const ranges = [0, 2, 4, 6, 8, 10];
const rangeLabels = ['0-2', '2-4', '4-6', '6-8', '8-10'];

// Transformamos los datos
const transformedData = [];

data.forEach(d => {
// Encuentra el rango para el valor i_general actual
const rangeIndex = ranges.findIndex((value, index, array) => d.i_general >= value && d.i_general < array[index + 1]);
const rangeLabel = rangeLabels[rangeIndex] || rangeLabels[rangeLabels.length - 1]; // Asegura que los valores en el límite superior caigan en el último rango

// Añade el objeto transformado al array
transformedData.push({ ...d, i_general_rang: rangeLabel });
});

// Ahora agrupamos por 'Genre' y 'i_general_rang' y calculamos el gross mediano
const output = Array.from(d3.group(transformedData, d => d.Genre, d => d.i_general_rang), ([Genre, genreValues]) => {
return Array.from(genreValues, ([i_general_rang, values]) => ({
Genre,
i_general_rang,
median_gross: d3.median(values, d => Number(d.Gross))
}));
}).flat();

return output;

}

Insert cell
Insert cell
grossValues = data.map(item => item.Gross);
Insert cell
indexs = ["i_general", "i_etnia"]
Insert cell
height = 500
Insert cell
y_scale = d3
.scaleBand()
.domain(d3.range(5))
.range([height, 0])
Insert cell
x_scale = d3
.scaleBand()
.domain(d3.range(1))
.range([0, width - margin.right])
Insert cell
margin = ({ top: 50, left: 40, right: 40, bottom: 50 })
Insert cell
color_scale = d3.scaleLinear()
.domain([-0.008363, 0.041349])
.range(['#fff', '#A3320B'])
Insert cell
corr_data = {
const corr_data = [0.041349, 0.036603, -0.008363, 0.033154, 0.010855]
const indexs = ["i_general", "i_etnia", "i_genere", "i_lgtbq", "i_disability"]
const correlationArray = [];

for (let i = 0; i < corr_data.length; i++) {
const variable = indexs[i];
const valor = corr_data[i];
const correlationObject = {
y: variable,
x: "Gross",
value: valor
};
correlationArray.push(correlationObject);
}
return correlationArray
}
Insert cell
bb2 = {

const sortedDomain = medianGrossPerGenreInclusivity
.map(d => d.i_general_rang) // Extraemos los rangos
.filter((value, index, self) => self.indexOf(value) === index) // Eliminamos duplicados
.sort((a, b) => b.localeCompare(a)); // Ordenamos de manera descendente


const medianGrossValues = medianGrossPerGenreInclusivity.map(d => d.median_gross);
const minGross = Math.min(...medianGrossValues);
const maxGross = Math.max(...medianGrossValues);

// Define una escala para el radio basada en 'median_gross'
// Esta es una función simple de ejemplo; ajusta según tus necesidades
const scaleRadius = d3.scaleSqrt()
.domain([minGross, maxGross]) // Usa el mínimo y máximo de 'median_gross'
.range([10, 200]); // Rango de radios, de más pequeño a más grande


const calculateRadius = (gross) => {
const numericGross = Number(gross);
return parseInt(gross);
};

const plot = Plot.plot({
label: null,
marginLeft: 60,
width: 1200,
height: 600,
grid: true,
y: {
domain: sortedDomain,
// padding: 0.1
},
color: {
legend: true
},
marks: [
// Aquí, asegúrate de que 'r' (radio) se define correctamente. Si quieres un tamaño fijo, simplemente pasa un valor numérico.
Plot.dot(medianGrossPerGenreInclusivity, {x: "Genre", y: "i_general_rang", fill: "red",r: d => d.median_gross/1000 })
]
});

return plot;
}
Insert cell
calculateRadius = (gross) => {
const numericGross = Number(gross);
return numericGross / 50000;
}
Insert cell
calculateRadius(medianGrossPerGenreInclusivity[9].median_gross)
Insert cell
console.log( medianGrossPerGenreInclusivity[9
].median_gross);
Insert cell
Plot.plot({
marks: [
Plot.ruleY([0]),
Plot.lineY(dataAux.filter(item => item.genre === "Drama"), {x: "i_general", y: "median_gross"})
]
})
Insert cell
dataAux = {
const reducedData = data.reduce((acc, current) => {
const iGeneral = current.i_general;
const gross = Number(current.Gross);
// Agrupar por 'i_general'
if (!acc.has(iGeneral)) {
acc.set(iGeneral, {
i_general: iGeneral,
grossValues: [gross],
genre: current.Genre
});
} else {
acc.get(iGeneral).grossValues.push(gross);
}
return acc;
}, new Map());
// Calcular la mediana y crear un nuevo array con la estructura deseada
const reducedDataArray = Array.from(reducedData.values()).map(entry => {
const medianGross = d3.median(entry.grossValues);
return {
i_general: entry.i_general,
median_gross: medianGross,
genre: entry.genre
};
});
// Log del resultado
return reducedDataArray;
}
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