Published
Edited
May 2, 2019
3 forks
4 stars
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")
//Not use
Insert cell
a = d3.csv('https://gist.githubusercontent.com/whtsead213/9e84c3e9194427641d937ea24bb8b253/raw/9449fb763e0e55a5c5595c95b9eb913f7fc63391/merged_event.csv', d => {return {"play_id": d.player_id, "x": d.x, "y": d.y, "to_x": d.to_x, "to_y": d.to_y, "type": d.type, "outcome": d.outcome, "side": d.side, "match_name": d.match_name}})
Insert cell
f1 = function (a) {
var output = [];
a.forEach(function (d) {
if (output.indexOf(d.match_name) === -1) {
output.push(d.match_name);
}
});
return output;
};
Insert cell
data1 = f1(a)
Insert cell
f2 = function(match_name){
var output = [];
match_name.forEach(function (d) {
if (output.indexOf(d) === -1) {
output.push({"match_name": d, children: []});
}
});
return output;
}
Insert cell
data2 = f2(data1)
Insert cell
f3 = function(output, a){
for(var i=0; i<a.length; i++){
if(a[i].type === "1" && a[i].outcome === "1"){
for(var j=0; j<output.length; j++){
if(output[j].match_name == a[i].match_name){
output[j].children.push(a[i]);
}
}
}
}
return output;
}
Insert cell
data = f3(data2, a)
Insert cell
goal_vs_time_data2 = d3.csv("https://gist.githubusercontent.com/cheung927/74bb5a15844ac34e4f822ae31d96ada1/raw/f409cbfd9297dfbd8a48984a4b5c61515734f70c/goal_vs_time_array2.csv")
// col: time , distance, type (miss/post/saved/goals)
// preprocessed data for further use
Insert cell
Insert cell
UsaVsPortugal731796 = d3.csv('https://gist.githubusercontent.com/cheung927/4b7bf42c0aee3b26c6594471398bc912/raw/69be9047f80438e5eaaa1cf01997c43a1bab8228/usa-vs-portugal-731796.csv')
// for testing purpose, one match in World Cup 2014
Insert cell
events_merged_all = d3.csv('https://gist.githubusercontent.com/cheung927/4dfd25af0cfefe2886902902817f5a92/raw/a186a02a5834a84190e12624a5d0a4a94f77f9d7/events_merge_all.csv')
Insert cell
//function for finding the distance
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
md` ### Calculate goal activities`
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 === "1") return "Pass"
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 => `
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 == 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_data2)
.enter()
.append('circle')
// Circles are distributed across x-axis
.attr('cx', d => xScale(d.time))
// Across y-axis as well, and it becomes two dimensional
.attr('cy', d => yScale(d.distance))
.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: 800,
height: 600,
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
md`## Total goal activities in World Cup 2014`
Insert cell
// Total goal activities in World Cup 2014
vchart1 = vegaEmbed({
data: {
values: [
{"Activity": "total miss","Number": total_miss},
{"Activity": "total post","Number": total_post},
{"Activity": "total saved","Number": total_saved},
{"Activity": "total goal","Number": total_goal},
]
},
encoding: {
y: {"field": "Activity", "type": "ordinal"},
x: {"field": "Number", "type": "quantitative"}
},
layer: [{
mark: "bar"
}, {
mark: {
type: "text",
align: "left",
baseline: "middle",
dx: 3
},
encoding: {
text: {"field": "Number", "type": "quantitative"}
}
}]
})
Insert cell
md`## Precentage of goal activities in World Cup 2014`
Insert cell
vchart2 = vegaEmbed({
data: {
values: [
{"Activity": "total miss","Number": total_miss},
{"Activity": "total post","Number": total_post},
{"Activity": "total saved","Number": total_saved},
{"Activity": "total goal","Number": total_goal},
]
},
transform: [{
window: [{
op: "sum",
field: "Number",
as: "TotalNumber"
}],
frame: [null, null]
},
{
calculate: "datum.Number/datum.TotalNumber * 100",
as: "PercentOfTotal"
}],
mark: "bar",
encoding: {
x: {
field: "PercentOfTotal",
type: "quantitative",
axis: {
title: "% of total Time"
}
},
y: {
field: "Activity",
type: "ordinal",
scale: {
rangeStep: 12
}
}
}
})

Insert cell
import {select} from "@jashkenas/inputs"
Insert cell
WorldCup2014Players = d3.csv('https://gist.githubusercontent.com/wingchu/c44283c2975cbdd32ef65454052d5e56/raw/d2b321163bf98dc50916147e0f121d1475f92243/player.csv', d => {return {"id": d.id, "name": d.name}})
Insert cell
viewof selected_match = select({
title: 'Pick a match:',
options: data1,
value: data1
});
Insert cell
followByMatch = function(d, m){
var list = [];
for(var i=0; i<d.length; i++){
if(d[i].match_name == m){
for(var j=0; j<d[i].children.length; j++){
if(list.indexOf(d[i].children[j].play_id)===-1){
list.push(d[i].children[j].play_id);
}
}
}
}
return list;
}
Insert cell
list = followByMatch(data, selected_match)
Insert cell
list_id = followByMatch(data, selected_match)
Insert cell
WorldCup2014Players
Insert cell
function id_to_name (list){
for (var i = 0; i < WorldCup2014Players.length; i++){
for (var j = 0; j < list.length; j++){
if (WorldCup2014Players[i].id == list[j]){
list[j] = WorldCup2014Players[i].name;
}
}
}
}
Insert cell
function name_to_id (name){
for (var i = 0; i < WorldCup2014Players.length; i++){
if (WorldCup2014Players[i].name == name){
name = WorldCup2014Players[i].id;
}
}
return name;
}
Insert cell
viewof selected_player = select({
title: 'Pick a player:',
options: list,
value: selected_match
});
Insert cell
selected_player
Insert cell
selected_player_id = name_to_id(selected_player)
Insert cell
data
Insert cell
data_filter = function (d, selected_match) {
var output = [];
for(var i=0; i<d.length; i++){
if(d[i].match_name == selected_match){
for(var j=0; j<d[i].children.length; j++){
output.push(d[i].children[j]);
}
}
}
return output;
}
Insert cell
data_matched = data_filter(data, selected_match)
Insert cell
teamsplit = selected_match.split("-")
Insert cell
md`## Pass Events in match: ${selected_match} <br/>`
Insert cell
md`### ${teamsplit[0]} : Blue (Home Team) | ${teamsplit[2]} : Pink (Away Team)`

Insert cell
//selected match

chart12 = {
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/>
Home/Away: ${d.side} <br/>
xPosition: ${Math.round(d.x)} <br/>
yPosition: ${Math.round(d.y)} <br/>
Pass Distance : ${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
pitch.selectAll('.pitchLines')
.data(data_matched.filter(function(d){return d.side == "H"}))
.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', 'blue')
.attr('opacity', 0.15);
pitch.selectAll('.pitchCircles')
.data(data_matched.filter(function(d){return d.side == "H"}))
.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')
.attr('opacity', 0.75)
.on('mouseover', tooltip.show)
.on('mouseout', tooltip.hide);
//type 1 , side = home team
pitch.selectAll('.pitchLines')
.data(data_matched.filter(function(d){return 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.15);
pitch.selectAll('.pitchCircles')
.data(data_matched.filter(function(d){return 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 => 'pink')
.attr('opacity', 0.75)
.on('mouseover', tooltip.show)
.on('mouseout', tooltip.hide);
//type 1 , side = 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'])
.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`### Using vegaEmbed to show Pass Event coordinate`
Insert cell
md`### ${teamsplit[0]} : Gold (Home Team) | ${teamsplit[2]} : Blue (Away Team)`
Insert cell
vegaEmbed({
data: { values: data_matched },
width: 840,
height: 544,
title: 'Pass Events happened place ',
mark: 'point',
encoding: {
x: { field: 'x' },
y: { field: 'y' },
color: { field: 'side' }
}
})
Insert cell
md`## player pass activities in the match`
Insert cell
md`### player name: ${selected_player} | Match: ${selected_match}`
Insert cell
//selected match

chart13 = {
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/>
Name: ${selected_player} <br/>
Home/Away: ${d.side} <br/>
xPosition: ${Math.round(d.x)} <br/>
yPosition: ${Math.round(d.y)} <br/>
Pass Distance : ${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
pitch.selectAll('.pitchLines')
.data(data_matched.filter(function(d){return (d.side == "H") && (d.play_id == selected_player_id) }))
.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(data_matched.filter(function(d){return (d.side == "H") && (d.play_id == selected_player_id) }))
.enter().append('circle')
.attr('cx', d => d.x * 8.4)
.attr('cy', d => d.y * 5.44)
.attr('r', d => 8)
.style('stroke-width', lineWidth)
.style('stroke', lineColor)
.style('fill', d => 'SteelBlue')
.attr('opacity', 0.75)
.on('mouseover', tooltip.show)
.on('mouseout', tooltip.hide);
//type 1 , side = home team
pitch.selectAll('.pitchLines')
.data(data_matched.filter(function(d){return (d.side == "A") && (d.play_id == selected_player_id) }))
.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.75);
pitch.selectAll('.pitchCircles')
.data(data_matched.filter(function(d){return (d.side == "A") && (d.play_id == selected_player_id) }))
.enter().append('circle')
.attr('cx', d => d.x * 8.4)
.attr('cy', d => d.y * 5.44)
.attr('r', d => 8)
.style('stroke-width', lineWidth)
.style('stroke', lineColor)
.style('fill', d => 'SteelBlue')
.attr('opacity', 0.75)
.on('mouseover', tooltip.show)
.on('mouseout', tooltip.hide);
//type 1 , side = 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'])
.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

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more