Public
Edited
Aug 3, 2023
Insert cell
Insert cell
arealineY(data,
{x: d => (!years || d.Date >= years[0] && d.Date <= years[1]) ? d.Date : NaN,
y: "Close",
color: "gray"})
.plot({
x: {
label: "Year",
domain: years
},
y: {
grid: true,
label: "Share Price [$]",
domain: [0, d3.max(data, (d) => d.Close)]
},
marks: [
Plot.ruleX(data, Plot.pointerX({x: "Date", py: "Close", stroke: "red"})),
Plot.dot(data, Plot.pointerX({x: "Date", y: "Close", stroke: "red"})),
Plot.text(data, Plot.pointerX({px: "Date", py: "Close", dy: -15, frameAnchor: "top", fontVariant: "tabular-nums", text: (d) => [`Apple's share price closed at $${d.Close.toFixed(2)} on ${Plot.formatIsoDate(d.Date)}`]})),
//https://archive.nytimes.com/www.nytimes.com/library/cyber/week/091797apple.html
Plot.tip(
[`Apple names Steve Jobs interim CEO`],{x: new Date("1997-09-16"), y:0.2, dy: -3, anchor: "bottom"},
),
//https://www.apple.com/newsroom/2006/05/16Apple-Unveils-New-MacBook-Featuring-Intel-Core-Duo-Processors/
Plot.tip(
[`Apple starts selling MacBook`],{x: new Date("2006-05-16"), y:2.32, dy: -3, anchor: "bottom"},
),
//https://www.apple.com/newsroom/2007/06/28iPhone-Premieres-This-Friday-Night-at-Apple-Retail-Stores/
Plot.tip(
[`Apple starts selling iPhone`],{x: new Date("2007-06-29"), y:4.36, dy: -43, anchor: "bottom"},
),
//https://www.apple.com/newsroom/2010/01/27Apple-Launches-iPad/
Plot.tip(
[`Apple starts selling iPad`],{x: new Date("2010-04-03"), y:8.52, dy: -3, anchor: "bottom"},
),
//https://www.apple.com/newsroom/2011/08/24Steve-Jobs-Resigns-as-CEO-of-Apple/
Plot.tip(
[`Tim Cook suceeds Steve Jobs as Apple's CEO`],{x: new Date("2011-08-24"), y:13.44, dy: -43, dx: 10, anchor: "bottom"},
),
//https://www.apple.com/newsroom/2015/03/09Apple-Watch-Available-in-Nine-Countries-on-April-24/
Plot.tip(
[`Apple starts selling Apple Watch`],{x: new Date("2015-04-24"), y:32.57, dy: 19, anchor: "top"},
),
Plot.tip(
[`Apple starts selling Apple TV+`],{x: new Date("2019-11-01"), y:63.96, dy: -3, anchor: "bottom"},
)
],
width: 1200
})
Insert cell
viewof years = brushFilterX(
d3.extent(data, (d) => d.Date),
{ defaultExtent: [d3.isoParse("1995-03-01"), d3.isoParse(Date.now())],
width: 1200
},
)
Insert cell
Insert cell
Insert cell
Insert cell
// Converts a Google Sheets website URL to its CSV URL. You can also go to “File → Publish to web”, select the “Comma-separated values (.csv)” type, select the sheet with your data, and use that CSV URL directly with `d3.csv` above. If you need data to update faster, try the Google Sheets API: https://stackoverflow.com/questions/30082277/accessing-a-new-style-public-google-sheet-as-json/44479726#44479726

getCsvUrl = url => {
url = new URL(url);
const id = url.pathname.split("/")[3]
const gid = new URLSearchParams(url.hash.slice(1)).get("gid") || 0;
return `https://docs.google.com/spreadsheets/d/${id}/export?format=csv&gid=${gid}`
}
Insert cell
Insert cell
import { SummaryTable } from "@observablehq/summary-table"
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