Published
Edited
Aug 26, 2020
1 fork
2 stars
Insert cell
md`# Interactive Bar Chart of Taylor Swift Lyrics made on Twitch `
Insert cell
md`### Below is data of Taylor Swift lyrics`
Insert cell
Insert cell
FileAttachment("tswiftlyrics.csv")
Insert cell
md`#### Require d3`
Insert cell
d3 = {
const d3 = require("d3-dsv@1", "d3@5","d3-scale@3","d3-scale-chromatic@1", "d3-shape@1", "d3-array@2")
return d3
}
Insert cell
data = {
const text = await FileAttachment("tswiftlyrics.csv").text();
return d3.csvParse(text, ({lyric}) => ({
lyric: lyric
}));
}
Insert cell
md`#### Make a lyrics array of just the lyrics from the csv file`
Insert cell
lyrics = []
Insert cell
data.forEach(lyric => lyrics.push(lyric.lyric));
Insert cell
lyrics
Insert cell
md`#### regex, convert to lower-case, clean up text`
Insert cell
newLyrics = lyrics.join(' ').replace(/[.,\/#!""'$%\?^&\*;:{}=\-_`~()0-9]/g,"").toLowerCase()
Insert cell
md`#### stop words`
Insert cell
stopwords = ['i','me','my','myself','we','our','ours','ourselves','you','your','yours','yourself','yourselves','he','him','his','himself','she','her','hers','herself','it','its','itself','they','them','their','theirs','themselves','what','which','who','whom','this','that','these','those','am','is','are','was','were','be','been','being','have','has','had','having','do','does','did','doing','a','an','the','and','but','if','or','because','as','until','while','of','at','by','for','with','about','against','between','into','through','during','before','after','above','below','to','from','up','down','in','out','on','off','over','under','again','further','then','once','here','there','when','where','why','how','all','any','both','each','few','more','most','other','some','such','no','nor','not','only','own','same','so','than','too','very','s','t','can','will','just','don','should','now', 'im', 'ill', 'let', 'said', 'thats', 'oh', 'say', 'see', 'yeah', 'youre', 'ey', 'cant', 'dont', 'cause']
Insert cell
remove_stopwords = function(str) {
var res = []
var words = str.split(' ')
for(let i=0;i<words.length;i++) {
var word_clean = words[i].split(".").join("")
if(!stopwords.includes(word_clean)) {
res.push(word_clean)
}
}
return(res.join(' '))
}
Insert cell
lyrics_no_stopwords = remove_stopwords(newLyrics)
Insert cell
md`#### Get string frequency for each lyric`
Insert cell
strFrequency = function (stringArr) { //es6 way of getting frequencies of words
return stringArr.reduce((count, word) => {
count[word] = (count[word] || 0) + 1;
return count;
}, {})
}
Insert cell
obj = strFrequency(lyrics_no_stopwords.split(' '))
Insert cell
md`#### function to return the first n items in the object`
Insert cell
md`#### sort the frequencies to be max to min`
Insert cell
sortedObj = Object.fromEntries(
// switch a[1] and b[1] in the arrow function
Object.entries(obj).sort( (a,b) => b[1] - a[1] )
)
Insert cell
Insert cell
md`#### set attributes of the chart/graph`
Insert cell
margin = ({top: 20, right: 0, bottom: 30, left: 40})
Insert cell
height = 500
Insert cell
x = d3.scaleBand()
.domain(final.map(d => d.lyric))
.rangeRound([margin.left, width - margin.right])
.padding(0.1)
Insert cell
y = d3.scaleLinear()
.domain([0, d3.max(final, d => d.freq)])
.range([height - margin.bottom, margin.top])
Insert cell
yTitle = g => g.append("text")
.attr("font-family", "sans-serif")
.attr("font-size", 10)
.attr("y", 10)
.text("Frequency")
Insert cell
xAxis = g => g
.attr("transform", `translate(0,${height - margin.bottom})`)
.call(d3.axisBottom(x).tickSizeOuter(0))
Insert cell
yAxis = g => g
.attr("transform", `translate(${margin.left},0)`)
.call(d3.axisLeft(y).ticks(15))
.call(g => g.select(".domain").remove())
Insert cell
tooltip = d3.select("body")
.append("div")
.style("position", "absolute")
.style("font-family", "'Open Sans', sans-serif")
.style("font-size", "15px")
.style("z-index", "10")
.style("background-color", "#A7CDFA")
.style("color", "#B380BA")
.style("border", "solid")
.style("border-color", "#A89ED6")
.style("padding", "5px")
.style("border-radius", "2px")
.style("visibility", "hidden");
Insert cell
{
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height]);

// Call tooltip
tooltip;

svg.append("g")
.selectAll("rect")
.data(final)
.enter().append("rect")
.attr('x', d => x(d.lyric))
.attr('y', d => y(d.freq))
.attr('width', x.bandwidth())
.attr('height', d => y(0) - y(d.freq))
.style("padding", "3px")
.style("margin", "1px")
.style("width", d => `${d * 10}px`)
.text(d => d)
.attr("fill", "#CEBEDE")
.attr("stroke", "#FFB9EC")
.attr("stroke-width", 1)
.on("mouseover", function(d) {
tooltip.style("visibility", "visible").text(d.lyric + ": " + d.freq);
d3.select(this).attr("fill", "#FDE5BD");
})
.on("mousemove", d => tooltip.style("top", (d3.event.pageY-10)+"px").style("left",(d3.event.pageX+10)+"px").text(d.lyric + ": " + d.freq))
.on("mouseout", function(d) {
tooltip.style("visibility", "hidden");
d3.select(this)
.attr("fill", "#CEBEDE")
});

svg.append("g")
.call(xAxis);
svg.append("g")
.call(yAxis);
svg.call(yTitle);

return svg.node();
}
Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more