An improved word-cloud generator with R
In Corpus Linguistics and Statistics with R, I showed how to make a word cloud from a text file (Section 6.3). A word cloud is a user-friendly way of representing a frequency list graphically. Not the most rigorous analytical tool in the corpus linguist’s kit, admittedly, but sometimes colleagues and students just want something that looks good on a slide and does not require a forty-minute explanation of log-likelihood ratios.
I originally shared a basic Shiny app for this. I have since updated it considerably, and the new version is what I am sharing here. If the old version was a bicycle, this one is a bicycle with gears. And mudguards. And a bell.

Shiny 101
(Skip this section if you’ve been here before.)
Shiny is a web application framework built on top of R. It lets you wrap your R code in a browser-based interface without knowing a line of HTML or JavaScript — which is fortunate, because knowing a line of HTML or JavaScript is rarely sufficient anyway.
To install the package:
install.packages("shiny")
A Shiny app has two components. The UI defines the layout: buttons, sliders, file upload widgets, and whatever you want the user to see. The server defines the behaviour: what happens when the user clicks something, uploads something, or moves a slider. The two halves are wired together by shinyApp().
Here is the canonical minimal example:
library(shiny)
ui <- fluidPage(
mainPanel(textOutput("hello"))
)
server <- function(input, output) {
output$hello <- reactive({ "Hello, Shiny!" })
}
shinyApp(ui = ui, server = server)
To run any Shiny app saved as a .R file:
library(shiny)
runApp("/path/to/myshinyapp.R")
This opens the app in your default browser. You interact with it there.
The updated word-cloud app
The original app was functional but unforgiving. Upload the wrong file and it crashed without explanation. Use a French or Spanish corpus and it cheerfully removed English stopwords, or none at all. There was no way to save the output. These are not features. They are character flaws, and I have corrected them.
The new version requires a few additional packages beyond shiny, tm, and wordcloud:
install.packages(c("RColorBrewer", "shinyjs", "shinycssloaders"))
Download the app from my Github repo (https://github.com/GuillaumeDesa/wordcloud-generator), save the full script as wordcloudapp.R and load it from R or RStudio with:
runApp("path/to/file/wordcloudapp.R")
What’s new
Language-aware stopword removal. The original app removed English stopwords and asked no questions. The new version lets you choose from English, French, Spanish, and German. If you are working on Zola rather than Melville, this matters.
Proper text cleaning. The pipeline now uses the tm package throughout: lowercase conversion, punctuation removal, number removal, and crucially, stripWhitespace after stopword removal. Without that last step, the tokeniser can produce phantom empty tokens, which is the kind of silent error that makes corpus linguists age prematurely.
UTF-8 encoding. The file is now read with encoding = "UTF-8" specified explicitly. If you have ever watched R silently mangle an é or a ß, you will appreciate why this is not optional.
Error handling. If you upload a corrupted file or something goes wrong during processing, the app now tells you so with a notification rather than dying quietly and leaving you staring at a blank panel wondering what you did wrong.
Colour scheme selector. Four RColorBrewer palettes to choose from: Dark2, Paired, Set1, and Accent. Purely cosmetic, but corpus linguistics does not have to be grey anymore.
Loading spinner. The app now displays a spinner while the word cloud renders. A small thing, but it signals that the app is working rather than frozen, which turns out to be a meaningful distinction for users who have uploaded large files.
Download button. You can now save the word cloud as a PNG directly from the interface. The exported image is 1200×900 pixels at 150 dpi, which is sharp enough for a presentation or a paper appendix.
Controls disabled until upload. Sliders and checkboxes are greyed out until a file is actually loaded. This prevents the app from attempting to process inputs that do not yet exist, and makes the intended workflow obvious: upload first, then configure.
A Quick Demo
Let us use Herman Melville’s Moby Dick again, downloaded from Project Gutenberg and lightly post-processed.
Click Browse, select your .txt file on your computer, and the app gets to work.

Adjust the maximum word count, set a minimum frequency threshold, choose your stopword language and colour scheme, and the cloud updates accordingly.


When you are happy with the result, click Download Word Cloud.
The size of each word is proportional to its frequency in the corpus. Whether that constitutes analysis in any rigorous sense is a question I do not think so. It is, however, an effective way of getting a room full of students or colleagues who know next to nothing about linguistics to engage with the concept of type frequency, and that is worth something.
Licence
This app is shared under a CC BY-NC 4.0 licence. You are welcome to use, adapt, and redistribute it for non-commercial purposes, provided you credit the source.
Have fun, and may your corpora be clean and your encodings consistent.
The text only may be used under licence Creative Commons Attribution Non Commercial 4.0 International. All other elements (illustrations, imported files) are “All rights reserved”, unless otherwise stated.
OpenEdition suggests that you cite this post as follows:
Guillaume Desagulier (April 19, 2026). An improved word-cloud generator with R. Around the word. Retrieved July 24, 2026 from https://doi.org/10.58079/1639z


orcid.org/0000-0003-4895-0788