lOMoARcPSD| 23136115
DSDV Mid Note
1.1. (35pts) Analyze a visualizaon. Analyze and evaluate the visualizaon in Figure 1 by answering
the following quesons: a. (5pts) What is the goal of the visualizaon?
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 visualizaon is to show the probability of near interacon between paents 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: aributes
C, The author has transmied the original data (which is integer) into the darkness of color shown in
the visualizaon 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 connues to be darker and darker unl it reaches ‘dark blue' at the end of the scale.
(STUDENT ANSWER 2 35/35)
a) This visualizaon is to show the rate of ight aendants and have close-rangecontact with a covid
paent.
b) This is a type of rao, where the auther get the rate of close contact between a ight aendants
and covid paents on a plane.
c) In this visualizaon, the author used squares as a mark on a background of real seats on a plane.
For the channels, author used hue and saturaon shown below: dark blue - > light blue -> white light
-> pink dark pink
d) As using 2 dierent hues, this visualizaon is a lile 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 saturaon, this
visualizaon may be beer to get the in sight.
lOMoARcPSD| 23136115
(GPT ANSWER)
a. Goal of the Visualizaon: The goal of the visualizaon is to represent the probability of infecon when
individuals are in close range with a sick person. This is indicated by the color gradient on an airplane
seang chart.
b. Data and Types of Data: The data consists of the probability percentages of passengers geng infected
when they are near a sick person. The types of data are categorical (seat labels and indicaons for sick
person and ight aendant) and quantave (probability percentages).
c. Use of Marks and Channels: The author used color as a channel to encode the data, with dierent
shades represenng dierent probabilies of infecon. Darker colors indicate higher probabilies.
Marks are used to represent seats, with special icons indicang the seat occupied by a sick person and
ight aendants.
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 disnguishable for all viewers including those with color
vision deciencies.
- Provide clear legends that explain what each mark and color represents.
- Instead of using color alone to represent the probability of infecon, consider using a combinaon
of color and size. For example, seats with a higher probability of infecon could be represented
by larger, darker circles, while seats with a lower probability could be represented by smaller,
lighter circles. This would make the visualizaon more accessible to a wider audience, including
those with color vision deciencies.
- Consider adding interacve elements to the visualizaon. For example, when a user hovers over
a seat, a toolp could appear showing the exact probability of infecon for that seat. This would
provide more precise informaon to the user.
- Finally, ensure that the visualizaon is responsive so that it can be viewed on devices of dierent
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 infecous in closed area like in an aircra cabin.
The Figure 2 shows a case of COVID-19 spreading in an aircra. However, the visualizaon is not
compable with gray-scale prinng.
Your task is to
a. Redesign the visualizaon in such a way that could show dierent sroups in a gray-scale prinng.
b. Jus your design: the reason for your selecon of marks, channels and others
lOMoARcPSD| 23136115
(STUDENT ANSWER 1 20/20)
a) Primary group and Secondary group have dierent shapes.
Ex: Primary. (infecous):
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/infecon, changeing the shape for each group to is a good opon. The idea
of adding a symbol inside of seat is one good alternave, but it can not be seen with the gray-scale
aribute, 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: Posion, Dierent shape
: Primary (infecous of ight)
: Primary (non-infecous of ight)
: Secondary (ight associated)
: Secondary (possible ight associated)
: Empty seat
: Negave PCR
(GPT ANSWER)
Redesigned Visualizaon for Gray-Scale Prinng:
Economy Class Cabin | Mid Cabin | A Cabin
-------------------------------------------
██ Primary (infecous on ight)
░░ Primary (non-infecous on ight)
▓▓ Secondary (ight associated)
▒▒ Secondary (possible ight associated)
Empty seat
XX Negave PCR
Juscaon for Design:
Marks and Channels:
lOMoARcPSD| 23136115
Primary (infecous on ight): Used a dark solid ll (██) to indicate high importance and immediate
aenon.
Primary (non-infecous on ight): Chose a light paern (░░) to dierenate from infecous but sll signify
potenal risk.
Secondary (ight associated): A medium dark paern (▓▓) represents conrmed secondary cases, disnct
from primary cases.
Secondary (possible ight associated): A lighter paern (▒▒) suggests uncertainty in the associaon.
Empty seat: Le blank to show the absence of a passenger.
Negave PCR: An ‘X’ mark (XX) is universally recognized and indicates a negave test result.
Reasoning:
The use of dierent shading paerns allows for clear dierenaon between groups without relying on
color.
Paerns are chosen to be disnct enough to avoid confusion when printed in grayscale.
The symbols are simple and can be easily understood without complex legends or explanaons.
2. (35pts) Design a visualizaon 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 aributes 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, posion and interacve visualizaon 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 (interacve visualizaon)
-> GPA
(STUDENT ANSWER 2 34/35)
For showing the student's data in a class, we will use the posion 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 iirst.
- For “Major”, I will use dierent hues for dierent major. For example, red for "IT", blue for "CS",
and green for "DS" (all of them are in the same level of saturaon, but dierent in hue)
- For "GPA", I will put this column to the second level of priority. I will use the saturaon level to
disnguish 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 posion number, I will move them to the top of each box.
Conclusion: by using 3 channels: posion, hue, saturaon 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 disnguished.
(GPT ANSWER)
I will use color, posion and interacve visualizaon 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 students
Group ID by pung 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
hps://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/
csse_covid_19_me_series/me_series_covid19_conrmed_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 conrmed 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 funcon of arrays in javascript) R5. (5pts) show
value in the bar Hint:
- Use rowConverter
- Use parseInt, parseFloat to convert strings to numbers - Filter funcon 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, inial-scale=1.0"> <tle>Midterm</tle>
<script src="hps://d3js.org/d3.v7.min.js"></script> </head>
<body>
<div id="chart"></div>
<script>
// Funcon to convert CSV row to desired data format
funcon rowConverter(row) {
lOMoARcPSD| 23136115
return {
place: row['Province/State'] + ', ' + row['Country/Region'],
cases: +row['4/4/22']
};
}
// Funcon to draw the chart using D3
funcon drawChart(data) {
// Dimensions and margins for the chart const svgWidth = 1500;
const svgHeight = 10000;
const margin = { top: 10, right: 20, boom: 50, le: 300 };
// Create SVG element
const svg = d3.select("#chart")
.append("svg")
.ar("width", svgWidth)
.ar("height", svgHeight)
// Dene 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.boom])
.padding(0.1);
// Color scale for the bars
const colorScale = d3.scaleSequenal()
.domain([0, d3.max(data, d => d.cases)])
.interpolator(d3.interpolateYlOrRd);
// Dene x and y axes
const xAxis = d3.axisBoom(xScale).ck(5); const yAxis =
d3.axisLe(yScale).ck(5);
// Append x axis to SVG
svg.append("g")
.ar("transform", `translate(5, ${svgHeight - margin.boom + 5})`)
.call(xAxis)
.append("text")
.ar("x", svgWidth - margin.right - 50) .ar("y", - 30)
lOMoARcPSD| 23136115
.ar("font-size", "30px")
.ar("font-weight", "bold") .text("Cases")
.ar("ll", "black");
// Append y axis to SVG
svg.append("g")
.ar("transform", `translate(${margin.le}, 0)`) .call(yAxis)
.append("text")
.ar("x", - 100)
.ar("y", 100)
.ar("font-size", "30px")
.ar("font-weight", "bold") .text("Place")
.ar("ll", "black");
// Draw bars on the chart
svg.selectAll("rect") .data(data)
.enter()
.append("rect")
.ar("x", margin.le + 5)
.ar("y", (d, i) => yScale(d.place))
.ar("width", 0) .transion()
.duraon(700)
.ar("width", (d) => xScale(d.cases) - margin.le)
.ar("height", yScale.bandwidth())
.ar("ll", (d) => colorScale(d.cases));
// Add labels to the bars
svg.selectAll(".label") .data(data)
.enter()
.append("text")
.ar("x", (d) => xScale(d.cases) + 10)
.ar("y", (d, i) => yScale(d.place) + yScale.bandwidth() / 2 + 5)
.ar("font-family", "sans-serif") .ar("font-size", "11px")
.ar("ll", "white") .text((d) => d.cases)
.transion()
.delay(500)
.ar("ll", "black");
lOMoARcPSD| 23136115
}
// Load data from CSV and draw the chart
d3.csv("me_series_covid19_conrmed_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, inial-scale=1.0"> <tle>Lab 4</tle>
<script src="hps://d3js.org/d3.v7.min.js"></script> </head>
<body>
<h1>Lab 4 –D3.js - Transion, 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>
<buon id="addBuon">Add New Province</buon>
<buon id="removeBuon">Remove Last Province</buon>
<select id="sortSelect">
<opon value="ma">MA</opon>
<opon value="area">Area</opon>
<opon value="populaon">Populaon</opon> <opon
value="density">Density</opon>
<opon value="grdp" selected>GRDP</opon>
<opon value="grdp_usd">GRDP (USD)</opon>
</select>
<div id="chart"></div>
<script>
var sortValue = "grdp"; //Load data
d3.csv("hps://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 buon
const addBuon = document.getElementById('addBuon');
let index = 20;
addBuon.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 buon
const removeBuon = document.getElementById('removeBuon');
removeBuon.addEventListener('click', () => { dataset.pop();
d3.select("svg").remove();
drawChart(dataset);
});
d3.select("#sortSelect").on("change", funcon() {
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 specic properes funcon rowConverter(row) {
// Converts strings to numbers where necessary return {
ma: +row.ma,
province: row.province,
area: +row.area,
populaon: +row.populaon, density: +row.density,
grdp: parseFloat(row['GRDP-VND'].replace(',', '.')),
grdp_usd: parseFloat(row['GRDP-USD'].replace(',', '.'))
};
}
// Draws the chart based on the provided data
funcon drawChart(data) {
// Denes dimensions and margins for the SVG element const svgWidth = 1000;
const svgHeight = 650;
const margin = { top: 10, right: 20, boom: 50, le: 70 };
// Selects the chart div and appends an SVG element to it const svg = d3.select("#chart")
.append("svg")
lOMoARcPSD| 23136115
.ar("width", svgWidth)
.ar("height", svgHeight)
// Denes 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.boom])
.padding(0.1);
// Denes color scale based on data values const colorScale =
d3.scaleSequenal()
.domain([0, d3.max(data, d => d[sortValue])])
.interpolator(d3.interpolateYlOrRd);
// Denes x and y axes
const xAxis = d3.axisBoom(xScale);
const yAxis = d3.axisLe(yScale).ckFormat(d3.format(".2f"));
// Appends x-axis to the SVG and adds label
svg.append("g")
.ar("transform", `translate(5, ${svgHeight - margin.boom + 5})`)
.call(xAxis)
.append("text")
.ar("x", svgWidth / 2) .ar("y", 40)
.ar("font-weight", "bold") .text(
sortValue == "grdp" ? "GRDP in VND" :
sortValue == "grdp_usd" ? "GRDP in USD" :
sortValue == "populaon" ? "Populaon" :
sortValue == "area" ? "Area" :
sortValue == "density" ? "Density" : "MA" )
.ar("ll", "black");
// Appends y-axis to the SVG and adds label
svg.append("g")
.ar("transform", `translate(${margin.le}, 0)`) .call(yAxis)
.append("text")
.ar("transform", "rotate(-90)")
lOMoARcPSD| 23136115
.ar("font-weight", "bold") .ar("x", - 200)
.ar("y", - 50) .text(
sortValue == "grdp" ? "Sorted by GRDP in VND" :
sortValue == "grdp_usd" ? "Sorted by GRDP in USD" :
sortValue == "populaon" ? "Sorted by Populaon" :
sortValue == "area" ? "Sorted by Area" :
sortValue == "density" ? "Sorted by Density" : "Sorted by MA" )
.ar("ll", "black");
// Appends bars to the SVG represenng data points
svg.selectAll("rect") .data(data)
.enter()
.append("rect")
.ar("x", margin.le + 5)
.ar("y", (d, i) => yScale(d[sortValue]))
.ar("width", 0) .transion()
.duraon(700)
.ar("width", (d) => xScale(d[sortValue]) - margin.le)
.ar("height", yScale.bandwidth())
.ar("ll", (d) => colorScale(d[sortValue]));
// Appends labels to the SVG near the bars
svg.selectAll(".label") .data(data)
.enter()
.append("text")
.ar("x", (d) => xScale(d[sortValue]) + 10)
.ar("y", (d, i) => yScale(d[sortValue]) + yScale.bandwidth() / 2 + 5)
.ar("font-family", "sans-serif") .ar("font-size", "11px")
.ar("ll", "white")
.text((d) => d.province) .transion()
.delay(500)
.ar("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, inial-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 visualizaon</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("hps://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 funcon with the loaded data });
// Funcon to convert each row of data
funcon rowConverter(d) { return {
province: d.province, // Convert province to string
populaon: +d.populaon, // Convert populaon to number
grdp: parseFloat(d['GRDP-VND'].replace(',', '.')), // Convert GRDP-VND to number, replacing commas with dots
area: +d.area // Convert area to number
};
}
// Funcon to draw the chart using the provided data
funcon drawChart(data) {
// Dene SVG dimensions and margins
const svgWidth = 600;
const svgHeight = 400;
const margin = { top: 20, right: 20, boom: 50, le: 80 };
lOMoARcPSD| 23136115
const chartWidth = svgWidth - margin.le - margin.right;
const chartHeight = svgHeight - margin.top - margin.boom;
// Create SVG element
const svg = d3.select("#chart")
.ar("width", svgWidth)
.ar("height", svgHeight);
// Dene scales for x, y, area, and color
const xScale = d3.scaleLinear()
.domain(d3.extent(data, d => d.populaon)) // Domain based on populaon data
.range([margin.le, svgWidth - margin.right]);
const yScale = d3.scaleLinear()
.domain([0, 180]) // Fixed domain for GRDP-VND
.range([svgHeight - margin.boom, 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.scaleSequenal()
.domain(d3.extent(data, d => d.populaon / d.area)) // Domain based on populaon/area rao
.interpolator(d3.interpolateTurbo); // Color interpolaon
// Draw circles for each data point
svg.selectAll("circle") .data(data)
.enter()
.append("circle")
.ar("cx", d => xScale(d.populaon))
.ar("cy", d => yScale(d.grdp))
.ar("r", d => areaScale(d.area))
.ar("ll", d => colorScale(d.populaon / d.area));
// Create x and y axis
const xAxis = d3.axisBoom(xScale); const yAxis =
d3.axisLe(yScale);
// Append x-axis to SVG
svg.append("g")
.ar("transform", `translate(0,${svgHeight - margin.boom})`) .call(xAxis)
.append("text")
lOMoARcPSD| 23136115
.ar("x", chartWidth) // Posion text at the end of the x-axis
.ar("y", -10)
.ar("text-anchor", "end")
.text("Populaon");
// Append y-axis to SVG
svg.append("g")
.ar("transform", `translate(${margin.le},0)`) .call(yAxis)
.append("text")
.ar("transform", "rotate(-90)")
.ar("y", chartWidth / 2) // Posion text at the middle of the y-axis .ar("x", -chartHeight / 2)
.ar("dy", "-2em") // Oset text from axis .ar("text-anchor", "middle")
.text("GRDP-VND (million VND/person/year)");
}
</script>
</body>
</html>

Preview text:

id="chart">