I am starting starting to dive deeper into programming and have started with d3 library. I wanted to run a program that will create a scatterplot and parallel line graphs using a penguin dataset I have but the first line of code itself is showing errors and for the life of me I can not debug the program.
JavaScript file:
//this is where I am getting my syntax error, I can not use a module statement outside of a module
import * as d3 from d3;
// loading the dataset
const dataset = await d3.csv("data/penguins.csv", d3.autoType);
const numerics = ['bill_length_mm', 'bill_depth_mm', 'body_mass_g'];
const categorical = "species";
const color_scale = d3.scaleOrdinal()
.domain(['Adelie', 'Chinstrap', 'Gentoo'])
.range(['#1f77b4', '#ff7f0e', '#2ca02c']);
// Parent HTML element that contains the labels and the plots
const parent = d3.select("div#visualization");
// Sizes of the plots
const width = 800;
const height = 800;
const labelHeight = 25;
createLegend();
createScatterPlotMatrix(width, height);
createHorizontalParallelCoordinates(width, height / 2);
function createLegend() {
const margin = { top: 5, left: 20, bottom: 5, right: 10 };
// Use 'species' attribute for the labels
const labels = ['Adelie', 'Chinstrap', 'Gentoo'];
const svg = parent.append("svg")
.attr("viewBox", [0, 0, width, labelHeight]);
const labelPositions = d3.scaleBand().domain(labels).range([margin.left, width - margin.right]);
const radius = (labelHeight - margin.top - margin.bottom)/2;
const y_circle = margin.top + radius;
const y_label = labelHeight - margin.bottom*1.3;
// Add all circles for the legend
// Use 'color_scale' function for the colors
svg.selectAll("circle")
.data(labels)
.join("circle")
.attr("cx", d => labelPositions(d))
.attr("cy", y_circle)
.attr("r", radius)
.attr("fill", d => color_scale(d)); // Add color to the legend
// Add all text to the legend
svg.selectAll("text")
.data(labels)
.join("text")
.attr("x", d => labelPositions(d) + 2*radius)
.attr("y", y_label)
.text(d => d)
.style("font-size", 2*radius);
}
/**
* Create Scatter Plot Matrix with the given width and height. The contents of each cell
* in this matrix is defined by the scatterPlot() function.
*
* @param {integer} width
* @param {integer} height
*/
function createScatterPlotMatrix(width, height) {
const margin = { top: 10, left: 30, bottom: 30, right: 10 };
const grid_height = height / numerics.length;
const grid_width = width / numerics.length;
const fontSize = 25;
const svg = parent.append("svg")
.attr("viewBox", [0, 0, width, height]);
const scatterplot_matrix = svg.selectAll("g.scatterplot")
.data(d3.cross(numerics, numerics))
.join("g")
.attr("transform", (d, i) => "translate(" + (i % numerics.length) * grid_width + "," + Math.floor(i / numerics.length) * grid_height + ")");
scatterplot_matrix.each(function (d) { // each pair from cross combination
const g = d3.select(this);
// label the same attribute axis
if (d[0] == d[1]) {
const labelXPosition = grid_width/ 2;
const labelYPosition = grid_height/2;
g.append("text")
.text(d[0])
.attr("transform", "translate(" + labelXPosition + "," + labelYPosition + ")")
.style("text-anchor", "middle")
.style("fill", "black")
.style("font-size", fontSize);
} else {
scatterPlot(d[0], d[1], g, grid_width, grid_height, margin);
}
})
}
/**
* @param {string} attributeX
* @param {string} attributeY
* @param {nodeElement} scatterplotCell
* @param {integer} width
* @param {integer} height
* @param {Object} margin
*/
function scatterPlot(attributeX, attributeY, scatterplotCell, width, height, margin) {
// Filter data to remove points with missing values
const filteredData = df1.filter(d => d[attributeX] != null && d[attributeY] != null);
// Get the extent (min and max values) for each attribute
const extentX = d3.extent(filteredData, d => d[attributeX]);
const extentY = d3.extent(filteredData, d => d[attributeY]);
// Set the input domain of the scales to the extent of the data
const x_scale = d3.scaleLinear().domain(extentX).range([margin.left, width - margin.right]);
const y_scale = d3.scaleLinear().domain(extentY).range([height - margin.bottom, margin.top]);
// Create axes
const axisX = d3.axisBottom(x_scale).ticks(4);
scatterplotCell
.append('g')
.attr('transform', `translate(0, ${height - margin.bottom})`)
.call(axisX);
const axisY = d3.axisLeft(y_scale).ticks(4);
scatterplotCell
.append('g')
.attr('transform', `translate(${margin.left}, 0)`)
.call(axisY);
// drawing the points of the scatterplot
scatterplotCell.selectAll("circle")
.data(filteredData)
.join("circle")
.attr("cx", d => x_scale(d[attributeX]))
.attr("cy", d => y_scale(d[attributeY]))
.attr("r", 3) // Set the radius of the points
.attr("fill", d => color_scale(d[categorical])); // Color the points according to the color scheme
}
/**
* @param {integer} width
* @param {integer} height
*/
function createHorizontalParallelCoordinates(width, height) {
const margin = { top: 10, left: 30, bottom: 30, right: 10 };
const svg = parent.append("svg")
.attr("viewBox", [0, 0, width, height]);
// Define the dimensions of the plot area
const plotWidth = width - margin.left - margin.right;
const plotHeight = height - margin.top - margin.bottom;
// Define the attributes to be plotted
const attributes = ["bill_length_mm", "bill_depth_mm", "flipper_length_mm", "body_mass_g"];
// Filter out rows with missing data
const filteredData = df1.filter(d => !attributes.some(attr => d[attr] == null));
// Define a scale for each attribute
const scales = new Map(attributes.map(attr => [
attr,
d3.scaleLinear()
.domain(d3.extent(filteredData, d => d[attr]))
.range([margin.left, plotWidth + margin.left])
]));
// defining a line generator
const line = d3.line()
.x((d, i) => scales.get(attributes[i])(d))
.y((_, i) => i * plotHeight / (attributes.length - 1) + margin.top);
// drawing the lines
svg.selectAll("path")
.data(filteredData)
.join("path")
.attr("d", d => line(attributes.map(attr => d[attr])))
.attr("fill", "none")
.attr("stroke", d => color_scale(d["species"]))
.attr("stroke-width", 1.5);
// drawing the axes
attributes.forEach((attr, i) => {
const y = i * plotHeight / (attributes.length - 1) + margin.top;
svg.append("g")
.attr("transform", `translate(0,${y})`)
.call(d3.axisTop(scales.get(attr)));
svg.append("text")
.attr("transform", `translate(${margin.left - 10},${y})`)
.attr("text-anchor", "end")
.attr("dominant-baseline", "middle")
.text(attr);
});
}
JSON file:
{
"name": "a2",
"version": "1.0.0",
"description": "",
"main": "index_edited.js",
"type": "module",
"scripts": {
"test": "echo "Error: no test specified" && exit 1",
"start": "snowpack dev"
},
"author": "",
"license": "ISC",
"dependencies": {
"d3": "^7.9.0",
"snowpack": "^3.8.8",
"zero-md": "^2.5.4"
}
}
CSS file:
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen,
Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
font-size: 1.2rem;
font-weight: 400;
}
main {
max-width: 1000px;
margin: 0 auto;
}
a {
color: #512da8;
text-decoration: none;
}
#codearea {
font-family: monospace;
}
a:hover {
text-decoration: underline;
}
a:visited {
color: #311b92;
}
h1 {
font-size: 3rem;
font-weight: 400;
margin: 3rem 0 1rem 0;
}
h2 {
font-size: 2.5rem;
font-weight: 400;
margin: 2rem 0 1rem 0;
}
h3 {
font-size: 2rem;
font-weight: 400;
margin: 1rem 0 1rem 0;
}
table {
width: 100%;
border: none;
}
th,
td {
border-bottom: 1px solid #ddd;
padding: 0 5px;
}
th {
text-align: left;
text-transform: uppercase;
font-weight: 500;
}
td>span {
padding: 1px 5px;
margin: 0px 10px;
}
span.tag {
display: inline;
padding: 6px 10px;
border-radius: 5px;
background-color: black;
color: white;
justify-content: center;
}
code {
font-family: monospace;
font-size: 1.1rem;
background-color: #b0bec5;
color: black;
border-radius: 4px;
padding: 0.1rem 0.2rem;
}
div.task {
padding: 0.1rem 1.2rem;
margin: 2rem 0;
border-radius: 6px;
background-color: #cfd8dc;
}
div.optional {
padding: 0.1rem 1.2rem;
margin: 2rem 0;
border-radius: 6px;
background-color: rgb(212, 200, 254);
}
span.monospace {
font-family: monospace;
}
.responsive {
width: 100%;
height: auto;
}
I wanted to run the program on my browser to take a look at the scatterplot and parallel line charts but my code keep running into issues. I tried changing the syntax, added filter functions because the dataset has missing data items even tried altering the actual dataset. I created a HTML file uses <script type=”module”> and also tried to serve my file locally on a python server but I could not find my file on the local server but none of that has worked as my code is still stuck at debugging on the first line. I would really appreciate someone’s insight.
bad_with_usernames is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.