Published
Edited
Dec 10, 2020
Importers
Insert cell
md`# Exploratory Data Analysis`
Insert cell
md` ## Quick Overview`
Insert cell
Insert cell
md` ## Statistical Overview`
Insert cell
avg_freethrow = d3.mean(data1, d => d["FT%"])
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
md`### attempt to put it all together`
Insert cell
// Select metric to visualize in the treemap
viewof metric = select({
title: "Metric for visualization",

options: [
{ label: "height", value: "height" },
{ label: "average points per game", value: "per" }
]
})
Insert cell
biglinechart = {
const svg = d3
.create("svg")
.attr("viewBox", [-80, -40, width + 80, height + 100]);

svg.node().update = game => {
svg.selectAll("*").remove();

const gx = svg
.append("g")
.call(linexAxis)
.attr("transform", `translate(0, ${height - margin.bottom})`);

const line_x = d3
.scaleTime()
.domain([
d3.min(summedLineData.map(d => formatutc(d[0]))),
d3.max(summedLineData.map(d => formatutc(d[0])))
])
.range([margin.left, width - margin.right]);

const line_y = d3
.scaleBand()
.domain(summedLineData.map(d => d[game]))
.range([margin.top, height - margin.bottom])
.padding(0.1)
.round(true);

const lineyAxis = (g, scale = line_y) =>
g
.attr("transform", `translate(${margin.left},0)`)
.call(d3.axisLeft(scale).ticks(height));

const gy = svg.append("g").call(lineyAxis);

const line = d3
.line()
.defined(d => !isNaN(d[game]))
.x(d => line_x(d[0]))
.y(d => line_y(d[game]));

svg
.append("path")
.datum(summedLineData)
.attr("fill", "none")
.attr("stroke", "steelblue")
.attr("stroke-width", 0.5)
.attr("stroke-linejoin", "round")
.attr("stroke-linecap", "round")
.attr("d", line);
};
return svg.node();
}
Insert cell
biglinechart.update(metric)
Insert cell
md`
### Summary:
We created these two graphs in order to compare the average height and points per game every year from 2010 to 2015 and to see if there was a relation between the two or if there was a different trend within each team. According to our two graphs, the relations for both the average points per game and the height have a negative relationship with the years. Even though the trend is showing that there is a connection when the average height is lower the average points per game is also lower, the drop is not really significant. From the data we collected and analyzed above, once again the relationship of points per game and height isn't clear enough to make a conclusion, for that we can say that there isn't a relationship between height and points per game.
`
Insert cell
md` ## Filtering Data & Preparing Graph`
Insert cell
filtered_data = data.filter(d => d.Year > "2010")
Insert cell
filtered_data1 = filtered_data.filter(d => d.PER > 0)
Insert cell
filtered_data2 = filtered_data1.filter(d => d.Height > 0)
Insert cell
chosen_data = {
if (team == "") {
return filtered_data1;
} else {
const temp_data = filtered_data2.filter(d => d.Tm == team);
const result_data = temp_data.map(d => {
return {
Year: formatutc(d["Year"]),
team: d["Tm"],
PER: +d["PER"],
height: +d["Height"]
};
});
return result_data;
}
}
Insert cell
filtered_team_data = {
const results = {};
chosen_data.forEach(d => {
if (d.Year in results) {
results[d.Year].points += d.PER;
results[d.Year].count += 1;
} else {
results[d.Year] = {
year: d.Year,
points: d.PER,
count: 1
};
}
});

const final_results = [];
for (const cat in results) {
final_results.push({
year: results[cat].year,
average: results[cat]["points"] / results[cat].count
});
}
return final_results;
}
Insert cell
chosen_data2 = {
if (team == "") {
return filtered_data1;
} else {
const temp_data = filtered_data2.filter(d => d.Year == year_select);
const result_data = temp_data.map(d => {
return {
team: d["Tm"],
PER: +d["PER"],
height: +d["Height"]
};
});
return result_data;
}
}
Insert cell
preperingData = {
const results = {};
chosen_data2.forEach(d => {
if (d.team in results) {
results[d.team].points += d.PER;
results[d.team].countPts += 1;
results[d.team].height += d.height;
results[d.team].countHeight += 1;
} else {
results[d.team] = {
team: d.team,
points: d.PER,
countPts: 1,
height: d.height,
countHeight: 1
};
}
});

const final_results = [];
for (const cat in results) {
final_results.push({
color: results[cat].team,
x: results[cat]["points"] / results[cat].countPts,
y: results[cat]["height"] / results[cat].countHeight
});
}
return final_results;
}
Insert cell
uniqColor = _.uniqBy(preperingData, d => d.color).map(d => d.color)
Insert cell
xScale = d3
.scaleLinear()
.domain([
d3.min(preperingData, d => d.x),
d3.max(preperingData, d => d.x) + 1
])
.range([margin.left, width - margin.right])
Insert cell
yScale = d3
.scaleLinear()
.domain([d3.min(preperingData, d => d.y), d3.max(preperingData, d => d.y)])
.range([height - margin.bottom, margin.top])
Insert cell
colorScale = d3.scaleOrdinal(uniqColor, d3.schemeCategory10)
Insert cell
xAxis1 = g =>
g
.attr("transform", `translate(0,${height - margin.bottom})`)
.call(d3.axisBottom(xScale))
Insert cell
yAxis1 = g =>
g.attr("transform", `translate(${margin.left}, 0)`).call(d3.axisLeft(yScale))
Insert cell
colorLegend = () =>
swatches({
color: colorScale
})
Insert cell
histogram1_x_scale = d3
.scaleTime()
.domain(d3.extent(filtered_team_data, d => d.year))
.range([0, width - 250])
Insert cell
histogram1_y_scale = d3
.scaleLinear()
.domain([0, d3.max(filtered_team_data, d => d.average) + 1])
.range([height - margin.bottom, margin.top])
Insert cell
histogram1_x_axis = g =>
g
.attr("transform", `translate(${margin.left}, ${height - margin.bottom})`)
.call(d3.axisBottom(histogram1_x_scale))
Insert cell
histogram1_y_axis = g =>
g
.attr("transform", `translate(${margin.left},0)`)
.call(d3.axisLeft(histogram1_y_scale))
Insert cell
x = d3
.scaleLinear()
.domain(d3.extent(formatted_data, d => d.x))
.range([margin.left, 600 - margin.right])
Insert cell
y = d3
.scaleLinear()
.domain(d3.extent(formatted_data, d => d.y))
.range([600 - margin.bottom, margin.top])
Insert cell
xAxis = g =>
g
.attr("transform", `translate(0,${600 - margin.bottom})`)
.call(d3.axisBottom(x))
Insert cell
yAxis = g =>
g.attr("transform", `translate(${margin.left},0)`).call(d3.axisLeft(y))
Insert cell
drawPoint = circle => {
circle
.attr("cx", d => x(d.x))
.attr("cy", d => y(d.y))
.attr("r", 5)
.style('opacity', 0.5);
}
Insert cell
xLabel = ele =>
ele
.text("Points Per Game")
.attr("x", (x.range()[1] - x.range()[0]) / 2 + 75)
.attr("y", 600 - margin.bottom + 50)
.style('font-family', "sans-serif")
.style("font-size", '14px')
Insert cell
yLabel = ele =>
ele
.text("Height (inches)")
.attr("transform", `translate(${margin.left - 40}, ${600 / 2})rotate(-90)`)
.style("text-anchor", "middle")
.style('font-family', "sans-serif")
Insert cell
chartTitle = ele =>
ele
.text(choosen_team + " 2010-2016 Season")
.attr("transform", `translate(${600 / 2}, ${20})`)
.style("text-anchor", "middle")
.style('font-family', "sans-serif")
Insert cell
drawChart = ele => {
const svg = ele
.append("svg")
.style("height", 625 + "px")
.style("width", 700 + "px");

svg.append("g").call(xAxis);
svg.append("g").call(yAxis);

svg.append('text').call(xLabel);
svg.append('text').call(chartTitle);
svg.append('text').call(yLabel);

svg
.selectAll("circle")
.data(d => d.values)
.join("circle")
.call(drawPoint);
}
Insert cell
chart_type_data = d3
.nest()
.key(d => d.team)
.entries(formatted_data)
Insert cell
line_chart_data = data.map(d => {
return {
year: d["Year"],
x: +d["PER"],
y: +d["Weight"],
age: +d["Age"],
height: +d["Height"]
};
})
Insert cell
line_chart_data1 = line_chart_data
.filter(d => d.year > 2010)
.filter(d => d.year < 2016)
.sort((a, b) => b.year - a.year)
Insert cell
d3_ = require("d3-array@2")
Insert cell
by_year = d3_.groups(line_chart_data1, d => d.year)
Insert cell
line_yrs = d3_.rollups(
line_chart_data1,
v => d3_.mean(v, d => d.height),
d => d.year
)
Insert cell
lines_yrs2 = d3_.rollups(
line_chart_data1,
v => d3_.mean(v, d => d.x),
d => d.year
)
Insert cell
summedLineData = {
let arr = [];
for (let i = 0; i < line_yrs.length; i++) {
const summedData = {};
summedData.yrs = line_yrs[i][0];
summedData.height = line_yrs[i][1];
summedData.per = lines_yrs2[i][1];
arr.push(summedData);
}
return arr;
}
Insert cell
line_x = d3
.scaleTime()
.domain([
d3.min(line_yrs.map(d => formatutc(d[0]))),
d3.max(line_yrs.map(d => formatutc(d[0])))
])
.range([margin.left, width - margin.right])
Insert cell
line_x2 = d3
.scaleTime()
.domain([
d3.min(lines_yrs2.map(d => formatutc(d[0]))),
d3.max(lines_yrs2.map(d => formatutc(d[0])))
])
.range([margin.left, width - margin.right])
Insert cell
line_y2 = d3
.scaleBand()
.domain(lines_yrs2.map(d => d[1]))
.range([margin.top, height - margin.bottom])
.padding(0.1)
.round(true)
Insert cell
line_y = d3
.scaleBand()
.domain(line_yrs.map(d => d[1]))
.range([margin.top, height - margin.bottom])
.padding(0.1)
.round(true)
Insert cell
line2 = d3
.line()
.defined(d => !isNaN(formatutc(d[0])))
.x(d => line_x2(formatutc(d[0])))
.y(d => line_y2(d[1]))
Insert cell
line = d3
.line()
.defined(d => !isNaN(formatutc(d[0])))
.x(d => line_x(formatutc(d[0])))
.y(d => line_y(d[1]))
Insert cell
linexAxis2 = d3
.axisBottom()
.scale(line_x2)
.ticks(5)
Insert cell
linexAxis = d3
.axisBottom()
.scale(line_x)
.ticks(5)
Insert cell
lineyAxis2 = (g, scale = line_y2) =>
g
.attr("transform", `translate(${margin.left},0)`)
.call(d3.axisLeft(scale).ticks(height))
Insert cell
lineyAxis = (g, scale = line_y) =>
g
.attr("transform", `translate(${margin.left},0)`)
.call(d3.axisLeft(scale).ticks(height))
Insert cell
line_chart_data1
Insert cell
formatted_data2 = data2.map(d => {
return {
player: d["Player"],
team: d["Tm"],
point: +d["PTS"]
};
})
Insert cell
md`## Appendix`
Insert cell
_ = require("lodash")
Insert cell
d3 = require("d3@5")
Insert cell
margin = ({ top: 40, right: 30, bottom: 40, left: 70 })
Insert cell
width = 500
Insert cell
height = 500
Insert cell
formatutc = d3.timeParse("%Y")
Insert cell
import { data, data1, data2 } from "@uw-info474/project-proposal"
Insert cell
import { autoSelect, select } from "@jashkenas/inputs"
Insert cell
import { swatches, legend } from "@d3/color-legend"
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