Closed Captioning Closed captioning available on our YouTube channel

How to code an interactive shiny app to search Twitter: Do More With R bonus video

InfoWorld | Jan 25, 2020

Learn how to turn code from Episode 41 into an interactive shiny Web app.

Copyright © 2020 IDG Communications, Inc.

Hi I’m Sharon Machlis at IDG here with a bonus Do More With R video: create an interactive Shiny Web app to track tweets by a hashtag.
The main episode showed how to search for tweets, import them into R, and create a sortable, filterable table. This video takes that code further, with additional search and filter capabilities. Let’s get started!
Here in RStudio is the code from the main episode. If you want to go over that, head to episode 41 on YouTube or InfoWorld.
Now let’s turn it into a local interactive shiny app with even more filtering possibilities.
First, I’ll create a new shiny app in a new subdirectory in RStudio by going to File > New File > New Shiny Web Application. I’ll call my app TwitterSearch but you can call yours anything. You’ll get a default app.R file.
The ui portion of a shiny app is the user interface, or front-end HTML page that the user – in this case you – interacts with. The server portion is the back-end R code that does all the computing to make a user’s request actually work.
I typically first delete most of the comments in the default app.R file, change the title, and load all the packages I need.

Next, I’ll add the code that searches for tweets, imports them to R, and wrangles a version to display in a table – but I’m going to shiny-fy it a bit.
I know I’m going to want the URL html-formatting function I made in the main episode. I’ll copy that URL function into the top of my app.R file, before all the interactive code. (I could also put it in a separate helper file and source that file.) Top of my app now looks like this:
Next, I’ll add code to create the initial twitter data frame from my search query. That goes in the app.R’s server section. Since that data frame will change and update depending on what the user requests, I need to make it a reactive value.
So far, there are two items that the user can change: the hashtag search query and the number of tweets to return. Instead of hard coding the values at the top of the file, I want to add those as inputs users can change.
That means adding two user input fields in the app.R ui section: hashtag_to_search and num_tweets_to_download. I’ll create a text box for entering a hashtag and numerical input box or slider for entering the number of tweets to request.
For number of tweets, I’ll start off by keeping the slider that came in the default app.R. However, I’ll change its id to num_tweets_to_download, the label that the user sees to “Number of tweets to download:”, the min value to 100, the max value to 18000, the default value to 200, and step (how much is added or subtracted with each slight move of the slider) to 100.
I’m also going to delete everything in the server section between the brackets since the default app won’t work anymore now that I’m changing inputs.
If I run the app by clicking the Run App button at the top right of my RStudio pane I can see my slider - although it doesn’t do anything yet.
If can be a little difficult to get the exact value you want when moving a slider. I’m going to change that slider to a numericInput() box:
That gives me a box you can type into instead of a slider.
Next I’m going to add a text input box for the hashtag query with shiny’s textInput() function. I’ll set the box’s inputId to be hashtag_to_search, the label as “Hashtag to search:” and the default value as “#rstudioconf”. My sidebar panel code now looks like this:
Notice that since I’m adding a second input argument to the sidebar panel, I needed a comma after the first input. Getting parentheses and commas correct can be a challenge when coding shiny apps. Creating inputs and outputs one by one and running the code after each addition can help make it easier to spot problems.
Let me run this updated code
The basic sidebar is finished, but I need one more input in my ui to tell shiny where I want my tweet table to display. I’ll put that placeholder in the main panel. The default app’s main panel has plotOutput("distPlot"), which tell shiny to save space for a plot in the main part of the page. I want a reactable table there, so I’ll change plotOutput() to reactableOutput(“tweet_table”). If I click to run my app now, nothing changed. But we’re almost there.
It’s finally time to actually get and display the tweets. Just as with the original code, I’ll use rtweet’s search_tweet() function to search for tweets and store results in tweets_df (which will contain 90 columns). I’ll then create a tweets_table_data data frame from my results, formatted to display in a table; and code the table. All this server logic has to inside the server portion of the app.R file.
I can re-use my original code with a few modifications. The most important ones: 1. Any variable that changes based on user input needs to be a reactive value, not a conventional R object. I have to create and handle them in slightly different ways than a regular variable. But happily, the tweaks are minor. 2. Any time I need the value of a user input, I have to refer to it as input dollar sign variable name and not just variable name.
Let’s see how that works.
To turn a “regular” value into a reactive one, use shiny’s reactive({}) function.

I only needed to change the first three lines of the tweet_table_data code, and add closing braces and parentheses at the end.
The first line creates an object that can change based on user input. The second line tells shiny not to start any calculations for tweet_table_data until a tweet_df() data frame exists. Without that, my app might throw an error if it tries to run calculations on a data frame that doesn’t exist. Note, too, it’s tweet_df PARENTHESES and not tweet_df since that data frame is reactive.
Finally, the table code. It needs three minor changes:
Since the table is a visualization, shiny needs to know where to put it and what it is. I’ll store the table in a variable called output dollar sign tweet_table. That connects it with the reactableOutput("tweet_table") placeholder in the user interface.
I’ll also use the renderReactable() function so shiny knows what kind of visualization it’s creating. The code should require the presence of the tweet_table_data data frame, or the app might throw an error trying to generate a table from data that doesn’t exist.
2. Code also needs to refer to tweet_table_data with parentheses since it’s reactive.
I’d like to change how the app reacts if I change the default hashtag or number of tweets to request. By default, shiny will try to update the data as I’m typing. A lot of times, that’s cool and useful behavior. But this isn’t one of those. I don’t want the app to make a call to the Twitter API every time I type a letter or number! I’ll risk bumping into my API limit if I have a long hashtag.
I don’t want my app making a request to the Twitter API until I click a “Get data” button. RStudio recommends an “Action button” for this. As with most things in shiny, that involves in two parts: the ui and the server.
For the ui, I can add an action button with the actionButton() function.
Let me add this to the UI:
To make that button do something – or, more accurately, stop the app from doing something until all the input information is ready – I need to change the tweet_df() object from a reactive value to a reactive event. That means it doesn’t change its value based on a value a user enters but an action a user takes (like a button click).
Note the comma after input$my_button_id! I’ve spent a fair amount of time trying to track down shiny errors because I forget a comma after the first argument of a reactive function.
And I need to change the tweet_df definition in my server code
If I run the app now, nothing should happen until I click the “Get data” button.
There are a lot more enhancements I can make to this app, such as filter by date range, add a download data button. I cover those in the article associated with this video.
But that’s all for this episode, thanks for watching! For more R tips, head to the Do More With R page at bit-dot-ly slash do more with R, all lowercase except for the R. You can also find the Do More With R playlist on the YouTube IDG Tech Talk channel -- where you can subscribe so you never miss an episode. Hope to see you next time!

Featured videos from