Sestavte si interaktivní sloupcový graf textů Taylor Swift pomocí D3.js a Observable

Vizualizace dat jsou užitečné způsoby, jak zkoumat data a přemýšlet o nich. Observable je nástroj podobný Jupyter Notebooku, který usnadňuje rychlé spouštění kódu JavaScript v buňkách, takže můžete vidět, co děláte v reálném čase.

Tento příspěvek se bude zabývat tím, jak vytvořit interaktivní sloupcový graf zobrazující nejpoužívanější slova Taylor Swift z jejích textů s Observable pomocí D3.js. Mezitím si zde můžete prohlédnout hotový zápisník a vizualizaci a sami si je můžete rozvětvovat a upravovat.

Stručný úvod do Observable

Každou jinou buňku si můžete představit jako funkci. Buňky přicházejí ve dvou primárních formách:

  1. Výrazy . Výrazové buňky jsou nejstručnější a jsou určeny pro jednoduché definice a v části Pozorovatelné mimo uzávěrku nepotřebujete var /const /let klíčové slovo.

  2. Blokování . Blokové buňky jsou ohraničeny složenými závorkami a obsahují složitější kód, který může obsahovat lokální proměnné a smyčky.

Protože místní proměnné jako arr výše nelze odkazovat jinými buňkami, mnoho notebooků Observable vkládá různé definice a funkce do svých vlastních buněk. To je to, co tento příspěvek udělá také – všechny úryvky kódu by měly být ve svých vlastních buňkách a po přidání kódu do buňky byste jej měli spustit zadáním shift-return .

Podrobnější úvod do Observable naleznete v tomto poznámkovém bloku.

Nastavení

Stáhněte si tento datový soubor textů Taylor Swift a poté si vytvořte účet pro pozorovatele, pokud jej ještě nemáte. Jakmile budete mít účet, vytvořte si nový poznámkový blok kliknutím na tlačítko Nový v pravém horním rohu.

Chcete-li začít, umístěte kurzor myši poblíž levé části buňky. Měli byste vidět znaménko plus takto:

Importujte datovou sadu ze svého počítače kliknutím na znaménko plus pod existující buňkou burzy, kliknutím do buňky Pozorovatelné a poté kliknutím na shift-command-u na Macu. Poté vyberte soubor, který chcete importovat (nezapomeňte jej rozbalit!) Ve vybrané buňce byste pak měli vidět něco jako:

FileAttachment("tswiftlyrics.csv")

Název vašeho souboru se může lišit. Buňku můžete spustit kliknutím na trojúhelník směřující doprava na pravém konci Spustit buňku knoflík

nebo zadáním shift-return , které oba vrátí následující:

Chcete-li zobrazit skutečná data z CSV, připojte ke kódu .text() a spusťte jej, abyste viděli výše uvedená data takto:

FileAttachment("tswiftlyrics.csv").text()


Můžete také vidět, že do této buňky byl importován soubor, protože vpravo je symbol souboru. Vidíme, že data zahrnují interpreta každé skladby (Taylor Swift), název alba, název skladby, číslo skladby na albu, text, řádek, na kterém je text, a rok, kdy skladba vyšla.

Nyní klikněte na znaménko plus nalevo od buňky a vložte novou buňku, která bude obsahovat komentář. Můžeme to udělat pomocí markdown:

md`#### Require d3`

Chcete-li vyžadovat D3.js, vložte novou buňku a přidejte následující.

d3 = {
  const d3 = require("d3-dsv@1", "d3@5","d3-scale@3","d3-scale-chromatic@1", "d3-shape@1", "d3-array@2")
  return d3
}

V Observable noteboocích nemůžete require jakýkoli balíček npm:můžete použít pouze nástroje, které odhalují své moduly prostřednictvím UMD nebo AMD. Obvykle, pokud můžete zahrnout modul z unpkg.com přes CDN na webovou stránku, můžete jej použít v Observable.

Nyní procházíme soubor CSV a voláme csvParse analyzovat vstupní řetězec (obsah našeho souboru CSV). To vrátí pole objektů podle analyzovaných řádků.

data = {
  const text = await FileAttachment(<your-imported-taylor-swift-file-name.csv>).text();
  return d3.csvParse(text, ({lyric}) => ({
    lyric: lyric
  }));
}

Pokud spustíte a rozbalíte tuto buňku, uvidíte tento vstup, který obsahuje pouze text ze souboru CSV:

V nové buňce vytvořte prázdné pole, do kterého přidáte slova z textu:

lyrics = []

Do nové buňky přidejte následující, abyste procházeli naším data objekt přidat každý text do lyrics pole.

data.forEach(lyric => lyrics.push(lyric.lyric));

Můžete vidět upravený lyrics objekt v nové buňce:

Vyčistit texty

Observable nám neumožňuje změnit přiřazení proměnných, protože "Pojmenované buňky jsou deklarace, nikoli přiřazení." Pokud byste se pokusili resetovat nebo změnit přiřazení lyrics proměnnou, dostanete tuto chybu, protože názvy buněk musí být jedinečné:

Chcete-li analyzovat nejpoužívanější slova z Taylorových textů, v nové buňce převeďte pole na řetězec a pomocí regulárního výrazu odstraňte neřetězcové znaky.

newLyrics = lyrics.join(' ').replace(/[.,\/#!""'$%\?^&\*;:{}=\-_`~()0-9]/g,"").toLowerCase()

Poté, co vyčistíme texty, odstraníme stopwords z pole textů. Většina z těchto slov byla převzata ze seznamu zastavovacích slov NLTK a ve skutečnosti toho moc neříkají:jsou to jakési "lešení-y". V nové buňce přidejte

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']

Chcete-li tato ignorovaná slova z textu odstranit, přidejte tuto funkci do nové buňky.

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(' '))
}  

Nyní vytvoříme novou proměnnou v nové buňce volající remove_stopwords funkce.

lyrics_no_stopwords = remove_stopwords(newLyrics)

Získejte frekvenci řetězce pro každý text

Chcete-li získat počet výskytů pro každé slovo v textu, přidejte tento kód do nové buňky pomocí [reduce](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce) .

strFrequency = function (stringArr) { //es6 way of getting frequencies of words
  return stringArr.reduce((count, word) => {
        count[word] = (count[word] || 0) + 1;
        return count;
  }, {})
}

Pak tomu říkáme strFrequency funkci a přiřadit výstup nové proměnné obj .

obj = strFrequency(lyrics_no_stopwords.split(' '))

Pokud buňku spustíte, uvidíte něco takového:

Seřaďte naše frekvence slov

Protože se jedná o objekt JavaScriptu, nemůžeme jen volat sort() . Chcete-li seřadit naše frekvence, přidejte tuto funkci do nové buňky, abyste seřadili náš objekt od největší po nejmenší.

sortedObj = Object.fromEntries(
  Object.entries(obj).sort( (a,b) => a[1] - b[1] )    
) 

Spuštění buňky by zobrazilo následující výstup:

Vytvořte novou funkci v nové buňce, která vrátí pouze první x-číslo (v tomto případě 30) položek objektu, upravte objekt tak, aby měl také lyric a freq před každou hodnotu, aby byly hodnoty snadno dostupné.

final = Object.entries(sortedObj).map(([lyric, freq]) => ({lyric, freq})).slice(0,30);

Spuštěním buňky můžete vidět, že final je pole, mírně odlišné od sortedObj výše.

Vytvořte si náš graf

Musíme nastavit některé atributy našeho grafu. V nové buňce přidejte

margin = ({top: 20, right: 0, bottom: 30, left: 40})

následuje další nová buňka s

height = 500

Nyní vytvoříme naše hodnoty x v nové buňce s d3.scaleBand() rozbití naší domény každého textu Taylor Swift z final objekt do rozsahu hodnot, což jsou minimální a maximální rozsahy pásma.

x = d3.scaleBand()
    .domain(final.map(d => d.lyric))
    .rangeRound([margin.left, width - margin.right])
    .padding(0.1)

Naše hodnoty y jsou vytvořeny podobným způsobem v nové buňce:

y = d3.scaleLinear()
    .domain([0, d3.max(final, d => d.freq)])
    .range([height - margin.bottom, margin.top])

Abychom mohli stylizovat a zobrazovat naše osy, musíme je definovat jako funkce, které je převádějí do příslušného umístění podle nastavené orientace. Ve dvou samostatných buňkách obsahuje následující:

xAxis = g => g
    .attr("transform", `translate(0,${height - margin.bottom})`)
    .call(d3.axisBottom(x).tickSizeOuter(0))
yAxis = g => g
    .call(d3.axisLeft(y).ticks(15))
    .call(g => g.select(".domain").remove())

Chcete-li nyní přidat nadpis na osu y, přidejte do nové buňky následující kód.

yTitle = g => g.append("text")
    .attr("font-family", "sans-serif")
    .attr("font-size", 10)
    .attr("y", 10)
    .text("Frequency")

Nyní je nazýváme vytvořením našeho grafu v nové buňce. Vytvoříme objekt SVG pomocí viewBox atribut pro nastavení pozice a rozměru. Poté přidáme g prvek (který není jedinečný pro D3.js, protože se používá ke seskupování tvarů SVG) vytváření obdélníků z našich dat textu a nastavení textu jako hodnoty x pro každý obdélník a frekvence textu jako hodnoty y pro každý obdélník. Nastavíme také některé atributy stylu a pak zavoláme xAxis , yAxis a yTitle .

{
  const svg = d3.create("svg")
      .attr("viewBox", [0, 0, width, height]);

  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)

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

  svg.call(yTitle);

  return svg.node();

Spuštění této buňky by mělo vygenerovat tento graf. Tada!

Přidat interaktivitu do pruhového grafu

Pod yAxis přidejte novou buňku, která bude obsahovat popisek, který se zobrazí, když uživatel najede kurzorem na obdélník. Nastavili jsme různé prvky stylu, aby byly hexadecimální barvy související s alby Taylor Swift a dalšími vlastnostmi podobnými CSS.

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"); 

Nyní upravte buňku grafu dříve přidáním následujícího kódu popisku. Na mouseover Pokud se zobrazí nápověda a zobrazí slovo s tím, jak často se slovo objevuje v písních Taylor Swift. Když se myš pohybuje při najetí na obdélník ve sloupcovém grafu, pohybuje se i nápověda a její text.

{
  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();
}

Měl bys vidět:

Tada! Nyní, když najedete na pruh, uvidíte přesnou hodnotu. Pokud chcete vidět úplný kód, můžete si pohrát s publikovaným poznámkovým blokem Observable zde.

Co bude dál s vizualizacemi dat?

K vizualizaci dat v JavaScriptu nemusíte používat poznámkové bloky Observable – můžete také použít D3.js a další knihovny vizualizace dat ve svém preferovaném textovém editoru a poté je zobrazit na webové stránce. Observable je však užitečný nástroj, který vám umožní rychle zobrazit výstup kódu a může pomoci usnadnit vytváření a sdílení ukázek. Můžete použít jiné datové sady i různé datové sady zde na Kaggle a nezapomeňte si položit těchto 5 otázek, než začnete s datovou sadou pracovat. Dejte mi online vědět, co stavíte!