Package loading:

library(tidyverse)
library(DT)
library(plotly)               # This package does interactive graphs
library(rtweet)               # This package accesses Twitter data
library(lubridate)  

This notebook introduces rtweet, which is a package that accesses data from twitter.

Set up API

This API is the most difficult to obtain because you need to set up a developer account and then log in when you use it.

For instructions on how to get an rtweet API key, go here: https://rtweet.info, and then follow the instructions starting at “API authorization”

It is important that you delete the keys and secrets from this code after you use them. Be sure not to publish them or save them in this notebook.


token <- create_token(app = "rstatsresearchchad",
  consumer_key = "6BRO74AsbbonJz05ZckV8mGxe",
  consumer_secret = "a5D6UM4k75g7p2pXil8LlgIGPBUAMp6aJcPsgF36c8uJyg680Z",
  access_token = "1226201887478706176-jFlIApMTwwVSiVjWWELPfPD7t1nkFC",
  access_secret = "bGIhXZ9aXjdxGMe4xbIEBdXkE3pywoZeRkNeYBJ65I0Z4")

get_token()
<Token>
<oauth_endpoint>
 request:   https://api.twitter.com/oauth/request_token
 authorize: https://api.twitter.com/oauth/authenticate
 access:    https://api.twitter.com/oauth/access_token
<oauth_app> rstatsresearchchad
  key:    6BRO74AsbbonJz05ZckV8mGxe
  secret: <hidden>
<credentials> oauth_token, oauth_token_secret
---

Search for a topic

Search for tweets about a topic. Let’s search for tweets about Nancy Pelosi, the new speaker of the house. The term ‘include_rts = F’ will exclude retweets so we don’t have the same tweet multiple times.

about_pelosi <- search_tweets("pelosi", n = 5000, include_rts = F)

Downloading [=>---------------------------------------]   4%
Downloading [=>---------------------------------------]   6%
Downloading [==>--------------------------------------]   8%
Downloading [===>-------------------------------------]  10%
Downloading [====>------------------------------------]  12%
Downloading [=====>-----------------------------------]  14%
Downloading [======>----------------------------------]  16%
Downloading [======>----------------------------------]  18%
Downloading [=======>---------------------------------]  20%
Downloading [========>--------------------------------]  22%
Downloading [=========>-------------------------------]  24%
Downloading [==========>------------------------------]  26%
Downloading [==========>------------------------------]  28%
Downloading [===========>-----------------------------]  30%
Downloading [============>----------------------------]  32%
Downloading [=============>---------------------------]  34%
Downloading [==============>--------------------------]  36%
Downloading [===============>-------------------------]  38%
Downloading [===============>-------------------------]  40%
Downloading [================>------------------------]  42%
Downloading [=================>-----------------------]  44%
Downloading [==================>----------------------]  46%
Downloading [===================>---------------------]  48%
Downloading [===================>---------------------]  50%
Downloading [====================>--------------------]  52%
Downloading [=====================>-------------------]  54%
Downloading [======================>------------------]  56%
Downloading [=======================>-----------------]  58%
Downloading [========================>----------------]  60%
Downloading [========================>----------------]  62%
Downloading [=========================>---------------]  64%
Downloading [==========================>--------------]  66%
Downloading [===========================>-------------]  68%
Downloading [============================>------------]  70%
Downloading [=============================>-----------]  72%
Downloading [=============================>-----------]  74%
Downloading [==============================>----------]  76%
Downloading [===============================>---------]  78%
Downloading [================================>--------]  80%
Downloading [=================================>-------]  82%
Downloading [=================================>-------]  84%
Downloading [==================================>------]  86%
Downloading [===================================>-----]  88%
Downloading [====================================>----]  90%
Downloading [=====================================>---]  92%
Downloading [======================================>--]  94%
Downloading [======================================>--]  96%
Downloading [=======================================>-]  98%
Downloading [=========================================] 100%

Create a chunk below with glimpse(about_pelosi). Take a moment and look at the data. For each tweet, there is a variety of information, like the text of the tweet, the screen_name of the person who created the tweet, the time and date it was created_at, any hashtags used, etc.

glimpse(about_pelosi)
Observations: 5,000
Variables: 90
$ user_id                 <chr> "1031458594519101440", "1052803560063291393", "757749037344796673", "1113028760272601088", "9…
$ status_id               <chr> "1242254550603456512", "1242254546837143555", "1242254546165891072", "1242254545503293444", "…
$ created_at              <dttm> 2020-03-24 00:58:59, 2020-03-24 00:58:58, 2020-03-24 00:58:58, 2020-03-24 00:58:58, 2020-03-…
$ screen_name             <chr> "MariaReginaHan1", "X62048239", "MissysDapur", "RayT75612993", "JoePetitjean", "frankt_patsfa…
$ text                    <chr> "Reject Pelosi's stuffed pork bill. America can do better. https://t.co/LlsBdvg6zo", "@KarenZ…
$ source                  <chr> "Twitter Web App", "Twitter Web App", "Twitter for iPad", "Twitter Web App", "Twitter for iPh…
$ display_text_width      <dbl> 57, 92, 259, 173, 104, 277, 186, 131, 279, 114, 40, 128, 111, 135, 50, 64, 147, 115, 81, 199,…
$ reply_to_status_id      <chr> NA, "1242107968948240385", "1242246752155119617", "1242247531201007624", "1242135206448050178…
$ reply_to_user_id        <chr> NA, "2182999411", "1078785775666384905", "255275973", "15764644", "812135885328236551", "3106…
$ reply_to_screen_name    <chr> NA, "KarenZacarias6", "mark25916680", "mocitynative", "SpeakerPelosi", "RealSaavedra", "Lilfo…
$ is_quote                <lgl> TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FAL…
$ is_retweet              <lgl> FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FA…
$ favorite_count          <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 3, 0, 0, 0, 0, 0, 0, …
$ retweet_count           <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, …
$ quote_count             <int> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ reply_count             <int> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ hashtags                <list> [NA, NA, NA, NA, NA, NA, <"trump2020", "miserabletrumphater", "pelosi">, NA, "DanCrenshaw", …
$ symbols                 <list> [NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
$ urls_url                <list> ["twitter.com/BreitbartNews/…", NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, "thepoliticalinsider…
$ urls_t.co               <list> ["https://t.co/LlsBdvg6zo", NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, "https://t.co/pr4yneN7XK…
$ urls_expanded_url       <list> ["https://twitter.com/BreitbartNews/status/1242252732213460993", NA, NA, NA, NA, NA, NA, NA,…
$ media_url               <list> [NA, NA, "http://pbs.twimg.com/media/ET1f66qU0AAksTP.jpg", NA, NA, NA, NA, NA, NA, NA, NA, N…
$ media_t.co              <list> [NA, NA, "https://t.co/u6ony1YV3P", NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ media_expanded_url      <list> [NA, NA, "https://twitter.com/MissysDapur/status/1242254546165891072/photo/1", NA, NA, NA, N…
$ media_type              <list> [NA, NA, "photo", NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
$ ext_media_url           <list> [NA, NA, <"http://pbs.twimg.com/media/ET1f66qU0AAksTP.jpg", "http://pbs.twimg.com/media/ET1f…
$ ext_media_t.co          <list> [NA, NA, <"https://t.co/u6ony1YV3P", "https://t.co/u6ony1YV3P">, NA, NA, NA, NA, NA, NA, NA,…
$ ext_media_expanded_url  <list> [NA, NA, <"https://twitter.com/MissysDapur/status/1242254546165891072/photo/1", "https://twi…
$ ext_media_type          <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ mentions_user_id        <list> [NA, <"2182999411", "30354991", "33537967">, "1078785775666384905", <"255275973", "376887039…
$ mentions_screen_name    <list> [NA, <"KarenZacarias6", "KamalaHarris", "amyklobuchar">, "mark25916680", <"mocitynative", "l…
$ lang                    <chr> "en", "en", "en", "en", "en", "en", "en", "en", "en", "en", "en", "en", "en", "en", "en", "en…
$ quoted_status_id        <chr> "1242252732213460993", NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, "12421…
$ quoted_text             <chr> "Unbelievable. https://t.co/wbSzn5yWZQ", NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ quoted_created_at       <dttm> 2020-03-24 00:51:45, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 2020-03…
$ quoted_source           <chr> "SocialFlow", NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, "SocialFlow", N…
$ quoted_favorite_count   <int> 199, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 667, NA, 4035, NA, 515, …
$ quoted_retweet_count    <int> 131, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 436, NA, 2286, NA, 346, …
$ quoted_user_id          <chr> "457984599", NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, "457984599", NA,…
$ quoted_screen_name      <chr> "BreitbartNews", NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, "BreitbartNe…
$ quoted_name             <chr> "Breitbart News", NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, "Breitbart …
$ quoted_followers_count  <int> 1283017, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 1283016, NA, 803853,…
$ quoted_friends_count    <int> 114, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 114, NA, 636, NA, 1159, …
$ quoted_statuses_count   <int> 124279, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 124279, NA, 4439, NA,…
$ quoted_location         <chr> "", NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, "", NA, "United States", …
$ quoted_description      <chr> "News, commentary, and destruction of the political/media establishment.", NA, NA, NA, NA, NA…
$ quoted_verified         <lgl> TRUE, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, TRUE, NA, TRUE, NA, FAL…
$ retweet_status_id       <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ retweet_text            <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ retweet_created_at      <dttm> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ retweet_source          <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ retweet_favorite_count  <int> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ retweet_retweet_count   <int> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ retweet_user_id         <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ retweet_screen_name     <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ retweet_name            <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ retweet_followers_count <int> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ retweet_friends_count   <int> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ retweet_statuses_count  <int> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ retweet_location        <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ retweet_description     <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ retweet_verified        <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ place_url               <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, "https://api.…
$ place_name              <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, "Hendron", NA…
$ place_full_name         <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, "Hendron, KY"…
$ place_type              <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, "city", NA, N…
$ country                 <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, "United State…
$ country_code            <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, "US", NA, NA,…
$ geo_coords              <list> [<NA, NA>, <NA, NA>, <NA, NA>, <NA, NA>, <NA, NA>, <NA, NA>, <NA, NA>, <NA, NA>, <NA, NA>, <…
$ coords_coords           <list> [<NA, NA>, <NA, NA>, <NA, NA>, <NA, NA>, <NA, NA>, <NA, NA>, <NA, NA>, <NA, NA>, <NA, NA>, <…
$ bbox_coords             <list> [<NA, NA, NA, NA, NA, NA, NA, NA>, <NA, NA, NA, NA, NA, NA, NA, NA>, <NA, NA, NA, NA, NA, NA…
$ status_url              <chr> "https://twitter.com/MariaReginaHan1/status/1242254550603456512", "https://twitter.com/X62048…
$ name                    <chr> "Maria Regina Hanson", "Blind Guy McSqueezy (ChineseVirus)", "ChiPin", "Ray T", "Deplorable J…
$ location                <chr> "California, USA", "USA", "United States", "Quakertown, pa", "", "Elizabethtown, KY", "United…
$ description             <chr> "Trump2020. Vote Red Tsunami to retake House and Senate with 2/3 majority. United we stand ag…
$ url                     <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, "https://…
$ protected               <lgl> FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FA…
$ followers_count         <int> 881, 1079, 666, 3176, 1588, 22, 46, 52, 10060, 10, 312, 977, 977, 977, 7, 2096, 4318, 688, 68…
$ friends_count           <int> 1734, 1686, 921, 4091, 3747, 56, 291, 43, 10336, 119, 614, 1440, 1440, 1440, 75, 1563, 4961, …
$ listed_count            <int> 0, 11, 0, 0, 18, 0, 1, 0, 9, 0, 0, 21, 21, 21, 0, 40, 80, 0, 0, 8, 0, 44, 44, 44, 44, 13, 0, …
$ statuses_count          <int> 3668, 26062, 2813, 17156, 68988, 1433, 2206, 769, 63102, 304, 975, 69393, 69393, 69393, 1545,…
$ favourites_count        <int> 4245, 40839, 1634, 5812, 16783, 18405, 3829, 1057, 56680, 120, 4679, 12748, 12748, 12748, 102…
$ account_created_at      <dttm> 2018-08-20 08:31:07, 2018-10-18 06:08:23, 2016-07-26 01:27:03, 2019-04-02 10:41:50, 2009-12-…
$ verified                <lgl> FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FA…
$ profile_url             <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, "https://…
$ profile_expanded_url    <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, "https://…
$ account_lang            <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
$ profile_banner_url      <chr> "https://pbs.twimg.com/profile_banners/1031458594519101440/1536608327", "https://pbs.twimg.co…
$ profile_background_url  <chr> NA, NA, NA, NA, "http://abs.twimg.com/images/themes/theme16/bg.gif", NA, NA, NA, "http://abs.…
$ profile_image_url       <chr> "http://abs.twimg.com/sticky/default_profile_images/default_profile_normal.png", "http://pbs.…

What hashtags are people who are tweeting about Pelosi using?

about_pelosi %>% 
  select(hashtags) %>%                   # Focus on the hashtags
  unnest() %>%                           # Separate multiple hashtags
  mutate(hashtags = tolower(hashtags)) %>%      # make all hashtags lowercase
  count(hashtags, sort=TRUE) %>%                # count how often they appear
  datatable()                                   # create an interactive table
`cols` is now required.
Please use `cols = c(hashtags)`

What are the most popular tweets, as measured by the number of retweets, about Pelosi?

about_pelosi %>% 
  select(text, retweet_count) %>%    
  top_n(25) %>%                       # get the top 25 most popular tweets
  arrange(-retweet_count) %>%         # sort in descending order of popularity
  datatable()
Selecting by retweet_count

Get tweets from an individual

Nancy Pelosi’s twitter account is @SpeakerPelosi We can use rtweet to get recent tweets from Pelosi with get_timeline():

pelosi_tweets <- get_timeline("SpeakerPelosi", n = 5000)

How often does Pelosi tweet?

The variable created_at tells us when the tweet was created. Each observation looks like this: 2018-12-12 12:45:21. It has the date and the time.

We can use the lubridate package to extract elements like the date, the hour, or the day of the week. The code below uses date() to extract the date from created_at:

pelosi_tweets %>% 
  group_by(day = date(created_at)) %>%    # extract the date, group by it
  summarize(tweets_per_day = n())         # count the number of tweets each day

Above, summarize() collects and present the number of tweets each day. If you use summarize() again on those, you can further collect those days together, and get the mean number of tweets per day.

Create a new chunk below, copy-paste the code in the chunk above, and add the following line at the end: summarize(mean(tweets_per_day)). Don’t forget the pipe.

pelosi_tweets %>% 
  group_by(day = date(created_at)) %>%    # extract the date, group by it
  summarize(tweets_per_day = n()) %>% 
  summarize(mean(tweets_per_day))

The above should show how many times per day Pelosi tweets.

We can also graph the number of tweets per day with the following code:

pelosi_tweets %>% 
  mutate(day = date(created_at)) %>% 
  ggplot(aes(x = day)) +
  geom_histogram()

pelosi_tweets %>% 
  mutate(day = date(created_at)) %>% 
  ggplot(aes(x = day)) +
  geom_histogram(binwidth = 7)

This histogram combines days into “bins,” making it difficult to tell how many tweets were created on each day. We can adjust binwidth to 1 for one day, or 7 for a week, for example. Create another histogram below, but in the parentheses of geom_histogram(), put binwidth = and select a size.

Graphing with plotly.

Plotly is a graphing package like ggplot2, but it creates interactive graphs that work great when published on the internet.

To create a graph, it starts with plot_ly() rather than ggplot(). There are a few differences between the packages: You don’t need aes(), but you must put ~ in front of variables like the x and y variables. I like the fact that it uses the standard %>% to connect lines rather than the + that ggplot uses.

For more information about plotly, see the following:

Book: https://plotly-book.cpsievert.me Reference site: https://plot.ly/r/

Here’s how you would re-create the histogram from ggplot above in plotly:

pelosi_tweets %>%
  mutate(day = date(created_at)) %>% 
  plot_ly(x = ~day) %>%                                        
  add_histogram()

Notice that you can hover over the graph to get more information, and you can play with the tools to show lines, zoom in and out, etc.

Copy-paste the code above and then add the following line to create a title: layout(title = “Number of tweets from @SpeakerPelosi”)

pelosi_tweets %>%
  mutate(day = date(created_at)) %>% 
  plot_ly(x = ~day) %>%                                        
  add_histogram() %>% 
  layout(title = "Number of tweets from @SpeakerPelosi")

Time of day of tweets

The hour() function from the lubridate package extracts the hour of the day from a date variable such as created_at. Set pageLength to 24 in datatable - it doesn’t look right in RStudio, but it will when published on a web page.

pelosi_tweets %>% 
  mutate(time = hour(created_at)) %>% 
  count(time) %>% 
  datatable(options = (list(pageLength = 24)), rownames = F)

In this table, 0 = midnight, 1 = 1 AM, etc. Is Pelosi really tweeting that much from midnight to 3 AM? We need to think about the time zone. You can get the time zone of created_at with the lubridate package’s tz().

tz(pelosi_tweets$created_at)
[1] "UTC"

This tells us that the time zone the tweet is in is UTC, Universal Coordinated Time, which is the time in London. That’s not the time zone Pelosi was in, it’s the time zone all tweets all over the world are given. No matter what time it is in your local time zone, the time provided by rtweet is in UTC time.

Pelosi is probably tweeting from Washington DC, which is in the Eastern time zone, called “America/New_York” (see here for a complete listing: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones ). She is from California, and so some of her tweets may be from there or elsewhere where she is not in DC, but let’s assume for simplicity that she is always tweeting from the Eastern time zone.

We can convert the time to a new time zone using with_tz(time, “time_zone”), where “time_zone” is the new time zone.

pelosi_tweets %>% 
  mutate(time = with_tz(created_at, "America/New_York")) %>% 
  mutate(time = hour(time)) %>% 
  count(time) %>% 
  datatable(options = (list(pageLength = 24)), rownames = F)

NA

The table above should make more sense: Not as many tweets in the middle of the night.

Let’s use plotly to create a histogram of the number of tweets at each hour of the day.

pelosi_tweets %>% 
  mutate(time = with_tz(created_at, "America/New_York")) %>%    # convert to Eastern time zone
  mutate(time = hour(time)) %>%                                 # extract the hour
  plot_ly(x = ~time) %>%                                        # create plotly graph
  add_histogram()                                          # make histogram

NA

To complete the graph above, add the following line:

layout(title = “When Does @SpeakerPelosi Tweet?”, xaxis = list(title = “Time of Day (0 = midnight)”), yaxis = list(title = “Number of Tweets”))

pelosi_tweets %>% 
  mutate(time = with_tz(created_at, "America/New_York")) %>%    # convert to Eastern time zone
  mutate(time = hour(time)) %>%                                 # extract the hour
  plot_ly(x = ~time) %>%                                        # create plotly graph
  add_histogram() %>%
    layout(title = "When Does @SpeakerPelosi Tweet?" , 
         xaxis = list(title = "Time of Day (0 = midnight)") ,
         yaxis = list(title = "Number of Tweets"))

NA

Day of week of the tweets

Let’s apply the same technique as above to which days of the week Pelosi tweets. Use wday() to extract the day of the week the tweet was made from created_at. The term ‘label = T’ will cause the names for the days (Sun, Mon, etc.) to be used, rather than numbers.

pelosi_tweets %>% 
  mutate(Day = wday(created_at,           # find the weekday that the tweet was created
                    label = T)) %>%       # use labels (Sun, Mon, etc) rather than numbers
  count(Day) %>%                          # count the number of tweets each day
  datatable(rownames = F)

NA

Using the code above as a starting point, create a histogram with plotly of the number of tweets per weekday, like we did above for the number of tweets each hour.

pelosi_tweets %>% 
  mutate(Day = wday(created_at,           # find the weekday that the tweet was created
                    label = T)) %>%       # use labels (Sun, Mon, etc) rather than numbers
  plot_ly(x = ~Day) %>% 
  add_histogram()

Heat map

Let’s finish with a really cool graph called a heatmap. The following will combine days of the week and hours of the day, and show how often the tweets occur.

pelosi_tweets %>% 
  mutate(day = wday(created_at, label = T)) %>% 
  mutate(hour = hour(with_tz(created_at, "America/New_York"))) %>% 
  plot_ly(x = ~day, y = ~hour) %>% 
  add_histogram2d(nbinsx = 7, nbinsy = 24)

NA

To finalize the graph, add a title and x and y axis labels.

pelosi_tweets %>% 
  mutate(day = wday(created_at, label = T)) %>% 
  mutate(hour = hour(with_tz(created_at, "America/New_York"))) %>% 
  plot_ly(x = ~day, y = ~hour) %>% 
  add_histogram2d(nbinsx = 7, nbinsy = 24) %>% 
  layout(title = "When does @SpeakerPelosi Tweet?",
         xaxis =list(title = "Time of Day (0 = midnight)"),
         yaxis = list(title = "Number of Tweets"))

NA
LS0tCnRpdGxlOiAicnR3ZWV0IHJhbmRhbGwiCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KClBhY2thZ2UgbG9hZGluZzoKCmBgYHtyfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShEVCkKbGlicmFyeShwbG90bHkpICAgICAgICAgICAgICAgIyBUaGlzIHBhY2thZ2UgZG9lcyBpbnRlcmFjdGl2ZSBncmFwaHMKbGlicmFyeShydHdlZXQpICAgICAgICAgICAgICAgIyBUaGlzIHBhY2thZ2UgYWNjZXNzZXMgVHdpdHRlciBkYXRhCmxpYnJhcnkobHVicmlkYXRlKSAgCmBgYAoKVGhpcyBub3RlYm9vayBpbnRyb2R1Y2VzIHJ0d2VldCwgd2hpY2ggaXMgYSBwYWNrYWdlIHRoYXQgYWNjZXNzZXMgZGF0YSBmcm9tIHR3aXR0ZXIuIAoKIyMjIFNldCB1cCBBUEkKClRoaXMgQVBJIGlzIHRoZSBtb3N0IGRpZmZpY3VsdCB0byBvYnRhaW4gYmVjYXVzZSB5b3UgbmVlZCB0byBzZXQgdXAgYSBkZXZlbG9wZXIgYWNjb3VudCBhbmQgdGhlbiBsb2cgaW4gd2hlbiB5b3UgdXNlIGl0LiAKCkZvciBpbnN0cnVjdGlvbnMgb24gaG93IHRvIGdldCBhbiBydHdlZXQgQVBJIGtleSwgZ28gaGVyZTogaHR0cHM6Ly9ydHdlZXQuaW5mbywgYW5kIHRoZW4gZm9sbG93IHRoZSBpbnN0cnVjdGlvbnMgc3RhcnRpbmcgYXQgIkFQSSBhdXRob3JpemF0aW9uIgoKSXQgaXMgaW1wb3J0YW50IHRoYXQgeW91IGRlbGV0ZSB0aGUga2V5cyBhbmQgc2VjcmV0cyBmcm9tIHRoaXMgY29kZSBhZnRlciB5b3UgdXNlIHRoZW0uIEJlIHN1cmUgbm90IHRvIHB1Ymxpc2ggdGhlbSBvciBzYXZlIHRoZW0gaW4gdGhpcyBub3RlYm9vay4gCmBgYHtyfQoKdG9rZW4gPC0gY3JlYXRlX3Rva2VuKGFwcCA9ICJyc3RhdHNyZXNlYXJjaGNoYWQiLAogIGNvbnN1bWVyX2tleSA9ICI2QlJPNzRBc2Jib25KejA1WmNrVjhtR3hlIiwKICBjb25zdW1lcl9zZWNyZXQgPSAiYTVENlVNNGs3NWc3cDJwWGlsOExsZ0lHUEJVQU1wNmFKY1BzZ0YzNmM4dUp5ZzY4MFoiLAogIGFjY2Vzc190b2tlbiA9ICIxMjI2MjAxODg3NDc4NzA2MTc2LWpGbElBcE1Ud3dWU2lWaldXRUxQZlBEN3QxbmtGQyIsCiAgYWNjZXNzX3NlY3JldCA9ICJiR0loWFo5YVhqZHhHTWU0eGJJRUJkWGtFM3B5d29aZVJrTmVZQko2NUkwWjQiKQoKZ2V0X3Rva2VuKCkKCmBgYAoKCgoKIyMjIFNlYXJjaCBmb3IgYSB0b3BpYwoKU2VhcmNoIGZvciB0d2VldHMgYWJvdXQgYSB0b3BpYy4gTGV0J3Mgc2VhcmNoIGZvciB0d2VldHMgYWJvdXQgTmFuY3kgUGVsb3NpLCB0aGUgbmV3IHNwZWFrZXIgb2YgdGhlIGhvdXNlLiBUaGUgdGVybSAnaW5jbHVkZV9ydHMgPSBGJyB3aWxsIGV4Y2x1ZGUgcmV0d2VldHMgc28gd2UgZG9uJ3QgaGF2ZSB0aGUgc2FtZSB0d2VldCBtdWx0aXBsZSB0aW1lcy4KCmBgYHtyfQphYm91dF9wZWxvc2kgPC0gc2VhcmNoX3R3ZWV0cygicGVsb3NpIiwgbiA9IDUwMDAsIGluY2x1ZGVfcnRzID0gRikKYGBgCgoKQ3JlYXRlIGEgY2h1bmsgYmVsb3cgd2l0aCBnbGltcHNlKGFib3V0X3BlbG9zaSkuIFRha2UgYSBtb21lbnQgYW5kIGxvb2sgYXQgdGhlIGRhdGEuIEZvciBlYWNoIHR3ZWV0LCB0aGVyZSBpcyBhIHZhcmlldHkgb2YgaW5mb3JtYXRpb24sIGxpa2UgdGhlICp0ZXh0KiBvZiB0aGUgdHdlZXQsIHRoZSAqc2NyZWVuX25hbWUqIG9mIHRoZSBwZXJzb24gd2hvIGNyZWF0ZWQgdGhlIHR3ZWV0LCB0aGUgdGltZSBhbmQgZGF0ZSBpdCB3YXMgKmNyZWF0ZWRfYXQqLCBhbnkgKmhhc2h0YWdzKiB1c2VkLCBldGMuCgpgYGB7cn0KZ2xpbXBzZShhYm91dF9wZWxvc2kpCmBgYApXaGF0IGhhc2h0YWdzIGFyZSBwZW9wbGUgd2hvIGFyZSB0d2VldGluZyBhYm91dCBQZWxvc2kgdXNpbmc/CgpgYGB7cn0KYWJvdXRfcGVsb3NpICU+JSAKICBzZWxlY3QoaGFzaHRhZ3MpICU+JSAgICAgICAgICAgICAgICAgICAjIEZvY3VzIG9uIHRoZSBoYXNodGFncwogIHVubmVzdCgpICU+JSAgICAgICAgICAgICAgICAgICAgICAgICAgICMgU2VwYXJhdGUgbXVsdGlwbGUgaGFzaHRhZ3MKICBtdXRhdGUoaGFzaHRhZ3MgPSB0b2xvd2VyKGhhc2h0YWdzKSkgJT4lICAgICAgIyBtYWtlIGFsbCBoYXNodGFncyBsb3dlcmNhc2UKICBjb3VudChoYXNodGFncywgc29ydD1UUlVFKSAlPiUgICAgICAgICAgICAgICAgIyBjb3VudCBob3cgb2Z0ZW4gdGhleSBhcHBlYXIKICBkYXRhdGFibGUoKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBjcmVhdGUgYW4gaW50ZXJhY3RpdmUgdGFibGUKYGBgCgpXaGF0IGFyZSB0aGUgbW9zdCBwb3B1bGFyIHR3ZWV0cywgYXMgbWVhc3VyZWQgYnkgdGhlIG51bWJlciBvZiByZXR3ZWV0cywgYWJvdXQgUGVsb3NpPwoKYGBge3J9CmFib3V0X3BlbG9zaSAlPiUgCiAgc2VsZWN0KHRleHQsIHJldHdlZXRfY291bnQpICU+JSAgICAKICB0b3BfbigyNSkgJT4lICAgICAgICAgICAgICAgICAgICAgICAjIGdldCB0aGUgdG9wIDI1IG1vc3QgcG9wdWxhciB0d2VldHMKICBhcnJhbmdlKC1yZXR3ZWV0X2NvdW50KSAlPiUgICAgICAgICAjIHNvcnQgaW4gZGVzY2VuZGluZyBvcmRlciBvZiBwb3B1bGFyaXR5CiAgZGF0YXRhYmxlKCkKYGBgCgoKIyMjIEdldCB0d2VldHMgZnJvbSBhbiBpbmRpdmlkdWFsCgpOYW5jeSBQZWxvc2kncyB0d2l0dGVyIGFjY291bnQgaXMgQFNwZWFrZXJQZWxvc2kgV2UgY2FuIHVzZSBydHdlZXQgdG8gZ2V0IHJlY2VudCB0d2VldHMgZnJvbSBQZWxvc2kgd2l0aCBnZXRfdGltZWxpbmUoKToKCmBgYHtyfQpwZWxvc2lfdHdlZXRzIDwtIGdldF90aW1lbGluZSgiU3BlYWtlclBlbG9zaSIsIG4gPSA1MDAwKQpgYGAKCgoKIyMjIEhvdyBvZnRlbiBkb2VzIFBlbG9zaSB0d2VldD8KClRoZSB2YXJpYWJsZSBjcmVhdGVkX2F0IHRlbGxzIHVzIHdoZW4gdGhlIHR3ZWV0IHdhcyBjcmVhdGVkLiBFYWNoIG9ic2VydmF0aW9uIGxvb2tzIGxpa2UgdGhpczogMjAxOC0xMi0xMiAxMjo0NToyMS4gSXQgaGFzIHRoZSBkYXRlIGFuZCB0aGUgdGltZS4gCgpXZSBjYW4gdXNlIHRoZSBsdWJyaWRhdGUgcGFja2FnZSB0byBleHRyYWN0IGVsZW1lbnRzIGxpa2UgdGhlIGRhdGUsIHRoZSBob3VyLCBvciB0aGUgZGF5IG9mIHRoZSB3ZWVrLiBUaGUgY29kZSBiZWxvdyB1c2VzIGRhdGUoKSB0byBleHRyYWN0IHRoZSBkYXRlIGZyb20gY3JlYXRlZF9hdDoKCmBgYHtyfQpwZWxvc2lfdHdlZXRzICU+JSAKICBncm91cF9ieShkYXkgPSBkYXRlKGNyZWF0ZWRfYXQpKSAlPiUgICAgIyBleHRyYWN0IHRoZSBkYXRlLCBncm91cCBieSBpdAogIHN1bW1hcml6ZSh0d2VldHNfcGVyX2RheSA9IG4oKSkgICAgICAgICAjIGNvdW50IHRoZSBudW1iZXIgb2YgdHdlZXRzIGVhY2ggZGF5CmBgYAoKQWJvdmUsIHN1bW1hcml6ZSgpIGNvbGxlY3RzIGFuZCBwcmVzZW50IHRoZSBudW1iZXIgb2YgdHdlZXRzIGVhY2ggZGF5LiBJZiB5b3UgdXNlIHN1bW1hcml6ZSgpIGFnYWluIG9uIHRob3NlLCB5b3UgY2FuIGZ1cnRoZXIgY29sbGVjdCB0aG9zZSBkYXlzIHRvZ2V0aGVyLCBhbmQgZ2V0IHRoZSBtZWFuIG51bWJlciBvZiB0d2VldHMgcGVyIGRheS4KCkNyZWF0ZSBhIG5ldyBjaHVuayBiZWxvdywgY29weS1wYXN0ZSB0aGUgY29kZSBpbiB0aGUgY2h1bmsgYWJvdmUsIGFuZCBhZGQgdGhlIGZvbGxvd2luZyBsaW5lIGF0IHRoZSBlbmQ6IHN1bW1hcml6ZShtZWFuKHR3ZWV0c19wZXJfZGF5KSkuIERvbid0IGZvcmdldCB0aGUgcGlwZS4KCmBgYHtyfQpwZWxvc2lfdHdlZXRzICU+JSAKICBncm91cF9ieShkYXkgPSBkYXRlKGNyZWF0ZWRfYXQpKSAlPiUgICAgIyBleHRyYWN0IHRoZSBkYXRlLCBncm91cCBieSBpdAogIHN1bW1hcml6ZSh0d2VldHNfcGVyX2RheSA9IG4oKSkgJT4lIAogIHN1bW1hcml6ZShtZWFuKHR3ZWV0c19wZXJfZGF5KSkKYGBgCgoKCgoKCgpUaGUgYWJvdmUgc2hvdWxkIHNob3cgaG93IG1hbnkgdGltZXMgcGVyIGRheSBQZWxvc2kgdHdlZXRzLgoKV2UgY2FuIGFsc28gZ3JhcGggdGhlIG51bWJlciBvZiB0d2VldHMgcGVyIGRheSB3aXRoIHRoZSBmb2xsb3dpbmcgY29kZToKCmBgYHtyfQpwZWxvc2lfdHdlZXRzICU+JSAKICBtdXRhdGUoZGF5ID0gZGF0ZShjcmVhdGVkX2F0KSkgJT4lIAogIGdncGxvdChhZXMoeCA9IGRheSkpICsKICBnZW9tX2hpc3RvZ3JhbSgpCmBgYAoKYGBge3J9CnBlbG9zaV90d2VldHMgJT4lIAogIG11dGF0ZShkYXkgPSBkYXRlKGNyZWF0ZWRfYXQpKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gZGF5KSkgKwogIGdlb21faGlzdG9ncmFtKGJpbndpZHRoID0gNykKYGBgClRoaXMgaGlzdG9ncmFtIGNvbWJpbmVzIGRheXMgaW50byAiYmlucywiIG1ha2luZyBpdCBkaWZmaWN1bHQgdG8gdGVsbCBob3cgbWFueSB0d2VldHMgd2VyZSBjcmVhdGVkIG9uIGVhY2ggZGF5LiBXZSBjYW4gYWRqdXN0IGJpbndpZHRoIHRvIDEgZm9yIG9uZSBkYXksIG9yIDcgZm9yIGEgd2VlaywgZm9yIGV4YW1wbGUuIENyZWF0ZSBhbm90aGVyIGhpc3RvZ3JhbSBiZWxvdywgYnV0IGluIHRoZSBwYXJlbnRoZXNlcyBvZiBnZW9tX2hpc3RvZ3JhbSgpLCBwdXQgYmlud2lkdGggPSBhbmQgc2VsZWN0IGEgc2l6ZS4KCgoKCgoKIyMjIEdyYXBoaW5nIHdpdGggcGxvdGx5LgoKUGxvdGx5IGlzIGEgZ3JhcGhpbmcgcGFja2FnZSBsaWtlIGdncGxvdDIsIGJ1dCBpdCBjcmVhdGVzIGludGVyYWN0aXZlIGdyYXBocyB0aGF0IHdvcmsgZ3JlYXQgd2hlbiBwdWJsaXNoZWQgb24gdGhlIGludGVybmV0LgoKVG8gY3JlYXRlIGEgZ3JhcGgsIGl0IHN0YXJ0cyB3aXRoIHBsb3RfbHkoKSByYXRoZXIgdGhhbiBnZ3Bsb3QoKS4gVGhlcmUgYXJlIGEgZmV3IGRpZmZlcmVuY2VzIGJldHdlZW4gdGhlIHBhY2thZ2VzOiBZb3UgZG9uJ3QgbmVlZCBhZXMoKSwgYnV0IHlvdSBtdXN0IHB1dCB+IGluIGZyb250IG9mIHZhcmlhYmxlcyBsaWtlIHRoZSB4IGFuZCB5IHZhcmlhYmxlcy4gSSBsaWtlIHRoZSBmYWN0IHRoYXQgaXQgdXNlcyB0aGUgc3RhbmRhcmQgJT4lIHRvIGNvbm5lY3QgbGluZXMgcmF0aGVyIHRoYW4gdGhlICsgdGhhdCBnZ3Bsb3QgdXNlcy4KCkZvciBtb3JlIGluZm9ybWF0aW9uIGFib3V0IHBsb3RseSwgc2VlIHRoZSBmb2xsb3dpbmc6CgpCb29rOiBodHRwczovL3Bsb3RseS1ib29rLmNwc2lldmVydC5tZQpSZWZlcmVuY2Ugc2l0ZTogaHR0cHM6Ly9wbG90Lmx5L3IvCgpIZXJlJ3MgaG93IHlvdSB3b3VsZCByZS1jcmVhdGUgdGhlIGhpc3RvZ3JhbSBmcm9tIGdncGxvdCBhYm92ZSBpbiBwbG90bHk6CgpgYGB7cn0KcGVsb3NpX3R3ZWV0cyAlPiUKICBtdXRhdGUoZGF5ID0gZGF0ZShjcmVhdGVkX2F0KSkgJT4lIAogIHBsb3RfbHkoeCA9IH5kYXkpICU+JSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICBhZGRfaGlzdG9ncmFtKCkKYGBgCgoKTm90aWNlIHRoYXQgeW91IGNhbiBob3ZlciBvdmVyIHRoZSBncmFwaCB0byBnZXQgbW9yZSBpbmZvcm1hdGlvbiwgYW5kIHlvdSBjYW4gcGxheSB3aXRoIHRoZSB0b29scyB0byBzaG93IGxpbmVzLCB6b29tIGluIGFuZCBvdXQsIGV0Yy4KCgoKQ29weS1wYXN0ZSB0aGUgY29kZSBhYm92ZSBhbmQgdGhlbiBhZGQgdGhlIGZvbGxvd2luZyBsaW5lIHRvIGNyZWF0ZSBhIHRpdGxlOiBsYXlvdXQodGl0bGUgPSAiTnVtYmVyIG9mIHR3ZWV0cyBmcm9tIEBTcGVha2VyUGVsb3NpIikKCgpgYGB7cn0KcGVsb3NpX3R3ZWV0cyAlPiUKICBtdXRhdGUoZGF5ID0gZGF0ZShjcmVhdGVkX2F0KSkgJT4lIAogIHBsb3RfbHkoeCA9IH5kYXkpICU+JSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICBhZGRfaGlzdG9ncmFtKCkgJT4lIAogIGxheW91dCh0aXRsZSA9ICJOdW1iZXIgb2YgdHdlZXRzIGZyb20gQFNwZWFrZXJQZWxvc2kiKQpgYGAKCgoKCgoKCgojIyMgVGltZSBvZiBkYXkgb2YgdHdlZXRzCgpUaGUgaG91cigpIGZ1bmN0aW9uIGZyb20gdGhlIGx1YnJpZGF0ZSBwYWNrYWdlIGV4dHJhY3RzIHRoZSBob3VyIG9mIHRoZSBkYXkgZnJvbSBhIGRhdGUgdmFyaWFibGUgc3VjaCBhcyBjcmVhdGVkX2F0LiBTZXQgcGFnZUxlbmd0aCB0byAyNCBpbiBkYXRhdGFibGUgLSBpdCBkb2Vzbid0IGxvb2sgcmlnaHQgaW4gUlN0dWRpbywgYnV0IGl0IHdpbGwgd2hlbiBwdWJsaXNoZWQgb24gYSB3ZWIgcGFnZS4KCmBgYHtyfQpwZWxvc2lfdHdlZXRzICU+JSAKICBtdXRhdGUodGltZSA9IGhvdXIoY3JlYXRlZF9hdCkpICU+JSAKICBjb3VudCh0aW1lKSAlPiUgCiAgZGF0YXRhYmxlKG9wdGlvbnMgPSAobGlzdChwYWdlTGVuZ3RoID0gMjQpKSwgcm93bmFtZXMgPSBGKQpgYGAKCkluIHRoaXMgdGFibGUsIDAgPSBtaWRuaWdodCwgMSA9IDEgQU0sIGV0Yy4gSXMgUGVsb3NpIHJlYWxseSB0d2VldGluZyB0aGF0IG11Y2ggZnJvbSBtaWRuaWdodCB0byAzIEFNPyBXZSBuZWVkIHRvIHRoaW5rIGFib3V0IHRoZSB0aW1lIHpvbmUuIFlvdSBjYW4gZ2V0IHRoZSB0aW1lIHpvbmUgb2YgY3JlYXRlZF9hdCB3aXRoIHRoZSBsdWJyaWRhdGUgcGFja2FnZSdzIHR6KCkuCgpgYGB7cn0KdHoocGVsb3NpX3R3ZWV0cyRjcmVhdGVkX2F0KQoKYGBgCgpUaGlzIHRlbGxzIHVzIHRoYXQgdGhlIHRpbWUgem9uZSB0aGUgdHdlZXQgaXMgaW4gaXMgVVRDLCBVbml2ZXJzYWwgQ29vcmRpbmF0ZWQgVGltZSwgd2hpY2ggaXMgdGhlIHRpbWUgaW4gTG9uZG9uLiBUaGF0J3Mgbm90IHRoZSB0aW1lIHpvbmUgUGVsb3NpIHdhcyBpbiwgaXQncyB0aGUgdGltZSB6b25lIGFsbCB0d2VldHMgYWxsIG92ZXIgdGhlIHdvcmxkIGFyZSBnaXZlbi4gTm8gbWF0dGVyIHdoYXQgdGltZSBpdCBpcyBpbiB5b3VyIGxvY2FsIHRpbWUgem9uZSwgdGhlIHRpbWUgcHJvdmlkZWQgYnkgcnR3ZWV0IGlzIGluIFVUQyB0aW1lLgoKUGVsb3NpIGlzIHByb2JhYmx5IHR3ZWV0aW5nIGZyb20gV2FzaGluZ3RvbiBEQywgd2hpY2ggaXMgaW4gdGhlIEVhc3Rlcm4gdGltZSB6b25lLCBjYWxsZWQgIkFtZXJpY2EvTmV3X1lvcmsiIChzZWUgaGVyZSBmb3IgYSBjb21wbGV0ZSBsaXN0aW5nOiBodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9MaXN0X29mX3R6X2RhdGFiYXNlX3RpbWVfem9uZXMgKS4gU2hlIGlzIGZyb20gQ2FsaWZvcm5pYSwgYW5kIHNvIHNvbWUgb2YgaGVyIHR3ZWV0cyBtYXkgYmUgZnJvbSB0aGVyZSBvciBlbHNld2hlcmUgd2hlcmUgc2hlIGlzIG5vdCBpbiBEQywgYnV0IGxldCdzIGFzc3VtZSBmb3Igc2ltcGxpY2l0eSB0aGF0IHNoZSBpcyBhbHdheXMgdHdlZXRpbmcgZnJvbSB0aGUgRWFzdGVybiB0aW1lIHpvbmUuCgpXZSBjYW4gY29udmVydCB0aGUgdGltZSB0byBhIG5ldyB0aW1lIHpvbmUgdXNpbmcgd2l0aF90eih0aW1lLCAidGltZV96b25lIiksIHdoZXJlICJ0aW1lX3pvbmUiIGlzIHRoZSBuZXcgdGltZSB6b25lLgoKYGBge3J9CnBlbG9zaV90d2VldHMgJT4lIAogIG11dGF0ZSh0aW1lID0gd2l0aF90eihjcmVhdGVkX2F0LCAiQW1lcmljYS9OZXdfWW9yayIpKSAlPiUgCiAgbXV0YXRlKHRpbWUgPSBob3VyKHRpbWUpKSAlPiUgCiAgY291bnQodGltZSkgJT4lIAogIGRhdGF0YWJsZShvcHRpb25zID0gKGxpc3QocGFnZUxlbmd0aCA9IDI0KSksIHJvd25hbWVzID0gRikKCmBgYAoKVGhlIHRhYmxlIGFib3ZlIHNob3VsZCBtYWtlIG1vcmUgc2Vuc2U6IE5vdCBhcyBtYW55IHR3ZWV0cyBpbiB0aGUgbWlkZGxlIG9mIHRoZSBuaWdodC4KCkxldCdzIHVzZSBwbG90bHkgdG8gY3JlYXRlIGEgaGlzdG9ncmFtIG9mIHRoZSBudW1iZXIgb2YgdHdlZXRzIGF0IGVhY2ggaG91ciBvZiB0aGUgZGF5LgoKCmBgYHtyfQpwZWxvc2lfdHdlZXRzICU+JSAKICBtdXRhdGUodGltZSA9IHdpdGhfdHooY3JlYXRlZF9hdCwgIkFtZXJpY2EvTmV3X1lvcmsiKSkgJT4lICAgICMgY29udmVydCB0byBFYXN0ZXJuIHRpbWUgem9uZQogIG11dGF0ZSh0aW1lID0gaG91cih0aW1lKSkgJT4lICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyBleHRyYWN0IHRoZSBob3VyCiAgcGxvdF9seSh4ID0gfnRpbWUpICU+JSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIGNyZWF0ZSBwbG90bHkgZ3JhcGgKICBhZGRfaGlzdG9ncmFtKCkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIG1ha2UgaGlzdG9ncmFtCgpgYGAKClRvIGNvbXBsZXRlIHRoZSBncmFwaCBhYm92ZSwgYWRkIHRoZSBmb2xsb3dpbmcgbGluZToKCmxheW91dCh0aXRsZSA9ICJXaGVuIERvZXMgQFNwZWFrZXJQZWxvc2kgVHdlZXQ/IiwgCiAgICAgICAgIHhheGlzID0gbGlzdCh0aXRsZSA9ICJUaW1lIG9mIERheSAoMCA9IG1pZG5pZ2h0KSIpLAogICAgICAgICB5YXhpcyA9IGxpc3QodGl0bGUgPSAiTnVtYmVyIG9mIFR3ZWV0cyIpKQoKYGBge3J9CnBlbG9zaV90d2VldHMgJT4lIAogIG11dGF0ZSh0aW1lID0gd2l0aF90eihjcmVhdGVkX2F0LCAiQW1lcmljYS9OZXdfWW9yayIpKSAlPiUgICAgIyBjb252ZXJ0IHRvIEVhc3Rlcm4gdGltZSB6b25lCiAgbXV0YXRlKHRpbWUgPSBob3VyKHRpbWUpKSAlPiUgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjIGV4dHJhY3QgdGhlIGhvdXIKICBwbG90X2x5KHggPSB+dGltZSkgJT4lICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgY3JlYXRlIHBsb3RseSBncmFwaAogIGFkZF9oaXN0b2dyYW0oKSAlPiUKICAgIGxheW91dCh0aXRsZSA9ICJXaGVuIERvZXMgQFNwZWFrZXJQZWxvc2kgVHdlZXQ/IiAsIAogICAgICAgICB4YXhpcyA9IGxpc3QodGl0bGUgPSAiVGltZSBvZiBEYXkgKDAgPSBtaWRuaWdodCkiKSAsCiAgICAgICAgIHlheGlzID0gbGlzdCh0aXRsZSA9ICJOdW1iZXIgb2YgVHdlZXRzIikpCiAgCmBgYAoKCgoKCgogICAgICAgICAKIyMjIERheSBvZiB3ZWVrIG9mIHRoZSB0d2VldHMKICAgICAgICAgCkxldCdzIGFwcGx5IHRoZSBzYW1lIHRlY2huaXF1ZSBhcyBhYm92ZSB0byB3aGljaCBkYXlzIG9mIHRoZSB3ZWVrIFBlbG9zaSB0d2VldHMuIFVzZSB3ZGF5KCkgdG8gZXh0cmFjdCB0aGUgZGF5IG9mIHRoZSB3ZWVrIHRoZSB0d2VldCB3YXMgbWFkZSBmcm9tIGNyZWF0ZWRfYXQuIFRoZSB0ZXJtICdsYWJlbCA9IFQnIHdpbGwgY2F1c2UgdGhlIG5hbWVzIGZvciB0aGUgZGF5cyAoU3VuLCBNb24sIGV0Yy4pIHRvIGJlIHVzZWQsIHJhdGhlciB0aGFuIG51bWJlcnMuCgpgYGB7cn0KcGVsb3NpX3R3ZWV0cyAlPiUgCiAgbXV0YXRlKERheSA9IHdkYXkoY3JlYXRlZF9hdCwgICAgICAgICAgICMgZmluZCB0aGUgd2Vla2RheSB0aGF0IHRoZSB0d2VldCB3YXMgY3JlYXRlZAogICAgICAgICAgICAgICAgICAgIGxhYmVsID0gVCkpICU+JSAgICAgICAjIHVzZSBsYWJlbHMgKFN1biwgTW9uLCBldGMpIHJhdGhlciB0aGFuIG51bWJlcnMKICBjb3VudChEYXkpICU+JSAgICAgICAgICAgICAgICAgICAgICAgICAgIyBjb3VudCB0aGUgbnVtYmVyIG9mIHR3ZWV0cyBlYWNoIGRheQogIGRhdGF0YWJsZShyb3duYW1lcyA9IEYpCgpgYGAKCgoKVXNpbmcgdGhlIGNvZGUgYWJvdmUgYXMgYSBzdGFydGluZyBwb2ludCwgY3JlYXRlIGEgaGlzdG9ncmFtIHdpdGggcGxvdGx5IG9mIHRoZSBudW1iZXIgb2YgdHdlZXRzIHBlciB3ZWVrZGF5LCBsaWtlIHdlIGRpZCBhYm92ZSBmb3IgdGhlIG51bWJlciBvZiB0d2VldHMgZWFjaCBob3VyLgoKYGBge3J9CnBlbG9zaV90d2VldHMgJT4lIAogIG11dGF0ZShEYXkgPSB3ZGF5KGNyZWF0ZWRfYXQsICAgICAgICAgICAjIGZpbmQgdGhlIHdlZWtkYXkgdGhhdCB0aGUgdHdlZXQgd2FzIGNyZWF0ZWQKICAgICAgICAgICAgICAgICAgICBsYWJlbCA9IFQpKSAlPiUgICAgICAgIyB1c2UgbGFiZWxzIChTdW4sIE1vbiwgZXRjKSByYXRoZXIgdGhhbiBudW1iZXJzCiAgcGxvdF9seSh4ID0gfkRheSkgJT4lIAogIGFkZF9oaXN0b2dyYW0oKQpgYGAKCgoKCgoKCgojIyMgSGVhdCBtYXAKCkxldCdzIGZpbmlzaCB3aXRoIGEgcmVhbGx5IGNvb2wgZ3JhcGggY2FsbGVkIGEgaGVhdG1hcC4gVGhlIGZvbGxvd2luZyB3aWxsIGNvbWJpbmUgZGF5cyBvZiB0aGUgd2VlayBhbmQgaG91cnMgb2YgdGhlIGRheSwgYW5kIHNob3cgaG93IG9mdGVuIHRoZSB0d2VldHMgb2NjdXIuCgpgYGB7cn0KcGVsb3NpX3R3ZWV0cyAlPiUgCiAgbXV0YXRlKGRheSA9IHdkYXkoY3JlYXRlZF9hdCwgbGFiZWwgPSBUKSkgJT4lIAogIG11dGF0ZShob3VyID0gaG91cih3aXRoX3R6KGNyZWF0ZWRfYXQsICJBbWVyaWNhL05ld19Zb3JrIikpKSAlPiUgCiAgcGxvdF9seSh4ID0gfmRheSwgeSA9IH5ob3VyKSAlPiUgCiAgYWRkX2hpc3RvZ3JhbTJkKG5iaW5zeCA9IDcsIG5iaW5zeSA9IDI0KQoKYGBgCgoKVG8gZmluYWxpemUgdGhlIGdyYXBoLCBhZGQgYSB0aXRsZSBhbmQgeCBhbmQgeSBheGlzIGxhYmVscy4KCmBgYHtyfQpwZWxvc2lfdHdlZXRzICU+JSAKICBtdXRhdGUoZGF5ID0gd2RheShjcmVhdGVkX2F0LCBsYWJlbCA9IFQpKSAlPiUgCiAgbXV0YXRlKGhvdXIgPSBob3VyKHdpdGhfdHooY3JlYXRlZF9hdCwgIkFtZXJpY2EvTmV3X1lvcmsiKSkpICU+JSAKICBwbG90X2x5KHggPSB+ZGF5LCB5ID0gfmhvdXIpICU+JSAKICBhZGRfaGlzdG9ncmFtMmQobmJpbnN4ID0gNywgbmJpbnN5ID0gMjQpICU+JSAKICBsYXlvdXQodGl0bGUgPSAiV2hlbiBkb2VzIEBTcGVha2VyUGVsb3NpIFR3ZWV0PyIsCiAgICAgICAgIHhheGlzID1saXN0KHRpdGxlID0gIlRpbWUgb2YgRGF5ICgwID0gbWlkbmlnaHQpIiksCiAgICAgICAgIHlheGlzID0gbGlzdCh0aXRsZSA9ICJOdW1iZXIgb2YgVHdlZXRzIikpCgpgYGAKCmBgYHtyfQoKYGBg