Public
Edited
May 21
Insert cell
Insert cell
vis1 = html`
<style>
.responsive-grid {
max-width:700px;
display: grid;
gap:10px;
align-items: start;
grid-template-columns: repeat(1, 1fr);
}

@media (min-width: 651px) {
.responsive-grid {
grid-template-columns: repeat(2, 1fr);
}
}
</style>

<h3 style="text-align: left">Світові ціни і експорт української залізної руди</h3>

<div class="responsive-grid">
<div>${vis11_}</div>
<div>${vis12_}</div>
</div>

<div style="color:grey;font-size:12px;line-height:1;text-align: left;padding-bottom:20px;">
Дані: Митниця, Держстат, Market Index, власні розрахунки
</div>
`
Insert cell
vis11_ = Plot.plot({
style: { fontSize: 14, fontWeight: 400 },
y: { label: "Щомісячна ціна на руду, $/тонна" },
width: 350,
marks: [Plot.ruleY([0]), Plot.lineY(data, { x: "date", y: "price" })]
})
Insert cell
vis12_ = Plot.plot({
style: { fontSize: 14, fontWeight: 400 },
y: {
label: "Експорт руди, млн тонн",
tickFormat: (d) => d / 1000
},
width: 350,
marginLeft: 50,
marks: [Plot.ruleY([0]), Plot.lineY(data, { x: "date", y: "export" })]
})
Insert cell
data = (await FileAttachment("merged@7.csv").csv())
.map((d) => {
return {
...d,
export: +d.export,
price: +d.price,
year: d.refYear,
date: new Date(d.date)
};
})
.filter((d) => d.export > 0)
// .filter((d) => d.date > new Date("2010-01-01"))
Insert cell
data_4 = (await FileAttachment("merged_4@3.csv").csv()).map((d) => {
return {
...d,
export: +d.export,
price: +d.price,
year: d.refPeriodId
// date: new Date(d.date)
};
})
Insert cell
vis2 = Plot.plot({
style: { fontSize: 14, fontWeight: 400 },
width: width > 650 ? 800 : 350,
height: 600,
inset: 10,
grid: true,
marginTop: 50,
marginBottom: 100,
marginRight: width > 650 ? 100 : 30,
marginLeft: width > 650 ? 100 : 35,
x: {
label: null,
tickFormat: (d) => d / 1000000,
domain: [0, 16000000]
},
y: {
label: null,
domain: [0, 200]
},
marks: [
Plot.line(data_4, {
x: "export",
y: "price",
curve: "catmull-rom",
marker: true
}),
Plot.text(data_4, {
// filter: (d) => d.year % 5 === 0,
x: "export",
y: "price",
text: (d) => `${d.year}`,
dy: -8,
fontSize: 12,
fill: "#333",
stroke: "#fff"
}),
Plot.text(
["↑ Середня світова ціна на\nруду в першому\nкварталі кожного року"],
{
frameAnchor: "top-left",
textAnchor: "start",
lineWidth: 18,
dx: width > 650 ? -100 : -30,
dy: -50,
fontWeight: 700,
fontSize: 15
}
),
Plot.text(["Український експорт руди\nза 4 місяці кожного року →"], {
frameAnchor: "bottom-right",
textAnchor: "start",
lineWidth: 18,
dx: width > 650 ? -100 : -170,
dy: 60,
fontWeight: 700,
fontSize: 15
}),
Plot.text(
[
"Перші чотири місяці 2025 року з погляду попиту (експорту) та цін були для рудокопів подібними до періодів 2015–2019 років"
],
{
frameAnchor: "middle",
textAnchor: "end",
lineWidth: 16,
dx: width > 650 ? 90 : 30,
dy: 0,
fill: "#333",
stroke: "#fff"
}
),
Plot.text(
[
"У 2015 році світові ціни на залізну руду впали до історичного мінімуму - нижче $50 за тонну, що стало найнижчим рівнем за останнє десятиліття через різкий надлишок пропозиції і падіння попиту з боку Китаю."
],
{
frameAnchor: "bottom-right",
textAnchor: "end",
lineWidth: 18,
dx: width > 650 ? 50 : 0,
dy: -20,
fill: "#333",
stroke: "#fff"
}
),
Plot.text(
[
width > 650
? "На 2020-2021 роки припав пік світових цін на залізну руду. В травні-липні 2021 року вона встановила історичний максимум – 210$/т. - в рамках світового відновлення після пандемії Covid."
: "На 2020-2021 роки припав пік світових цін на залізну руду"
],
{
frameAnchor: "top-right",
textAnchor: "start",
lineWidth: width > 650 ? 18 : 9,
dx: width > 650 ? -120 : -80,
dy: width > 650 ? -30 : -10,
fill: "#333",
stroke: "#fff"
}
)
]
})
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