import pandas as pd
from IPython.display import IFrame, HTML
import html
user, repository = 'd3', 'd3'
data = pd.read_json(f'https://api.github.com/repos/{user}/{repository}/stats/punch_card')
data.columns = ['dow', 'hour', 'contributions']
data.head()
dow | hour | contributions | |
---|---|---|---|
0 | 0 | 0 | 7 |
1 | 0 | 1 | 0 |
2 | 0 | 2 | 1 |
3 | 0 | 3 | 0 |
4 | 0 | 4 | 0 |
data.to_json('./data/d3-contributions.json', orient='records')
!cat punchcard.html
<!DOCTYPE html> <meta charset="utf-8"> <body> <style> div.tooltip { position: absolute; text-align: center; width: 60px; height: 28px; padding: 2px; font: 12px sans-serif; background: rgb(255, 255, 255); border: 0px; border-radius: 8px; pointer-events: none; } </style> <script src="https://d3js.org/d3.v5.min.js"></script> <script> const margin = {top: 20, right: 20, bottom: 50, left: 50}; const width = 600 - margin.left - margin.right; const height = 200 - margin.top - margin.bottom; const xScale = d3.scaleLinear().range([0, width]); const yScale = d3.scaleLinear().rangeRound([0, height]); const rScale = d3.scaleSqrt().range([0, 10]); const dayOfWeek = ["Sun", "Mon", "Tue", "Wed", "Thr", "Fri", "Sat"]; const svg = d3.select("body") .append("svg") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom) .append("g") .attr("transform", `translate(${margin.left}, ${margin.top})`); const dataPromise = d3.json("/files/contributions.json"); // inject:contributions dataPromise.then(data => { xScale.domain([-0.5, 23.5]); yScale.domain([-0.5, 6.5]); rScale.domain([0, d3.max(data, d => d.contributions)]); const div = d3.select("body").append("div") .attr("class", "tooltip") .style("opacity", 0); svg.selectAll("dot") .data(data) .enter().append("circle") .attr("r", d => rScale(d.contributions)) .attr("cx", d => xScale(d.hour)) .attr("cy", d => yScale(d.dow)) .on('mouseover', d => { div.transition() .duration(200) .style("opacity", .9); div.html(`${dayOfWeek[d.dow]}, ${d.hour}<br />${d.contributions}`) .style("left", (d3.event.pageX) + "px") .style("top", (d3.event.pageY - 28) + "px"); }) .on("mouseout", d => { div.transition() .duration(500) .style("opacity", 0); }); svg.append("g") .attr("transform", `translate(0, ${height})`) .call(d3.axisBottom(xScale).ticks(24)); svg.append("g") .call( d3.axisLeft(yScale) .ticks(7) .tickFormat((d, i) => dayOfWeek[d]) ); svg.append("text") .attr("transform", `translate(${width / 2}, ${(height + margin.top + 15)})`) .style("text-anchor", "middle") .style("font-size", "12px") .text("hour"); svg.append("text") .attr("transform", "rotate(-90)") .attr("y", 0 - margin.left) .attr("x", 0 - (height / 2)) .attr("dy", "1em") .style("text-anchor", "middle") .style("font-size", "12px") .text("day of week"); }); </script> </body>
IFrame(src="punchcard.html", width=650, height=250)
with open('punchcard.html', mode='r') as f:
punchcard_html = ''.join(f.readlines())
json_str = data.to_json(orient='records')
punchcard_html_injected = punchcard_html.replace(
'const dataPromise = d3.json("/files/contributions.json");',
f'const dataPromise = Promise.resolve({json_str});')
IFrame(f'data:text/html;charset=utf-8,{html.escape(punchcard_html_injected)}', width=650, height=250)
dow = ["Sun", "Mon", "Tue", "Wed", "Thr", "Fri", "Sat"]
json_str = (
data
.assign(dow = lambda d: d.dow.map(lambda i: dow[i]))
.rename(columns={'dow': 'day of week'})
.to_json(orient='records')
)
with open('2019-01-08_try_js_vis_tools/vega-lite/index.html', mode='r') as f:
vegalite_html = ''.join(f.readlines())
print(vegalite_html)
<!DOCTYPE html> <head> <title>Vega Lite Bar Chart</title> <meta charset="utf-8"> <script src="https://cdn.jsdelivr.net/npm/vega@4.3.0/build/vega.js"></script> <script src="https://cdn.jsdelivr.net/npm/vega-lite@3.0.0-rc10/build/vega-lite.js"></script> <script src="https://cdn.jsdelivr.net/npm/vega-embed@3.24.1/build/vega-embed.js"></script> </head> <body> <!-- Container for the visualization --> <div id="vis"></div> <script> // Assign the specification to a local variable vlSpec. var vlSpec = { "$schema": "https://vega.github.io/schema/vega-lite/v3.json", "data": { "url": "../../data/d3-contributions.json"}, "mark": { "type": "circle", "color": "black" }, "encoding": { "y": { "field": "day of week", "type": "nominal", "sort": ["Sun", "Mon", "Tue", "Wed", "Thr", "Fri", "Sat"] }, "x": { "field": "hour", "type": "nominal" }, "size": { "field": "contributions", "type": "quantitative", "aggregate": "sum" } } }; // Embed the visualization in the container with id `vis` vegaEmbed("#vis", vlSpec, {actions: false}); </script> </body> </html>
vegalite_html_injected = vegalite_html.replace(
'{ "url": "../../data/d3-contributions.json"}',
'{ "values": ' + json_str + '}')
IFrame(f'data:text/html;charset=utf-8,{html.escape(vegalite_html_injected)}', width=700, height=220)