Public
Edited
Jan 11
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
daily_orders
Type Table, then Shift-Enter. Ctrl-space for more options.

Insert cell
stores
Type Table, then Shift-Enter. Ctrl-space for more options.

Insert cell
daily_orders_product
Type Table, then Shift-Enter. Ctrl-space for more options.

Insert cell
// Convert order_date values to Date objects
orderDates = daily_orders_product.map(d => new Date(d.order_date));
Insert cell
startDate = d3.min(orderDates);
Insert cell
endDate = d3.max(orderDates);
Insert cell
// Display the results
startDate.toISOString(); // Fecha de inicio
Insert cell
endDate.toISOString(); // Fecha de fin
Insert cell
Insert cell
Insert cell
Insert cell
aggregatedData = d3.rollup(
daily_orders_product,
v => ({
averagePrice: d3.mean(v, d => d.price),
totalRevenue: d3.sum(v, d => d.revenue)
}),
d => d.name // group by product name
);
Insert cell
Insert cell
aggregatedData2 = Array.from(aggregatedData, ([productName, {averagePrice, totalRevenue}]) => ({
productName,
averagePrice,
totalRevenue
}));
Insert cell
Insert cell
mergedData = daily_orders.map(order => {
const store = stores.find(store => store.id === order.store_id);
return {
city: store.city,
revenue: order.revenue,
order_date: new Date(order.order_date),
store_id: order.store_id
};
});
Insert cell
Insert cell

cityRevenueSum = mergedData.reduce((acc, order) => {
const city = order.city;
if (!acc[city]) {
acc[city] = 0;
}
acc[city] += order.revenue;
return acc;
}, {});

Insert cell
Insert cell
sortedCityRevenue = Object.keys(cityRevenueSum).map(city => ({
city: city,
total_revenue: cityRevenueSum[city]
}));

Insert cell
Insert cell

sortedDataByCityRevenue = sortedCityRevenue.sort((a, b) => b.total_revenue - a.total_revenue);
Insert cell
Insert cell
quarterlyData = d3.rollups(
daily_orders,
group => ({
revenue: d3.sum(group, d => d.revenue)
}),
d => {
const date = new Date(d.order_date);
const year = date.getFullYear();
const quarter = Math.ceil((date.getMonth() + 1) / 3);
return `${year}-Q${quarter}`; // "YYYY-QN"
}
).map(([quarter, values]) => ({
quarter,
revenue: values.revenue
}));

Insert cell
Insert cell
ribbonData = d3.rollups(
daily_orders,
group => ({
revenue: d3.sum(group, d => d.revenue)
}),
d => {
const date = new Date(d.order_date);
const year = date.getFullYear();
const quarter = Math.ceil((date.getMonth() + 1) / 3);
return `${year}-Q${quarter}`;
},
d => d.store_id
).flatMap(([quarter, stores]) =>
stores.map(([store_id, values]) => ({
quarter,
store_id,
revenue: values.revenue
}))
);

Insert cell
ribbonData.sort((a, b) => {
const [yearA, quarterA] = a.quarter.split('-Q').map(Number);
const [yearB, quarterB] = b.quarter.split('-Q').map(Number);
return yearA === yearB ? quarterA - quarterB : yearA - yearB;
});

Insert cell
Insert cell
groupedData = d3.rollups(
daily_orders_product,
v => d3.sum(v, d => d.revenue),
d => d.day_of_week
);
Insert cell
Insert cell
groupedData.sort((a, b) => d3.ascending(a[0], b[0]));
Insert cell
Insert cell
averageRevenueByDay = d3.rollups(
daily_orders_product,
v => d3.mean(v, d => d.revenue),
d => d.day_of_week_num
);
Insert cell
quarterlyRevenue = d3.rollups(
daily_orders_product,
(group) => d3.sum(group, (d) => d.revenue),
(d) => `${d3.timeFormat("%Y")(new Date(d.order_date))}-Q${Math.ceil((new Date(d.order_date).getMonth() + 1) / 3)}`,
(d) => d.category
).flatMap(([quarter, categories]) =>
categories.map(([category, revenue]) => ({
quarter,
category,
revenue,
}))
);
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Plot.plot({
marks: [
Plot.dot(aggregatedData2, {
x: "averagePrice",
y: "totalRevenue",
fill: "#FFA500",
stroke: "#8B4513",
title: d => `Product: ${d.productName}\nAverage price: $${d.averagePrice.toFixed(2)}`,
r: 8
})
],
x: { label: "Average Price, $" },
y: { label: "Total Revenue, $" },
width: 600,
height: 400,
marginLeft: 80,
marginTop: 30,
marginBottom: 50,
marginRight: 20
})
Insert cell
Insert cell
Plot.plot({
marks: [
Plot.ruleY([0]),
Plot.lineY(quarterlyRevenue, {
x: "quarter",
y: "revenue",
z: "category",
stroke: "category",
strokeWidth: 3,
title: (d) => `Quarter: ${d.quarter}\nCategory: ${d.category}\nRevenue: $${d.revenue.toFixed(2)}`
})
],
color: {
domain: ["Classic", "Specialty", "Vegetarian"],
range: ["orange", "#eb6d58", "#a9cdb1"],
legend: true
},
x: {
label: "Quarter",
tickRotate: -45,
},
y: {
label: "Revenue, $",
grid: true
},
height: 400,
width: 800,
marginLeft: 80,
marginTop: 30,
marginBottom: 60,
marginRight: 20,
tooltip: (event, d) => {return `Quarter: ${d.quarter}<br>Category: ${d.category}<br>Revenue: $${d.revenue.toFixed(2)}`;
}
});
Insert cell
Insert cell
Plot.plot({
marks: [
Plot.barX(sortedDataByCityRevenue, {
x: "total_revenue",
y: "city",
fill: "orange",
height: 600,
marginLeft: 120,
marginTop: 10,
marginBottom: 50,
marginRight: 20,
title: d => `Revenue: $${d.total_revenue.toFixed(2)}` // Tooltip
}),
Plot.ruleX([0])
]
});
Insert cell
Insert cell
Plot.plot({
x: {
domain: Array.from(new Set(ribbonData.map(d => d.quarter))),
label: "Quarter",
tickRotate: -45
},
y: {
grid: true,
label: "Revenue, $"
},
color: {
domain: Array.from(new Set(ribbonData.map(d => d.store_id))),
range: d3.Observable10,
legend: true,
label: "Store ID - City"
},
marks: [
Plot.barY(ribbonData, {
x: "quarter",
y: "revenue",
z: "store_id",
fill: "store_id",
order: "value",
width: 600,
height: 450,
marginLeft: 80,
marginTop: 20,
marginBottom: 60,
marginRight: 20
})
]
})

Insert cell
Insert cell
Plot.plot({
marks: [
Plot.barY(averageRevenueByDay, {
x: d => d[0],
y: d => d[1],
fill: "orange",
height: 600,
marginLeft: 120,
marginTop: 10,
marginBottom: 50,
marginRight: 20,
title: d => `Week day: ${d[0]}, Revenue Mean: $${d[1].toFixed(2)}`,
color: "steelblue"
})
],
x: {
label: "Week day"
},
y: {
label: "Revenue Mean, $"
}
})

Insert cell
Insert cell
Insert cell
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