Lyrics WordCloud

How do I create a poster representing a favorite song?

Getting Started: Lyrics

First, note that if you want text this is called a String. We make a string by including quotation marks around the text.

"This is some text."

Evaluate the following and see that the Head of this object is String.

Head["This is some text."]

See what happens if you do not have the quotation marks. If you evaluate this code, each word is treated as a variable and it gets alphabetized as if you are multiplying those variables together.

This is some text

Now, find the lyrics to a favorite song on the internet. Copy/Paste the lyrics into your notebook, but be sure to include quotation marks around the text to make it a String. In the front, give your String a variable name (such as lyrics as below). At the end, after the second quotation mark, include a semicolon ; so that the text does not appear as output when you evaluate the cell.

lyrics="Ah, yeah, ah, yeah
I got this feelin' inside my bones
It goes electric, wavy when I turn it on
All through my city, all through my home
We're flyin' up, no ceilin', when we in our zone

I got that sunshine in my pocket
Got that good soul in my feet
I feel that hot blood in my body when it drops (ooh)
I can't take my eyes up off it, movin' so phenomenally
Room on lock, the way we rock it, so don't stop

And under the lights when everything goes
Nowhere to hide when I'm gettin' you close
When we move, well, you already know
So just imagine, just imagine, just imagine

Nothin' I can see but you when you dance, dance, dance
Feel a good, good creepin' up on you ?????
So just dance, dance, dance, come on
All those things I shouldn't do
But you dance, dance, dance
And ain't nobody leavin' soon, so keep dancin'
I can't stop the feelin'
So just dance, dance, dance
I can't stop the feelin'
So just dance, dance, dance, come on

Ooh, it's something magical
It's in the air, it's in my blood, it's rushin' on (rushin' on)
I don't need no reason, don't need control (need control)
I fly so high, no ceiling, when I'm in my zone

'Cause I got that sunshine in my pocket
Got that good soul in my feet
I feel that hot blood in my body when it drops (ooh)
I can't take my eyes up off it, moving so phenomenally
Room on lock, the way we rock it, so don't stop (stop, stop, stop)

Under the lights when everything goes
Nowhere to hide when I'm gettin' you close
When we move, well, you already know
So just imagine, just imagine, just imagine

Nothing I can see but you when you dance, dance, dance
Feel a good, good, creepin' up on you?????
So just dance, dance, dance, come on
All those things I shouldn't do
But you dance, dance, dance
And ain't nobody leavin' soon, so keep dancin'
I can't stop the feelin'
So just dance, dance, dance
I can't stop the feelin'
So just dance, dance, dance
I can't stop the feelin'
So just dance, dance, dance
I can't stop the feelin' (yeah)
So keep dancin', come on

Oh, yeah, yeah
I can't stop the, I can't stop the
I can't stop the, I can't stop the
I can't stop the feelin'

Nothin' I can see but you when you dance, dance, dance (I can't stop the feelin')
Feel the good, good, creepin' up on you
So just dance, dance, dance, come on (I can't stop the feelin')
All those things I shouldn't do
But you dance, dance, dance (dance, dance, dance) (I can't stop the feelin')
And ain't nobody leavin' soon, so keep dancin' 

Everybody sing (I can't stop the feelin')
Got this feeling in my body (I can't stop the feelin')
Got this feeling in my body (I can't stop the feelin')
Wanna see you move your body (I can't stop the feelin')
Got this feelin' in my body
Break it down
Got this feelin' in my body (ah)
Can't stop the feelin'
Got this feelin' in my body, come on (ooh)";

We can easily make a word cloud with just this. Notice how words used more often are centered and have larger fonts than the words that appear less often in the text. WordCloud also omits words like “the” and “of” and “and.”

WordCloud[lyrics]

Preparing an Image

Getting an Image

Find an image related to the song on the internet. Try to find something that has a well defined silhouette and a white background, if possible. You may even want to include “silhouette” in the terms for your image search.

Try using copy/paste to get the image into your notebook. If that does not work, then save the image to your computer and use Import to bring it into your notebook. (Hint if you need to use Import: After typing Import[ there is a double down arrow in the blue popup suggestion that has “File Browser” as an option at the bottom of the list. Click on that and navigate to your saved image. Or, use Insert >> File Path... in the menu at the top of the notebook.)

Import["C:\\Users\\abby.brown\\Desktop\\MyImage.png"]

Type a variable name for your image in front of it with = and use a semicolon ; again to prevent new output. Evaluate this cell.

poppy=;

Resizing Image

If your image is too big or too small, this won’t work well. Let’s see what the dimensions are using ImageDimensions. The result lists width and height in pixels. (If one of your dimensions is less than 400 pixels, you may want a new picture or modify everything else below this point to have numbers smaller than what I use in this example.)

ImageDimensions[poppy]

We want the largest dimension to be 400 pixels. In my example, Princess Poppy is taller than she is wide, so I will set the height to be 400 while keeping the width proportioned correctly. Give this image a new name.

poppy400=ImageResize[poppy,{Automatic,400}]

Aside: Note that if you only specify one number for pixels (rather than a list), that number will be applied to the width while the height will be adjusted accordingly to maintain the same proportions. So, in my example, the code below would actually make the image bigger.

ImageResize[poppy,400]

Getting a White Background

If your image does not have a white background, you could try “RemoveBackground.”

RemoveBackground[]

To improve the background removal, try some of options within the function. See the Documentation Center for additional options.

RemoveBackground[,{Black,0.001}]

Creating More Whitespace

Our final product will be 500 x 500 pixels. Create an image of white using an empty Graphics box as below.

whitebox=Image[Graphics[{},ImageSize->{500,500}]]

Using ImageCompose we can put the images together to form a new image that has more whitespace. Give this a new name.

newpoppy=ImageCompose[whitebox,poppy400]

Binarize will convert the image to black and white (just black and white, no shades of gray).

Binarize[newpoppy]

A value in the second argument (a number between 0 and 1) will adjust how refined it is. Try to get the whole image to be black with only the background as white.

Binarize[newpoppy,0.98]

Putting it all Together

Word Cloud in a Shape

To get the word cloud to follow your shape, include the binarized image (use copy/paste unless you named it again) as the second argument to WordCloud. Note that the words will be in the white area.

WordCloud[lyrics,]

Make the word could the desired dimensions using ImageSize. Name this result.

WordCloud[lyrics,,ImageSize->{500,500}]

Turn the word cloud into an Image and name it with a variable.

wc=Image[WordCloud[lyrics,,ImageSize->{500,500}]]

All Together Now

ImageMultiply[wc,newpoppy]

If there is a lot of additional whitespace, you can crop it using the image editing tools that appear when you click on the image. Or try going through the steps again with different dimensions. The image below is a cropped version of the one above.

Option: Putting all the code together

The following is all of the steps of the above put together. Notice the addition of naming the binarized image and the use of semicolons ; after each line to suppress the output until the last line that does not have one.

poppy=;
poppy400=ImageResize[poppy,{Automatic,400}];
whitebox=Image[Graphics[{},ImageSize->{500,500}]];
newpoppy=ImageCompose[whitebox,poppy400];
bpoppy=Binarize[newpoppy,0.98];
wc=Image[WordCloud[lyrics,bpoppy,ImageSize->{500,500}]];ImageMultiply[wc,newpoppy]

Option: Image not in the middle

On the step where the image is composed with the white box, you can place the image somewhere other than centered. The coordinates are pixel numbers {width, height) measured from the bottom left corner. Click on the image to see the box after evaluating.

newpoppy=ImageCompose[whitebox,poppy400,{100,250}]

This is incorporated into the overall code below, but you could retrace your steps eariler too.

poppy=;
poppy400=ImageResize[poppy,{Automatic,400}];
whitebox=Image[Graphics[{},ImageSize->{500,500}]];
newpoppy=ImageCompose[whitebox,poppy400,{100,250}];
bpoppy=Binarize[newpoppy,0.98];
wc=Image[WordCloud[lyrics,bpoppy,ImageSize->{500,500}]];ImageMultiply[wc,newpoppy]

Option: Include All Words or Choosing Words

WordCloud[lyrics]

Notice that "can't" is missing from the word cloud and that word is a significant part of the song.

How do we get "can't" back in without having to include all of the other little words too?

WordCloud automatically deletes “stopwords” from the text when making a word cloud. There is a built-in list of standard stopwords. However, to have all of the words included, we can turn the lyrics into a list of words and then do WordCloud without it eliminating anything.

TextWords[lyrics]

WordCloud[TextWords[lyrics]]

Compare this word cloud to the standard ones above.

Grid[{
{"Original","All Words"},
{WordCloud[lyrics,ImageSize->Medium],WordCloud[TextWords[lyrics],ImageSize->Medium]}
},BaseStyle->20]

When all words are included, the “the” is rather large, so maybe we want to eliminate just that.

WordCloud[DeleteCases[TextWords[lyrics],"the"]]

If we want to eliminate additional words we list them as alternatives using | to separate them.

WordCloud[DeleteCases[TextWords[lyrics],"the"|"I"|"a"|"so"]]

If we want to ignore capitalization (notice “So” in this example above), we can use ToLowerCase.

WordCloud[DeleteCases[TextWords[ToLowerCase[lyrics]],"the"|"I"|"a"|"so"]]

I don’t know what all of the stopwords are, but we can find the stopwords in our set of lyrics.

First, delete the stopwords within the list of words.

DeleteStopwords[TextWords[lyrics]]

Now, find words that are in the original lyrics that are not in the list above (the lyrics without stopwords) using Complement.

Complement[TextWords[lyrics],DeleteStopwords[TextWords[lyrics]]]

Rather than individually deleting all of these words that we still don’t want, with a little work we can set it up to say which of the stopwords we do want to keep.

keepwords={"can't","something","nothing","everything","under"};
lyricslist=TextWords[ToLowerCase[lyrics]];
editedlyrics=DeleteCases[lyricslist,
Apply[Alternatives,DeleteCases[Complement[lyricslist,DeleteStopwords[lyricslist]],
Apply[Alternatives,keepwords]]]]

Let’s see what this looks like.

WordCloud[editedlyrics]

Related Idea:

Are some of the stopwords important to keep?
Maybe Tally can help answer this.

Tally[TextWords[ToLowerCase[lyrics]]]

Sort[Tally[TextWords[ToLowerCase[lyrics]]]]

ReverseSort[Tally[TextWords[ToLowerCase[lyrics]]],#1[[2]]<#2[[2]]&]

Another Question

Why is “got” not in the list of stopwords?
Maybe we want to get rid of that too.

keepwords={"can't","something","nothing","everything","under"};
lyricslist=TextWords[ToLowerCase[lyrics]];
editedlyrics=DeleteCases[lyricslist,
Apply[Alternatives,
Join[
DeleteCases[Complement[lyricslist,DeleteStopwords[lyricslist]],Apply[Alternatives,keepwords]],
{"got"}]
]
]

Let’s see it now.

WordCloud[editedlyrics]

And just because I want to see it all together . . .

poppy=;
keepwords={"can't","something","nothing","everything","under"};
lyricslist=TextWords[ToLowerCase[lyrics]];
editedlyrics=DeleteCases[lyricslist,
Apply[Alternatives,
Join[
DeleteCases[Complement[lyricslist,DeleteStopwords[lyricslist]],Apply[Alternatives,keepwords]],
{"got"}]
]
];
whitebox=Image[Graphics[{},ImageSize->{500,500}]];
newpoppy=ImageCompose[whitebox,poppy,{100,250}];
bpoppy=Binarize[newpoppy,0.98];
wc=Image[WordCloud[editedlyrics,bpoppy,ImageSize->{500,500}]];ImageMultiply[wc,newpoppy]

Option: Changing Colors of Words

WordCloud[lyrics]

Try a PlotTheme. These will use different default colors.

WordCloud[lyrics,PlotTheme->"Classic"]

WordCloud[lyrics,PlotTheme->"Monochrome"]

WordCloud[lyrics,PlotTheme->"DarkColor"]

One color or multiple colors can be assigned using ColorFunction.

WordCloud[lyrics,ColorFunction->Red]

WordCloud[lyrics,ColorFunction->{Red,Blue,Green}]

ColorFunction can also include a Blend of two colors.

WordCloud[lyrics,ColorFunction->(Blend[{Purple,Red},#]&)]

See Documentation Center for more options: WordCloud >> Examples >> Options >> ColorFunction and ColorFunctionScaling

Can I use colors related to the image?

I know that the Wolfram Language can analyze an image and get numerical information about colors since I have seen this: ChromaticityPlot. (By the way, try ChromaticityPlot3D.)

ChromaticityPlot[poppy]

I also know that ColorQuantize will reduce an image to a limited number of colors by averaging the colors within the image. For example, if you use 1 as the second argument, the whole thing is the average color. If you use 2 for the second argument, the image is drawn with only two colors.

ColorQuantize[poppy,7]

Ah ha! In the Documentation Center, under related functions (“See Also”) for ColorQuantize, I found a function called DominantColors. Let’s see what that does.

DominantColors[poppy]

Perfect!

WordCloud[lyrics,ColorFunction->DominantColors[poppy]]

Well, not so perfect. We don’t want that nearly white color in there. (If you hover over the swatch, you will see that the tooltip has RGB values close to, but not exactly, 1 so it’s not quite white.)

DominantColors[poppy]

I could get rid of the “white” one by selecting and deleting it then using copy/paste, but I’d rather use code.

Method 1: Sort the list and “white” is last, so I can then take the first 8 elements in the list. This also puts the greenish one first and that will be the color of the big “dance” so that may be nice.

Sort[{,,,,,,,,}]

Take[Sort[{,,,,,,,,}],8]

WordCloud[lyrics,ColorFunction->{,,,,,,,}]

Method 2: Don’t use Sort, but use Take with a negative value to grab the last 8 elements of the list.

Take[DominantColors[poppy],-8]

WordCloud[lyrics,ColorFunction->{,,,,,,,}]

Method 3: Note that if you know the white one is at the end, but the list of colors is long and you don’t want to count them, you could do something like this. (I’m using Sort since I like the green one for “dance.”)

Take[Sort[DominantColors[poppy]],Length[DominantColors[poppy]]-1]

If we don’t want it calculating DominantColors twice, we could introduce another variable.

Take[Sort[dc=DominantColors[poppy]],Length[dc]-1]

I will use this, so maybe I can change images easily. I’m assuming that “white” will sort to be the first element each time, even with another image.

WordCloud[lyrics,ColorFunction->Take[Sort[dc=DominantColors[poppy]],Length[dc]-1]]

All together again . . .

poppy=;
keepwords={"can't","something","nothing","everything","under"};
lyricslist=TextWords[ToLowerCase[lyrics]];
editedlyrics=DeleteCases[lyricslist,
Apply[Alternatives,
Join[
DeleteCases[Complement[lyricslist,DeleteStopwords[lyricslist]],Apply[Alternatives,keepwords]],
{"got"}]
]
];
whitebox=Image[Graphics[{},ImageSize->{500,500}]];
newpoppy=ImageCompose[whitebox,poppy,{100,250}];
bpoppy=Binarize[newpoppy,0.98];
wc=Image[WordCloud[editedlyrics,bpoppy,ImageSize->{500,500},ColorFunction->Take[Sort[dc=DominantColors[poppy]],Length[dc]-1]]];ImageMultiply[wc,newpoppy]

Option: WordOrientation

And now for more fun . . .

WordCloud[lyrics]

Another option for WordCloud is WordOrientation. Note that each time you evaluate the below you get a different result.

WordCloud[lyrics,WordOrientation->"Random"]

You can set a specific angle.

WordCloud[lyrics,WordOrientation->Pi/4]

If you don’t know radians yet (you should!), you can use degrees like this.

WordCloud[lyrics,WordOrientation->45Degree]

You can give it a choice of angles in a list. Again, it will choose randomly.

WordCloud[lyrics,WordOrientation->{{Pi/4,-Pi/4}}]

In the above, try changing 3π/4 to -π/4 or 5π/4 and note the differences.

WordCloud[lyrics,WordOrientation->{{0,Pi,Pi/2,3Pi/2}}]

Note: I have not learned if there is a way to give it a range of angles among which to set random values. Let me know if you figure that out. The closest idea I have is something like this, but that’s probably good enough.

WordCloud[lyrics,WordOrientation->{Range[0,Pi/2,Pi/20]}]

And finally, because at some point I have to stop . . .

poppy=;
keepwords={"can't","something","nothing","everything","under"};
lyricslist=TextWords[ToLowerCase[lyrics]];
editedlyrics=DeleteCases[lyricslist,
Apply[Alternatives,
Join[
DeleteCases[Complement[lyricslist,DeleteStopwords[lyricslist]],Apply[Alternatives,keepwords]],
{"got"}]
]
];
whitebox=Image[Graphics[{},ImageSize->{500,500}]];
newpoppy=ImageCompose[whitebox,poppy,{100,250}];
bpoppy=Binarize[newpoppy,0.98];
wc=Image[WordCloud[editedlyrics,bpoppy,ImageSize->{500,500},
ColorFunction->Take[Sort[dc=DominantColors[poppy]],Length[dc]-1],
WordOrientation->{{0,0,Pi/6,-Pi/6}}]];ImageMultiply[wc,newpoppy]

Okay, so I couldn’t resist one more . . .

poppy=;branch=;
keepwords={"can't","something","nothing","everything","under"};
lyricslist=TextWords[ToLowerCase[lyrics]];
editedlyrics=DeleteCases[lyricslist,
Apply[Alternatives,
Join[DeleteCases[Complement[lyricslist,DeleteStopwords[lyricslist]],Apply[Alternatives,keepwords]],{"got"}]
]];
whitebox=Image[Graphics[{},ImageSize->500]];
newpoppy=ImageCompose[ImageCompose[whitebox,poppy,{150,250}],branch,{295,210}];
bpoppy=Binarize[newpoppy,0.98];
wc=Image[WordCloud[editedlyrics,bpoppy,ImageSize->500,
ColorFunction->Take[Sort[dc=DominantColors[poppy]],Length[dc]-1],
WordOrientation->{{0,0,Pi/6,-Pi/6}}]];ImageMultiply[wc,newpoppy]

Lyrics and Image Credits

Justin Timberlake “Can’t Stop the Feeling!” lyrics found through Google Search. Songwriters: Justin R. Timberlake / Martin Karl Sandberg / Johan Karl Schuster, Can’t Stop the Feeling! lyrics © Universal Music Publishing Group, Kobalt Music Publishing Ltd.

Princess Poppy and Branch images were found through Google searches. Months later I cannot find the exact web pages where I copied these from. Images likely © DreamWorks Animation LLC. https://www.dreamworksanimation.com

Abby Brown
www.abbymath.com
CT@TP: Computational Thinking at Torrey Pines High School
December 2017