Day 23 of the Anvil Advent Calendar

Build a web app every day until Christmas, with nothing but Python!

D3 applied to carols

For those of us who can’t sing, how should we occupy ourselves while our friends are out carolling? You guessed it - data visualisation! Let’s take those carols, and draw some word clouds of the lyrics. Pro tip: This app even works on songs that aren’t Christmas carols! 1

https://christmas-cloud.anvil.app

We’re going to use the D3 visualisation library, and the third-party d3-cloud layout to take care of the heavy lifting for us. All we need to do is load the libraries in our Anvil app, write a small amount of JavaScript to drive them, then build a simple web UI.

This app demonstrates writing Custom Components, as well as depending on third-party JavaScript libraries. Check out the source code here:

As you’ll see from the source, the app has three main parts:

  • The main form, which contains a text box to enter lyrics, and my custom WordCloud component
  • The WordCloud component, which has a custom text property we can use to set the source text for the cloud
  • The word_cloud.html asset, which provides the actual HTML and JS of our custom component. This is where we interface with the D3 libraries.

We calculate the word sizes manually in Python, using the built-in Counter class to get frequencies:

def get_word_sizes(words):
  if len(words) > 0:
    word_counts = Counter(words)
    
    biggest_word, highest_count = word_counts.most_common(1)[0]
    highest_count = max(1, highest_count)

    words = [{"text": text, "value": count/(highest_count/2.0)} for text,count in word_counts.items()]
    
    return words
  else:
    return []

When we’re done, we can call our JS update function directly from Python like so:

    self.call_js("update", words)

And that’s really all there is to it! Check out the code below, or just play with the app.


  1. And possibly even on text that isn’t song lyrics in any form, but I haven’t tried that. Generalise at your peril. ↩︎


Give the Gift of Python

Share this post: