Public
Edited
Nov 3, 2022
Insert cell
Insert cell
// data = {
// var d = d3.csvParse(await FileAttachment("google://US_youtube_trending_data_sentiment.csv").text(), d3.autoType)
// d.columns = Object.keys(d[1]);
// return d;
// }
Insert cell
data= csvfile.csv({typed: true})
Insert cell
Insert cell
Insert cell
Insert cell
// byDay = d3.rollup(data_title,
// v => Object.fromEntries(columnsToSum.map(col => [col, d3.mean(v, d => d[col])])),
// d => d.categories)
Insert cell
Insert cell
Insert cell
// data_by_months_year= d3.rollup(data_view,
// v => Object.fromEntries(columnsToSum2.map(col => [col, d3.sum(v, d => d[col])])),
// d => d.category,d => d.published_month)
Insert cell
// data_by_days= d3.rollup(data_view,
// v => v.length,
// d => d.category,d => d.published_week)
Insert cell
Insert cell
Insert cell
Insert cell
// data_by_trend_days= d3.rollup(days_to_trend,
// v => v.length,
// d => d.category,d => d.date_range)
Insert cell
Insert cell
viewof csvfile = Inputs.file({label: "CSV file", accept: ".csv", required: true})
Insert cell
Insert cell
// Copyright 2021 Observable, Inc.
// Released under the ISC license.
// https://observablehq.com/@d3/bar-chart
function BarChart(data, {
x = (d, i) => i, // given d in data, returns the (ordinal) x-value
y = d => d, // given d in data, returns the (quantitative) y-value
title, // given d in data, returns the title text
marginTop = 20, // the top margin, in pixels
marginRight = 0, // the right margin, in pixels
marginBottom = 30, // the bottom margin, in pixels
marginLeft = 40, // the left margin, in pixels
width = 640, // the outer width of the chart, in pixels
height = 400, // the outer height of the chart, in pixels
xDomain, // an array of (ordinal) x-values
xRange = [marginLeft, width - marginRight], // [left, right]
yType = d3.scaleLinear, // y-scale type
yDomain, // [ymin, ymax]
yRange = [height - marginBottom, marginTop], // [bottom, top]
xPadding = 0.1, // amount of x-range to reserve to separate bars
yFormat, // a format specifier string for the y-axis
yLabel, // a label for the y-axis
color = "currentColor" // bar fill color
} = {}) {
// Compute values.
const X = d3.map(data, x);
const Y = d3.map(data, y);

// Compute default domains, and unique the x-domain.
if (xDomain === undefined) xDomain = X;
if (yDomain === undefined) yDomain = [0, d3.max(Y)];
xDomain = new d3.InternSet(xDomain);

// Omit any data not present in the x-domain.
const I = d3.range(X.length).filter(i => xDomain.has(X[i]));

// Construct scales, axes, and formats.
const xScale = d3.scaleBand(xDomain, xRange).padding(xPadding);
const yScale = yType(yDomain, yRange);
const xAxis = d3.axisBottom(xScale).tickSizeOuter(0);
const yAxis = d3.axisLeft(yScale).ticks(height / 40, yFormat);

// Compute titles.
if (title === undefined) {
const formatValue = yScale.tickFormat(100, yFormat);
title = i => `${X[i]}\n${formatValue(Y[i])}`;
} else {
const O = d3.map(data, d => d);
const T = title;
title = i => T(O[i], i, data);
}

const svg = d3.create("svg")
.attr("width", width)
.attr("height", height)
.attr("viewBox", [0, 0, width, height])
.attr("style", "max-width: 100%; height: auto; height: intrinsic;");

svg.append("g")
.attr("transform", `translate(${marginLeft},0)`)
.call(yAxis)
.call(g => g.select(".domain").remove())
.call(g => g.selectAll(".tick line").clone()
.attr("x2", width - marginLeft - marginRight)
.attr("stroke-opacity", 0.1))
.call(g => g.append("text")
.attr("x", -marginLeft)
.attr("y", 10)
.attr("fill", "currentColor")
.attr("text-anchor", "start")
.text(yLabel));

const bar = svg.append("g")
.attr("fill", color)
.selectAll("rect")
.data(I)
.join("rect")
.attr("x", i => xScale(X[i]))
.attr("y", i => yScale(Y[i]))
.attr("height", i => yScale(0) - yScale(Y[i]))
.attr("width", xScale.bandwidth());

if (title) bar.append("title")
.text(title);

svg.append("g")
.attr("transform", `translate(0,${height - marginBottom})`)
.call(xAxis);

return svg.node();
}
Insert cell
import {howto, altplot} from "@d3/example-components"
Insert cell
chart = BarChart(view_sentiment_array, {
x: d => d.category,
y: d => d.net_popularity_per_view,
xDomain: d3.groupSort(view_sentiment_array, ([d]) => -d.net_popularity_per_view, d => d.category), // sort by descending frequency
yFormat: "%",
yLabel: "↑ Net Popularity per View",
width,
height: 500,
color: "steelblue"
})
Insert cell
// Copyright 2021 Observable, Inc.
// Released under the ISC license.
// https://observablehq.com/@d3/grouped-bar-chart
function GroupedBarChart(data, {
x = (d, i) => i, // given d in data, returns the (ordinal) x-value
y = d => d, // given d in data, returns the (quantitative) y-value
z = () => 1, // given d in data, returns the (categorical) z-value
title, // given d in data, returns the title text
marginTop = 30, // top margin, in pixels
marginRight = 0, // right margin, in pixels
marginBottom = 30, // bottom margin, in pixels
marginLeft = 40, // left margin, in pixels
width = 640, // outer width, in pixels
height = 400, // outer height, in pixels
xDomain, // array of x-values
xRange = [marginLeft, width - marginRight], // [xmin, xmax]
xPadding = 0.1, // amount of x-range to reserve to separate groups
yType = d3.scaleLinear, // type of y-scale
yDomain, // [ymin, ymax]
yRange = [height - marginBottom, marginTop], // [ymin, ymax]
zDomain, // array of z-values
zPadding = 0.05, // amount of x-range to reserve to separate bars
yFormat, // a format specifier string for the y-axis
yLabel, // a label for the y-axis
colors = d3.schemeTableau10, // array of colors
} = {}) {
// Compute values.
const X = d3.map(data, x);
const Y = d3.map(data, y);
const Z = d3.map(data, z);

// Compute default domains, and unique the x- and z-domains.
if (xDomain === undefined) xDomain = X;
if (yDomain === undefined) yDomain = [0, d3.max(Y)];
if (zDomain === undefined) zDomain = Z;
xDomain = new d3.InternSet(xDomain);
zDomain = new d3.InternSet(zDomain);

// Omit any data not present in both the x- and z-domain.
const I = d3.range(X.length).filter(i => xDomain.has(X[i]) && zDomain.has(Z[i]));

// Construct scales, axes, and formats.
const xScale = d3.scaleBand(xDomain, xRange).paddingInner(xPadding);
const xzScale = d3.scaleBand(zDomain, [0, xScale.bandwidth()]).padding(zPadding);
const yScale = yType(yDomain, yRange);
const zScale = d3.scaleOrdinal(zDomain, colors);
const xAxis = d3.axisBottom(xScale).tickSizeOuter(0);
const yAxis = d3.axisLeft(yScale).ticks(height / 60, yFormat);

// Compute titles.
if (title === undefined) {
const formatValue = yScale.tickFormat(100, yFormat);
title = i => `${X[i]}\n${Z[i]}\n${formatValue(Y[i])}`;
} else {
const O = d3.map(data, d => d);
const T = title;
title = i => T(O[i], i, data);
}

const svg = d3.create("svg")
.attr("width", width)
.attr("height", height)
.attr("viewBox", [0, 0, width, height])
.attr("style", "max-width: 100%; height: auto; height: intrinsic;");

svg.append("g")
.attr("transform", `translate(${marginLeft},0)`)
.call(yAxis)
.call(g => g.select(".domain").remove())
.call(g => g.selectAll(".tick line").clone()
.attr("x2", width - marginLeft - marginRight)
.attr("stroke-opacity", 0.1))
.call(g => g.append("text")
.attr("x", -marginLeft)
.attr("y", 10)
.attr("fill", "currentColor")
.attr("text-anchor", "start")
.text(yLabel));

const bar = svg.append("g")
.selectAll("rect")
.data(I)
.join("rect")
.attr("x", i => xScale(X[i]) + xzScale(Z[i]))
.attr("y", i => yScale(Y[i]))
.attr("width", xzScale.bandwidth())
.attr("height", i => yScale(0) - yScale(Y[i]))
.attr("fill", i => zScale(Z[i]));

if (title) bar.append("title")
.text(title);

svg.append("g")
.attr("transform", `translate(0,${height - marginBottom})`)
.call(xAxis);

return Object.assign(svg.node(), {scales: {color: zScale}});
}
Insert cell
import {Legend, Swatches} from "@d3/color-legend"
Insert cell
import {howto, altplot} from "@d3/example-components"
Insert cell
chart2 = GroupedBarChart(view_sentiment_array, {
x: d => d.category,
y: d => d.net_popularity_per_view,
z: d => d.sentiment_scores,
xDomain: d3.groupSort(view_sentiment_array, D => d3.sum(D, d => -d.population), d => d.state).slice(0, 6), // top 6
yLabel: "↑ Score (0 to 1)",
zDomain: d => d.sentiment_scores,
colors: d3.schemeSpectral[d => d.sentiment_scores.length],
width,
height: 500
})
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