Published
Edited
May 2, 2019
1 fork
1 star
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
d3tip = require('d3-tip')
Insert cell
vegaEmbed = require("vega-embed@3")
Insert cell
import { vz } from '@gjmcn/vizsla-and-vega-lite'
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
goal_vs_time_data = d3.csv("https://gist.githubusercontent.com/cheung927/bee0838a281f5bb97a9ee220c1c099c6/raw/92f690b03b5aa886bc96c4887bb2d4ec0257df06/goal_vs_time_array.csv")
Insert cell
goal_vs_time_data2 = d3.csv("https://gist.githubusercontent.com/cheung927/74bb5a15844ac34e4f822ae31d96ada1/raw/f409cbfd9297dfbd8a48984a4b5c61515734f70c/goal_vs_time_array2.csv")
// time , distance, type (miss/post/saved/goals)
Insert cell
Insert cell
UsaVsPortugal731796 = d3.csv('https://gist.githubusercontent.com/cheung927/4b7bf42c0aee3b26c6594471398bc912/raw/69be9047f80438e5eaaa1cf01997c43a1bab8228/usa-vs-portugal-731796.csv')
Insert cell
events_merged_all = d3.csv('https://gist.githubusercontent.com/cheung927/4dfd25af0cfefe2886902902817f5a92/raw/a186a02a5834a84190e12624a5d0a4a94f77f9d7/events_merge_all.csv')
Insert cell
// move_merged_all = d3.csv('https://gist.githubusercontent.com/cheung927/49459947cff3bf24e550917fd22f2ce1/raw/38dbe190c0e9d10d21783ff9a66e7b04485d81f3/moves_merge_all.csv')
Insert cell
//form line chart
function finddistance (x1,x2,y1,y2){
return Math.pow(Math.pow((x2-x1),2)+Math.pow((y2-y1),2),0.5)
}
Insert cell
r = finddistance(92.5,52.2,100,39.4)
//example
Insert cell
{
let total_goal = 0
let total_miss = 0
let total_post = 0
let total_saved = 0
for (let i = 0; i < events_merged_all.length; i++){
if (events_merged_all[i].type === '16')
total_goal += 1
else if (events_merged_all[i].type === '13')
total_miss += 1
else if (events_merged_all[i].type === '14')
total_post += 1
else if (events_merged_all[i].type === '15')
total_saved += 1
}
return [total_miss, total_post, total_saved, total_goal]
}
Insert cell
function get_distance_array(r) {
let goala = ({
time: [],
distance: []
})
for (let i = 0; i < events_merged_all.length; i++)
if (events_merged_all[i].type === r){
goala.time.push(events_merged_all[i].min)
goala.distance.push(finddistance(events_merged_all[i].x,events_merged_all[i].to_x,events_merged_all[i].y,events_merged_all[i].to_y))
}
return goala
}
Insert cell
goal_array = get_distance_array("16")
Insert cell
miss_array = get_distance_array("13")
Insert cell
post_array = get_distance_array("14")
Insert cell
saved_array = get_distance_array("15")
Insert cell
total_miss = 677
Insert cell
total_post = 23
Insert cell
total_saved = 836
Insert cell
total_goal = 171
Insert cell
// {
// for (let i = 0; i < events_merged_all.length; i++){
// if (events_merged_all[i].type === '13'||events_merged_all[i].type === '14' || events_merged_all[i].type === '15'||events_merged_all[i].type === '16'){
// events_merged_all[i].field_pass = finddistance(events_merged_all[i].x,events_merged_all[i].to_x,events_merged_all[i].y,events_merged_all[i].to_y)
// }
// }
// } --------not use----------
Insert cell
{
for (let i = 0; i < events_merged_all.length; i++){
if (events_merged_all[i].side === 'A' && (events_merged_all[i].type === '13'||events_merged_all[i].type === '14' || events_merged_all[i].type === '15'||events_merged_all[i].type === '16')){
events_merged_all[i].x = 100 - events_merged_all[i].x
events_merged_all[i].to_x = 100 - events_merged_all[i].to_x
}
}//convert the away team data to the left
return events_merged_all
}
Insert cell
function typeconvert (x){
if (x === 13) return "Miss"
if (x === 14) return "Post"
if (x === 15) return "Saved"
if (x === 16) return "Goal"
}
Insert cell
//Usa Vs Portugal, miss(type:13) vs goal(type:16)

chart2 = {
const svg = d3.select(DOM.svg(width + margin.left + margin.right, height + margin.top + margin.bottom));
const pitch = svg.append('g')
.attr('transform', `translate(${margin.left},${margin.right})`)
// //tooltip
// const tooltip = d3tip()
// .style('border', 'solid 3px black')
// .style('background-color', 'white')
// .style('border-radius', '10px')
// .style('float', 'left')
// .style('font-family', 'monospace')
// // Apply tooltip to our SVG
// svg.call(tooltip)
pitch.append('rect')
.attr('x', -margin.left)
.attr('y', -margin.top)
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top + margin.bottom)
.style('fill', pitchColor)
//background
const pitchLineData = getPitchLines;
pitch.selectAll('.pitchLines')
.data(pitchLineData)
.enter().append('line')
.attr('x1', d => d['x1'] * pitchMultiplier)
.attr('x2', d => d['x2'] * pitchMultiplier)
.attr('y1', d => d['y1'] * pitchMultiplier)
.attr('y2', d => d['y2'] * pitchMultiplier)
.style('stroke-width', lineWidth)
.style('stroke', lineColor);
//all straight line
const shotData = UsaVsPortugal731796;
pitch.selectAll('.pitchLines')
.data(shotData.filter(function(d){return d.type == 13 && d.side == 'H'}))
.enter().append('line')
.attr('x1', d => width - d['x'] *8.4)
.attr('x2', d => width - d['to_x'] *8.4 )
.attr('y1', d => height - d['y'] *5.44 )
.attr('y2', d => height - d['to_y'] *5.44 )
.style('stroke-width', lineWidth)
.style('stroke', 'purple')
.attr('opacity', 0.5);
pitch.selectAll('.pitchCircles')
.data(shotData.filter(function(d){return d.type == 13 && d.side == 'H'}))
.enter().append('circle')
.attr('cx', d => width - d['x'] * 8.4)
.attr('cy', d => height - d['y'] * 5.44)
.attr('r', d => 5)
.style('stroke-width', lineWidth)
.style('stroke', lineColor)
.style('fill', d => 'SteelBlue');
//type 13: Miss by home team

pitch.selectAll('.pitchLines')
.data(shotData.filter(function(d){return d.type == 13 && d.side == 'A'}))
.enter().append('line')
.attr('x1', d => d['x'] *8.4)
.attr('x2', d => d['to_x'] *8.4 )
.attr('y1', d => d['y'] *5.44 )
.attr('y2', d => d['to_y'] *5.44 )
.style('stroke-width', lineWidth)
.style('stroke', 'purple')
.attr('opacity', 0.5);
pitch.selectAll('.pitchCircles')
.data(shotData.filter(function(d){return d.type == 13 && d.side == 'A'}))
.enter().append('circle')
.attr('cx', d => d['x'] * 8.4)
.attr('cy', d => d['y'] * 5.44)
.attr('r', d => 5)
.style('stroke-width', lineWidth)
.style('stroke', lineColor)
.style('fill', d => 'SteelBlue');
//type 13: Miss by away team
pitch.selectAll('.pitchLines')
.data(shotData.filter(function(d){return d.type == 16 && d.side == 'H'}))
.enter().append('line')
.attr('x1', d => width - d['x'] *8.4)
.attr('x2', d => width - d['to_x'] *8.4 )
.attr('y1', d => height - d['y'] *5.44 )
.attr('y2', d => height - d['to_y'] *5.44 )
.style('stroke-width', lineWidth)
.style('stroke', 'red')
.attr('opacity', 0.5);
pitch.selectAll('.pitchCircles')
.data(shotData.filter(function(d){return d.type == 16 && d.side == 'H'}))
.enter().append('circle')
.attr('cx', d => width - d['x'] * 8.4)
.attr('cy', d => height - d['y'] * 5.44)
.attr('r', d => 5)
.style('stroke-width', lineWidth)
.style('stroke', lineColor)
.style('fill', d => 'GoldenRod');
//type 16: goal by home team

pitch.selectAll('.pitchLines')
.data(shotData.filter(function(d){return d.type == 16 && d.side == 'A'}))
.enter().append('line')
.attr('x1', d => d['x'] *8.4)
.attr('x2', d => d['to_x'] *8.4 )
.attr('y1', d => d['y'] *5.44 )
.attr('y2', d => d['to_y'] *5.44 )
.style('stroke-width', lineWidth)
.style('stroke', 'red')
.attr('opacity', 0.5);
pitch.selectAll('.pitchCircles')
.data(shotData.filter(function(d){return d.type == 16 && d.side == 'A'}))
.enter().append('circle')
.attr('cx', d => d['x'] * 8.4)
.attr('cy', d => d['y'] * 5.44)
.attr('r', d => 5)
.style('stroke-width', lineWidth)
.style('stroke', lineColor)
.style('fill', d => 'GoldenRod');
//type 16: goal by away team
const pitchCircleData = getPitchCircles2;
pitch.selectAll('.pitchCircles')
.data(pitchCircleData)
.enter().append('circle')
.attr('cx', d => d['cx'] * pitchMultiplier)
.attr('cy', d => d['cy'] * pitchMultiplier)
.attr('r', d => d['r'] * pitchMultiplier)
.style('stroke-width', lineWidth)
.style('stroke', lineColor)
.style('fill', d => d['color']);
//circle

const pitchArcData = getArcs;
const arc = d3.arc();
pitch.selectAll('.pitchCorners')
.data(pitchArcData)
.enter().append('path')
.attr('d', d => arc(d['arc']))
.attr('transform', d => `translate(${pitchMultiplier * d.x},${pitchMultiplier * d.y})`)
.style('fill', lineColor);
//curve
return svg.node();
}
Insert cell
md`## Total miss and total goal in World Cup 2014`
Insert cell
////all matches, miss(type:13) vs goal(type:16)

chart4 = {
const svg = d3.select(DOM.svg(width + margin.left + margin.right, height + margin.top + margin.bottom));
const pitch = svg.append('g')
.attr('transform', `translate(${margin.left},${margin.right})`)
//tooltip
const tooltip = d3tip()
.style('border', 'solid 3px black')
.style('background-color', 'white')
.style('border-radius', '10px')
.style('float', 'left')
.style('font-family', 'arial')
.html(d => `
xPosition: ${Math.round(d.x)} <br/>
yPosition: ${Math.round(d.y)} <br/>
Distance to goal : ${Math.round(finddistance(d.x,d.to_x,d.y,d.to_y))} <br/>
</div>`)
// Apply tooltip to our SVG
svg.call(tooltip)
pitch.append('rect')
.attr('x', -margin.left)
.attr('y', -margin.top)
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top + margin.bottom)
//.style('fill', pitchColor)
.style('fill', 'green')
.attr('opacity', 0.7);
//background
const pitchLineData = getPitchLines;
pitch.selectAll('.pitchLines')
.data(pitchLineData)
.enter().append('line')
.attr('x1', d => d['x1'] * pitchMultiplier)
.attr('x2', d => d['x2'] * pitchMultiplier)
.attr('y1', d => d['y1'] * pitchMultiplier)
.attr('y2', d => d['y2'] * pitchMultiplier)
.style('stroke-width', lineWidth)
//.style('stroke', lineColor);
.style('stroke', 'white');
//all straight line
const shotData2 = events_merged_all;
pitch.selectAll('.pitchLines')
.data(shotData2.filter(function(d){return d.type == 13}))
.enter().append('line')
.attr('x1', d => d['x'] *8.4)
.attr('x2', d => d['to_x'] *8.4 )
.attr('y1', d => d['y'] *5.44 )
.attr('y2', d => d['to_y'] *5.44 )
.style('stroke-width', lineWidth)
.style('stroke', 'purple')
.attr('opacity', 0.15);
pitch.selectAll('.pitchCircles')
.data(shotData2.filter(function(d){return d.type == 13}))
.enter().append('circle')
.attr('cx', d => d['x'] * 8.4)
.attr('cy', d => d['y'] * 5.44)
.attr('r', d => 5)
.style('stroke-width', lineWidth)
.style('stroke', lineColor)
.style('fill', d => 'SteelBlue')
.on('mouseover', tooltip.show)
.on('mouseout', tooltip.hide);
//type 13: Miss

pitch.selectAll('.pitchLines')
.data(shotData2.filter(function(d){return d.type == 16}))
.enter().append('line')
.attr('x1', d => d['x'] *8.4)
.attr('x2', d => d['to_x'] *8.4 )
.attr('y1', d => d['y'] *5.44 )
.attr('y2', d => d['to_y'] *5.44 )
.style('stroke-width', lineWidth)
.style('stroke', 'red')
.attr('opacity', 0.15);
pitch.selectAll('.pitchCircles')
.data(shotData2.filter(function(d){return d.type == 16}))
.enter().append('circle')
.attr('cx', d => d['x'] * 8.4)
.attr('cy', d => d['y'] * 5.44)
.attr('r', d => 5)
.style('stroke-width', lineWidth)
.style('stroke', lineColor)
.style('fill', d => 'GoldenRod')
.on('mouseover', tooltip.show)
.on('mouseout', tooltip.hide);
//type 13: Miss
const pitchCircleData = getPitchCircles2;
pitch.selectAll('.pitchCircles')
.data(pitchCircleData)
.enter().append('circle')
.attr('cx', d => d['cx'] * pitchMultiplier)
.attr('cy', d => d['cy'] * pitchMultiplier)
.attr('r', d => d['r'] * pitchMultiplier)
.style('stroke-width', lineWidth)
//.style('stroke', lineColor)
.style('fill', d => d['color'])
.style('stroke', 'white');
//circle

const pitchArcData = getArcs;
const arc = d3.arc();
pitch.selectAll('.pitchCorners')
.data(pitchArcData)
.enter().append('path')
.attr('d', d => arc(d['arc']))
.attr('transform', d => `translate(${pitchMultiplier * d.x},${pitchMultiplier * d.y})`)
//.style('fill', lineColor)
.style('stroke', 'white');
//curve
return svg.node();
}
Insert cell
md`## Total Saved and total goal in World Cup 2014`
Insert cell
////saved (type:15) vs goal(type:16) in all matches

chart5 = {
const svg = d3.select(DOM.svg(width + margin.left + margin.right, height + margin.top + margin.bottom));
const pitch = svg.append('g')
.attr('transform', `translate(${margin.left},${margin.right})`)
//tooltip
const tooltip = d3tip()
.style('border', 'solid 3px black')
.style('background-color', 'white')
.style('border-radius', '10px')
.style('float', 'left')
.style('font-family', 'arial')
.html(d => `
Type: ${(typeconvert(d.type))} <br/>
xPosition: ${Math.round(d.x)} <br/>
yPosition: ${Math.round(d.y)} <br/>
Distance to goal : ${Math.round(finddistance(d.x,d.to_x,d.y,d.to_y))} <br/>
</div>`)
// Apply tooltip to our SVG
svg.call(tooltip)
pitch.append('rect')
.attr('x', -margin.left)
.attr('y', -margin.top)
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top + margin.bottom)
//.style('fill', pitchColor)
.style('fill', 'green')
.attr('opacity', 0.7);
//background
const pitchLineData = getPitchLines;
pitch.selectAll('.pitchLines')
.data(pitchLineData)
.enter().append('line')
.attr('x1', d => d['x1'] * pitchMultiplier)
.attr('x2', d => d['x2'] * pitchMultiplier)
.attr('y1', d => d['y1'] * pitchMultiplier)
.attr('y2', d => d['y2'] * pitchMultiplier)
.style('stroke-width', lineWidth)
//.style('stroke', lineColor);
.style('stroke', 'white');
//all straight line
const shotData2 = events_merged_all;
pitch.selectAll('.pitchLines')
.data(shotData2.filter(function(d){return d.type == 15}))
.enter().append('line')
.attr('x1', d => d['x'] *8.4)
.attr('x2', d => d['to_x'] *8.4 )
.attr('y1', d => d['y'] *5.44 )
.attr('y2', d => d['to_y'] *5.44 )
.style('stroke-width', lineWidth)
.style('stroke', 'purple')
.attr('opacity', 0.25);
pitch.selectAll('.pitchCircles')
.data(shotData2.filter(function(d){return d.type == 15}))
.enter().append('circle')
.attr('cx', d => d['x'] * 8.4)
.attr('cy', d => d['y'] * 5.44)
.attr('r', d => 5)
.style('stroke-width', lineWidth)
.style('stroke', lineColor)
.style('fill', d => 'pink')
.on('mouseover', tooltip.show)
.on('mouseout', tooltip.hide);
//type 15: saved

pitch.selectAll('.pitchLines')
.data(shotData2.filter(function(d){return d.type == 16}))
.enter().append('line')
.attr('x1', d => d['x'] *8.4)
.attr('x2', d => d['to_x'] *8.4 )
.attr('y1', d => d['y'] *5.44 )
.attr('y2', d => d['to_y'] *5.44 )
.style('stroke-width', lineWidth)
.style('stroke', 'red')
.attr('opacity', 0.5);
pitch.selectAll('.pitchCircles')
.data(shotData2.filter(function(d){return d.type == 16}))
.enter().append('circle')
.attr('cx', d => d['x'] * 8.4)
.attr('cy', d => d['y'] * 5.44)
.attr('r', d => 5)
.style('stroke-width', lineWidth)
.style('stroke', lineColor)
.style('fill', d => 'GoldenRod')
.on('mouseover', tooltip.show)
.on('mouseout', tooltip.hide);
//type 16: goal
const pitchCircleData = getPitchCircles2;
pitch.selectAll('.pitchCircles')
.data(pitchCircleData)
.enter().append('circle')
.attr('cx', d => d['cx'] * pitchMultiplier)
.attr('cy', d => d['cy'] * pitchMultiplier)
.attr('r', d => d['r'] * pitchMultiplier)
.style('stroke-width', lineWidth)
//.style('stroke', lineColor)
.style('fill', d => d['color'])
.style('stroke', 'white');
//circle

const pitchArcData = getArcs;
const arc = d3.arc();
pitch.selectAll('.pitchCorners')
.data(pitchArcData)
.enter().append('path')
.attr('d', d => arc(d['arc']))
.attr('transform', d => `translate(${pitchMultiplier * d.x},${pitchMultiplier * d.y})`)
//.style('fill', lineColor)
.style('stroke', 'white');
//curve
return svg.node();
}
Insert cell
chart6 = {
const shotData3 = events_merged_all;

const height = 600
const svg = d3.select(DOM.svg(width, height))
const margin = { left: 30, top: 10, right: 10, bottom: 20 }
// Use d3.scaleTime() instead of d3.scaleLinear() for datetime
const xScale = d3.scaleLinear()
.range([margin.left, width - margin.right])
// .domain(d3.extent(shotData3.map(d => d.min)))
.domain([0,120])
svg.append('g')
.call(d3.axisBottom(xScale))
.attr('transform', `translate(0,${height - margin.bottom})`)

const yScale = d3.scaleLinear()
.range([height - margin.bottom, margin.top])
// Substitute dataset
.domain(d3.extent(shotData3.map(d => d.y)))

svg.append('g')
.call(d3.axisLeft(yScale))
.attr('transform', `translate(${margin.left},0)`)

svg.selectAll('circle')
.data(goal_vs_time_data)
.enter()
.append('circle')
// Circles are distributed across x-axis
.attr('cx', d => xScale(d.gtime))
// Across y-axis as well, and it becomes two dimensional
.attr('cy', d => yScale(d.gdistance))
.attr('r', 5)
.attr('opacity',0.5)
.attr('fill', 'GoldenRod')
// .append('circle')
// // Circles are distributed across x-axis
// .attr('cx', d => xScale(d.mtime))
// // Across y-axis as well, and it becomes two dimensional
// .attr('cy', d => yScale(d.mdistance))
// .attr('r', 5)
// .attr('opacity',0.5)
// .attr('fill', 'SteelBlue')

return svg.node()
}
Insert cell
md`## Comparing goal activities' distanace to the goal along with the time`
Insert cell
vegaEmbed({
data: { values: goal_vs_time_data2 },
width: 500,
height: 400,
title: 'Goal vs time',
mark: 'point',
encoding: {
x: { field: 'time' },
y: { field: 'distance' },
color: { field: 'type' }
}
})
Insert cell
md`## Total amount of goal activities in 2014 World Cup`
Insert cell
chart8 = {
var data=[
{x:"total_miss", y:total_miss},
{x:"total_post", y:total_post},
{x:"total_saved", y:total_saved},
{x:"total_goal", y:total_goal},
];
const height = 600
const svg = d3.select(DOM.svg(width, height))
const margin = { left: 30, top: 10, right: 10, bottom: 20 }
const xScale = d3.scaleBand()
.range([0, width])
.domain(data.map((s) => s.x))
.padding(0.5)
svg.append('g')
.call(d3.axisBottom(xScale))
.attr('transform', `translate(0,${height - margin.bottom})`)
const yScale = d3.scaleLinear()
.range([height - margin.bottom, margin.top])
.domain([0,1000])
svg.append('g')
.call(d3.axisLeft(yScale))
.attr('transform', `translate(${margin.left},0)`)

svg.selectAll('rect')
.data(data)
.enter()
.append('rect')
.attr('x', d => xScale(d.x))
.attr('y', d => yScale(d.y))
.attr('height', d => yScale(0) - yScale(d.y))
.attr('width', 100)
.attr('fill', 'SteelBlue')
return svg.node()
}
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