
lOMoARcPSD| 23136115
DSDV Mid Note
1.1. (35pts) Analyze a visualizaon. Analyze and evaluate the visualizaon in Figure 1 by answering
the following quesons: a. (5pts) What is the goal of the visualizaon?
b. (10pts) What is its data? types of data?
c. (10pts) How did the author use marks and channels to encode the data?
d. (10pts) The design is not good, redesign it.
(STUDENT ANSWER 1 35/35)
A, The goal of the visualizaon is to show the probability of near interacon between paents of
COVID-19 and the stewardess
B, +, The data is the gures of the probability (%%), which is integer and is shown in terms of color
scale.
+, Type of data: aributes
C, The author has transmied the original data (which is integer) into the darkness of color shown in
the visualizaon That means the low gures will be represented by light color ( this case is light blue.
Medium gures are shown in white and the highest are shown in the darkest color ( this case is dark
pink..). D, The color scale is not good This is how I redesign it. The smallest percentage should be
shown in the lightest color white. The bigger the percentage is the ‘more blue’ the color gets. The
color connues to be darker and darker unl it reaches ‘dark blue' at the end of the scale.
(STUDENT ANSWER 2 35/35)
a) This visualizaon is to show the rate of ight aendants and have close-rangecontact with a covid
paent.
b) This is a type of rao, where the auther get the rate of close contact between a ight aendants
and covid paents on a plane.
c) In this visualizaon, the author used squares as a mark on a background of real seats on a plane.
For the channels, author used hue and saturaon shown below: dark blue - > light blue -> white light
-> pink dark pink
d) As using 2 dierent hues, this visualizaon is a lile bit harder to read by using only 1 hue (which
I recommend blue as it's cooler and easier to get the change) with a wider range of saturaon, this
visualizaon may be beer to get the in sight.

lOMoARcPSD| 23136115
(GPT ANSWER)
a. Goal of the Visualizaon: The goal of the visualizaon is to represent the probability of infecon when
individuals are in close range with a sick person. This is indicated by the color gradient on an airplane
seang chart.
b. Data and Types of Data: The data consists of the probability percentages of passengers geng infected
when they are near a sick person. The types of data are categorical (seat labels and indicaons for sick
person and ight aendant) and quantave (probability percentages).
c. Use of Marks and Channels: The author used color as a channel to encode the data, with dierent
shades represenng dierent probabilies of infecon. Darker colors indicate higher probabilies.
Marks are used to represent seats, with special icons indicang the seat occupied by a sick person and
ight aendants.
d. Redesign: To redesign it, I would suggest the following improvements: - Use clearer labels for
rows and columns.
- Make sure that the color gradient is easily disnguishable for all viewers including those with color
vision deciencies.
- Provide clear legends that explain what each mark and color represents.
- Instead of using color alone to represent the probability of infecon, consider using a combinaon
of color and size. For example, seats with a higher probability of infecon could be represented
by larger, darker circles, while seats with a lower probability could be represented by smaller,
lighter circles. This would make the visualizaon more accessible to a wider audience, including
those with color vision deciencies.
- Consider adding interacve elements to the visualizaon. For example, when a user hovers over
a seat, a toolp could appear showing the exact probability of infecon for that seat. This would
provide more precise informaon to the user.
- Finally, ensure that the visualizaon is responsive so that it can be viewed on devices of dierent
sizes. This could be achieved by using a exible layout and scalable vector graphics (SVGs).
1.2. (20pts) Redesign. COVID-I9 is known to be very infecous in closed area like in an aircra cabin.
The Figure 2 shows a case of COVID-19 spreading in an aircra. However, the visualizaon is not
compable with gray-scale prinng.
Your task is to
a. Redesign the visualizaon in such a way that could show dierent sroups in a gray-scale prinng.
b. Jus your design: the reason for your selecon of marks, channels and others

lOMoARcPSD| 23136115
(STUDENT ANSWER 1 20/20)
a) Primary group and Secondary group have dierent shapes.
Ex: Primary. (infecous):
Secondary (ight associated):
The gray-scale channel remains the same in each group (lighter).
Empty seat will remove gray-scale channel, and add them “-" sign in the Seat: becomes
b) Since the design in gray scale will only have 1 color range from white to implythe black-grey-white
to imply the possibility/infecon, changeing the shape for each group to is a good opon. The idea
of adding a symbol inside of seat is one good alternave, but it can not be seen with the gray-scale
aribute, so we can't use this for the "Primary " and "secondary" group, but can be used for "empty
seat" group, which has been removed the gray-scale channel.
(STUDENT ANSWER 2 18/20)
For gray-scale channel, the best way to visualize is using shape
Rectangle
Channel: Posion, Dierent shape
: Primary (infecous of ight)
: Primary (non-infecous of ight)
: Secondary (ight associated)
: Secondary (possible ight associated)
: Empty seat
: Negave PCR
(GPT ANSWER)
Redesigned Visualizaon for Gray-Scale Prinng:
Economy Class Cabin | Mid Cabin | A Cabin
-------------------------------------------
██ Primary (infecous on ight)
░░ Primary (non-infecous on ight)
▓▓ Secondary (ight associated)
▒▒ Secondary (possible ight associated)
Empty seat
XX Negave PCR
Juscaon for Design:
Marks and Channels:

lOMoARcPSD| 23136115
Primary (infecous on ight): Used a dark solid ll (██) to indicate high importance and immediate
aenon.
Primary (non-infecous on ight): Chose a light paern (░░) to dierenate from infecous but sll signify
potenal risk.
Secondary (ight associated): A medium dark paern (▓▓) represents conrmed secondary cases, disnct
from primary cases.
Secondary (possible ight associated): A lighter paern (▒▒) suggests uncertainty in the associaon.
Empty seat: Le blank to show the absence of a passenger.
Negave PCR: An ‘X’ mark (XX) is universally recognized and indicates a negave test result.
Reasoning:
The use of dierent shading paerns allows for clear dierenaon between groups without relying on
color.
Paerns are chosen to be disnct enough to avoid confusion when printed in grayscale.
The symbols are simple and can be easily understood without complex legends or explanaons.
2. (35pts) Design a visualizaon to show students in a class.
Each student has a GPA (10pts), a major (10pts), a group’s ID (10pts), and a seat number.
Show all aributes of each student and show links between all members of a group in the classroom
arrangement given in Figure 2.

lOMoARcPSD| 23136115
(STUDENT ANSWER 1 35/35)
I will use color, posion and interacve visualizaon for this dataset +, 6 colors are used
to represent 6 group ID
Group ID
color
1
red
2
orange
3
green
4
blue
5
yellow
6
purple
+, 3 types of shape are used to represent 3 major
Major
Shape
IT
rectangle

lOMoARcPSD| 23136115
CS
triagle
DS
circle
+, The shapes are placed exactly at the seat of student
+, Finally, the size of the shape will represent the GPA of each student. The smallest size stands for 60
and the biggest will be 100
+, Any me the printer touch the shape (rectangle, triangle cude), the original gures will be shower
o. They will consist of:
-> Group ID
-> Major (interacve visualizaon)
-> GPA
(STUDENT ANSWER 2 34/35)
For showing the student's data in a class, we will use the posion in the class for the "Seat" column, which
is shown in Figure 2. Therefore, we only need to deal with 3 columns " GPA", "Major" and "GroupID."
- The most important column to visualize is Major in my opinion, so I will deal with iirst.
- For “Major”, I will use dierent hues for dierent major. For example, red for "IT", blue for "CS",
and green for "DS" (all of them are in the same level of saturaon, but dierent in hue)
- For "GPA", I will put this column to the second level of priority. I will use the saturaon level to
disnguish between students with high GPA with students with low GPA.
- Finally, a number in the middle of the box will show the group that this student belongs to. In this
case, in order to keep the posion number, I will move them to the top of each box.
Conclusion: by using 3 channels: posion, hue, saturaon and a number, I will visualize the given data into
a class diagram
* For the links between members of a group: all members of a group will have the same number in
the middle of the box as shown in the rst part, which can be easily disnguished.
(GPT ANSWER)
I will use color, posion and interacve visualizaon for this dataset
+, 6 colors are used to represent 5 range of GPAs
GPA
color
50-59
red
60-69
orange
70-79
yellow
80-89
green
90-100
blue
+, 3 types of shape are used to represent 3 major
Major
Shape
IT
Triangle
CS
Circle
DS
Square
+, The shapes are placed exactly at the seat of student
+, Finally, for the Group ID, we can number 1 to 6 corresponding to the student’s
Group ID by pung the number at the center of the shape

lOMoARcPSD| 23136115
3. (30pts) Create an HTML web page with the tle “Midterm”. a. Get data from
hps://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/
csse_covid_19_me_series/me_series_covid19_conrmed_global.csv (in your code, you can refer to this source as
“covid_global.csv”)
In the dataset,
- “Province/State” and “Country/Region” are used as the key for each row. - The date is in US-
format
Figure 3 is a sample from the dataset.
Figure 3 - A sample from the dataset
b. (5pts) Write code to draw a horizontal bar chart to show COVID conrmed cases over the world on “04/04/2022”.
The chart must
R1. (5pts) have a xed size (use scale to convert data)
R2. (5pts) have an axis with a tle and cks
R3. (5pts) use Province/State and Country/Region as key/label for a row
R4. (5pts) show only non-zero rows (Use lter funcon of arrays in javascript) R5. (5pts) show
value in the bar Hint:
- Use rowConverter
- Use parseInt, parseFloat to convert strings to numbers - Filter funcon of arrays in javascript.
newDataSet = dataset.lter(d => d[“04/04/2022”] > 0);
(ANSWER)
<!DOCTYPE html>
<html lang="en"> <head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, inial-scale=1.0"> <tle>Midterm</tle>
<script src="hps://d3js.org/d3.v7.min.js"></script> </head>
<body>
<div id="chart"></div>
<script>
// Funcon to convert CSV row to desired data format
funcon rowConverter(row) {

lOMoARcPSD| 23136115
return {
place: row['Province/State'] + ', ' + row['Country/Region'],
cases: +row['4/4/22']
};
}
// Funcon to draw the chart using D3
funcon drawChart(data) {
// Dimensions and margins for the chart const svgWidth = 1500;
const svgHeight = 10000;
const margin = { top: 10, right: 20, boom: 50, le: 300 };
// Create SVG element
const svg = d3.select("#chart")
.append("svg")
.ar("width", svgWidth)
.ar("height", svgHeight)
// Dene x and y scales
const xScale = d3.scaleLinear()
.domain([0, d3.max(data, d => d.cases)])
.range([margin.le, svgWidth - margin.right - 50]);
const yScale = d3.scaleBand()
.domain(data.map(d => d.place))
.range([margin.top, svgHeight - margin.boom])
.padding(0.1);
// Color scale for the bars
const colorScale = d3.scaleSequenal()
.domain([0, d3.max(data, d => d.cases)])
.interpolator(d3.interpolateYlOrRd);
// Dene x and y axes
const xAxis = d3.axisBoom(xScale).ck(5); const yAxis =
d3.axisLe(yScale).ck(5);
// Append x axis to SVG
svg.append("g")
.ar("transform", `translate(5, ${svgHeight - margin.boom + 5})`)
.call(xAxis)
.append("text")
.ar("x", svgWidth - margin.right - 50) .ar("y", - 30)

lOMoARcPSD| 23136115
.ar("font-size", "30px")
.ar("font-weight", "bold") .text("Cases")
.ar("ll", "black");
// Append y axis to SVG
svg.append("g")
.ar("transform", `translate(${margin.le}, 0)`) .call(yAxis)
.append("text")
.ar("x", - 100)
.ar("y", 100)
.ar("font-size", "30px")
.ar("font-weight", "bold") .text("Place")
.ar("ll", "black");
// Draw bars on the chart
svg.selectAll("rect") .data(data)
.enter()
.append("rect")
.ar("x", margin.le + 5)
.ar("y", (d, i) => yScale(d.place))
.ar("width", 0) .transion()
.duraon(700)
.ar("width", (d) => xScale(d.cases) - margin.le)
.ar("height", yScale.bandwidth())
.ar("ll", (d) => colorScale(d.cases));
// Add labels to the bars
svg.selectAll(".label") .data(data)
.enter()
.append("text")
.ar("x", (d) => xScale(d.cases) + 10)
.ar("y", (d, i) => yScale(d.place) + yScale.bandwidth() / 2 + 5)
.ar("font-family", "sans-serif") .ar("font-size", "11px")
.ar("ll", "white") .text((d) => d.cases)
.transion()
.delay(500)
.ar("ll", "black");

lOMoARcPSD| 23136115
}
// Load data from CSV and draw the chart
d3.csv("me_series_covid19_conrmed_global.csv", rowConverter) .then(data => {
// Filter out rows with zero cases
data = data.lter(row => row.cases !== 0);
drawChart(data);
});
</script> </body>
</html>

lOMoARcPSD| 23136115
Lab 4
<!DOCTYPE html>
<html lang="en"> <head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, inial-scale=1.0"> <tle>Lab 4</tle>
<script src="hps://d3js.org/d3.v7.min.js"></script> </head>
<body>
<h1>Lab 4 –D3.js - Transion, Update, Enter & Exit</h1> <h2>Data science and data
visualizaon</h2>
<p>Truong Tri Dung</p>
<p>ITCSIU21126</p>
<p>This is all my own work. I did not copy the code from any other source.</p>
<buon id="addBuon">Add New Province</buon>
<buon id="removeBuon">Remove Last Province</buon>
<select id="sortSelect">
<opon value="ma">MA</opon>
<opon value="area">Area</opon>
<opon value="populaon">Populaon</opon> <opon
value="density">Density</opon>
<opon value="grdp" selected>GRDP</opon>
<opon value="grdp_usd">GRDP (USD)</opon>
</select>
<div id="chart"></div>
<script>
var sortValue = "grdp"; //Load data
d3.csv("hps://tungth.github.io/data/vn-provinces-data.csv", rowConverter) .then(data => {
const dataset = data.slice(0, 20);
dataset.sort((a, b) => d3.descending(a[sortValue], b[sortValue])); drawChart(dataset);
//Add province buon
const addBuon = document.getElementById('addBuon');
let index = 20;
addBuon.addEventListener('click', () => {
if (index < data.length) {
dataset.push(data[index]);
dataset.sort((a, b) => d3.descending(a[sortValue], b[sortValue]));
d3.select("svg").remove();
drawChart(dataset);

lOMoARcPSD| 23136115
index++;
}
});
//Remove lát province buon
const removeBuon = document.getElementById('removeBuon');
removeBuon.addEventListener('click', () => { dataset.pop();
d3.select("svg").remove();
drawChart(dataset);
});
d3.select("#sortSelect").on("change", funcon() {
sortValue = d3.select(this).property("value");
dataset.sort((a, b) => d3.descending(a[sortValue], b[sortValue]));
d3.select("svg").remove();
drawChart(dataset);
});
});
// Converts each row of the CSV data into an object with specic properes funcon rowConverter(row) {
// Converts strings to numbers where necessary return {
ma: +row.ma,
province: row.province,
area: +row.area,
populaon: +row.populaon, density: +row.density,
grdp: parseFloat(row['GRDP-VND'].replace(',', '.')),
grdp_usd: parseFloat(row['GRDP-USD'].replace(',', '.'))
};
}
// Draws the chart based on the provided data
funcon drawChart(data) {
// Denes dimensions and margins for the SVG element const svgWidth = 1000;
const svgHeight = 650;
const margin = { top: 10, right: 20, boom: 50, le: 70 };
// Selects the chart div and appends an SVG element to it const svg = d3.select("#chart")
.append("svg")

lOMoARcPSD| 23136115
.ar("width", svgWidth)
.ar("height", svgHeight)
// Denes scales for x and y axes
const xScale = d3.scaleLinear()
.domain([0, d3.max(data, d => d[sortValue])])
.range([margin.le, svgWidth - margin.right - 50]);
const yScale = d3.scaleBand()
.domain(data.map(d => d[sortValue]))
.range([margin.top, svgHeight - margin.boom])
.padding(0.1);
// Denes color scale based on data values const colorScale =
d3.scaleSequenal()
.domain([0, d3.max(data, d => d[sortValue])])
.interpolator(d3.interpolateYlOrRd);
// Denes x and y axes
const xAxis = d3.axisBoom(xScale);
const yAxis = d3.axisLe(yScale).ckFormat(d3.format(".2f"));
// Appends x-axis to the SVG and adds label
svg.append("g")
.ar("transform", `translate(5, ${svgHeight - margin.boom + 5})`)
.call(xAxis)
.append("text")
.ar("x", svgWidth / 2) .ar("y", 40)
.ar("font-weight", "bold") .text(
sortValue == "grdp" ? "GRDP in VND" :
sortValue == "grdp_usd" ? "GRDP in USD" :
sortValue == "populaon" ? "Populaon" :
sortValue == "area" ? "Area" :
sortValue == "density" ? "Density" : "MA" )
.ar("ll", "black");
// Appends y-axis to the SVG and adds label
svg.append("g")
.ar("transform", `translate(${margin.le}, 0)`) .call(yAxis)
.append("text")
.ar("transform", "rotate(-90)")

lOMoARcPSD| 23136115
.ar("font-weight", "bold") .ar("x", - 200)
.ar("y", - 50) .text(
sortValue == "grdp" ? "Sorted by GRDP in VND" :
sortValue == "grdp_usd" ? "Sorted by GRDP in USD" :
sortValue == "populaon" ? "Sorted by Populaon" :
sortValue == "area" ? "Sorted by Area" :
sortValue == "density" ? "Sorted by Density" : "Sorted by MA" )
.ar("ll", "black");
// Appends bars to the SVG represenng data points
svg.selectAll("rect") .data(data)
.enter()
.append("rect")
.ar("x", margin.le + 5)
.ar("y", (d, i) => yScale(d[sortValue]))
.ar("width", 0) .transion()
.duraon(700)
.ar("width", (d) => xScale(d[sortValue]) - margin.le)
.ar("height", yScale.bandwidth())
.ar("ll", (d) => colorScale(d[sortValue]));
// Appends labels to the SVG near the bars
svg.selectAll(".label") .data(data)
.enter()
.append("text")
.ar("x", (d) => xScale(d[sortValue]) + 10)
.ar("y", (d, i) => yScale(d[sortValue]) + yScale.bandwidth() / 2 + 5)
.ar("font-family", "sans-serif") .ar("font-size", "11px")
.ar("ll", "white")
.text((d) => d.province) .transion()
.delay(500)
.ar("ll", "black");
}
</script> </body>
</html>

lOMoARcPSD| 23136115
Lab 3
<!DOCTYPE html>
<html lang="en"> <head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, inial-scale=1.0"> <tle>Lab 3</tle>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div id="container"> <h1>Lab 3</h1>
<p>Name: Ta Trung Hieu</p>
<p>Student ID: ITCSIU21180</p>
<p>Course Title: Data science and data visualizaon</p>
<p>Lab Title: Lab 3 – D3.js - scales</p>
<p>This is all my own work. I did not copy the code from any other source.</p>
<svg id="chart"></svg>
</div>
<script>
// Read CSV le and draw chart
d3.csv("hps://tungth.github.io/data/vn-provinces-data.csv", rowConverter) .then(data => { // When data is loaded
successfully
console.log(data); // Log the loaded data to the console
drawChart(data); // Call the drawChart funcon with the loaded data });
// Funcon to convert each row of data
funcon rowConverter(d) { return {
province: d.province, // Convert province to string
populaon: +d.populaon, // Convert populaon to number
grdp: parseFloat(d['GRDP-VND'].replace(',', '.')), // Convert GRDP-VND to number, replacing commas with dots
area: +d.area // Convert area to number
};
}
// Funcon to draw the chart using the provided data
funcon drawChart(data) {
// Dene SVG dimensions and margins
const svgWidth = 600;
const svgHeight = 400;
const margin = { top: 20, right: 20, boom: 50, le: 80 };

lOMoARcPSD| 23136115
const chartWidth = svgWidth - margin.le - margin.right;
const chartHeight = svgHeight - margin.top - margin.boom;
// Create SVG element
const svg = d3.select("#chart")
.ar("width", svgWidth)
.ar("height", svgHeight);
// Dene scales for x, y, area, and color
const xScale = d3.scaleLinear()
.domain(d3.extent(data, d => d.populaon)) // Domain based on populaon data
.range([margin.le, svgWidth - margin.right]);
const yScale = d3.scaleLinear()
.domain([0, 180]) // Fixed domain for GRDP-VND
.range([svgHeight - margin.boom, margin.top]);
const areaScale = d3.scaleSqrt()
.domain(d3.extent(data, d => d.area)) // Domain based on area data
.range([3, 12]); // Range for circle radius
const colorScale = d3.scaleSequenal()
.domain(d3.extent(data, d => d.populaon / d.area)) // Domain based on populaon/area rao
.interpolator(d3.interpolateTurbo); // Color interpolaon
// Draw circles for each data point
svg.selectAll("circle") .data(data)
.enter()
.append("circle")
.ar("cx", d => xScale(d.populaon))
.ar("cy", d => yScale(d.grdp))
.ar("r", d => areaScale(d.area))
.ar("ll", d => colorScale(d.populaon / d.area));
// Create x and y axis
const xAxis = d3.axisBoom(xScale); const yAxis =
d3.axisLe(yScale);
// Append x-axis to SVG
svg.append("g")
.ar("transform", `translate(0,${svgHeight - margin.boom})`) .call(xAxis)
.append("text")

lOMoARcPSD| 23136115
.ar("x", chartWidth) // Posion text at the end of the x-axis
.ar("y", -10)
.ar("text-anchor", "end")
.text("Populaon");
// Append y-axis to SVG
svg.append("g")
.ar("transform", `translate(${margin.le},0)`) .call(yAxis)
.append("text")
.ar("transform", "rotate(-90)")
.ar("y", chartWidth / 2) // Posion text at the middle of the y-axis .ar("x", -chartHeight / 2)
.ar("dy", "-2em") // Oset text from axis .ar("text-anchor", "middle")
.text("GRDP-VND (million VND/person/year)");
}
</script>
</body>
</html>
Bấm Tải xuống để xem toàn bộ.
Preview text:
id="chart">