library(tidytags)
This vignette serves as an introduction to how to use many
tidytags functions through the example of analyzing
tweets associated with the 2019 annual convention of the Association for Educational Communications
& Technology (AECT): #aect19
,
#aect2019
, or #aect19inspired
. The information
in this vignette is available scattered throughout the R documentation
for the tidytags package. This vignette conveniently
brings it all together in one place.
A core functionality of tidytags is collecting tweets continuously with a Twitter Archiving Google Sheet (TAGS).
For help setting up your own TAGS tracker, see the “Getting started
with tidytags” (vignette("setup", package = "tidytags")
)
vignette, Key Task #1.
With a TAGS tracker archive imported into R,
tidytags allows you to gather quite a bit more
information related to the TAGS-collected tweets with the
pull_tweet_data()
function. This function builds off the rtweet
package (via rtweet::lookup_tweets()
and
rtweet::users_data()
) to query the Twitter API.
However, to access the Twitter API, whether through rtweet or tidytags, you will need to apply for developers’ access from Twitter. You do this through Twitter’s developer website.
The rtweet documentation already contains a very
thorough vignette, “Authentication with rtweet”
(vignette("auth", package = "rtweet")
), to guide you
through the process of authenticating access to the Twitter API. We
recommend the app-based authentication method that uses
auth <- rtweet::rtweet_app()
, described in the Apps
section of the vignette.
For further help getting your own Twitter API keys, see the “Getting
started with tidytags” vignette
(vignette("setup", package = "tidytags")
), specifically
Pain Point #2.
Note that your dataset will often contain fewer rows after running
pull_tweet_data()
. This is because
rtweet::lookup_tweets()
is searching for tweet status IDs
that are currently available. Any tweets that have been deleted or made
“protected” (i.e., private) since TAGS first collected them are dropped
from the dataset. Rather than view this as a limitation, we see this as
an asset to help ensure our data better reflects the intentions of the
accounts whose tweets we have collected (see Fiesler
& Proferes, 2018).
Here, we demonstrate two different ways of using
pull_tweet_data()
. The first method is to query the Twitter
API with the tweet ID numbers from the id_str
column
returned by rtweet. However, a limitation of TAGS is
that the numbers in this column are often corrupted because Google
Sheets considers them very large numbers (instead of character strings)
and rounds them by putting them into exponential form. The results of
this first method are stored in the variable
example_after_rtweet_A
below. The second method pulls the
tweet ID numbers from the tweet URLs. For example, the tweet with the
URL
https://twitter.com/tweet__example/status/1176592704647716864
has a tweet ID of 1176592704647716864
. The results of this
second method are stored in the variable
example_after_rtweet_B
below.
<- rtweet::rtweet_app(bearer_token = Sys.getenv("TWITTER_BEARER_TOKEN"))
app ::auth_as(app)
rtweet
<- pull_tweet_data(id_vector = example_df_all$id_str)
example_after_rtweet_A <- pull_tweet_data(url_vector = example_df_all$status_url) example_after_rtweet_B
When this vignette was run on Aug 09 22, the TAGS tracker had
collected 18 variables associated with 2564 tweets. The first method
searching with id_str
collected 66 variables associated
with 2195 tweets. The second method using
‘tidytags::get_char_tweet_ids()’ collected 66 variables associated with
2195 tweets.
Notice how many more variables are in the dataset after using
pull_tweet_data()
, and how many more tweets are in the
dataset when using the second method. We have found that in the process
of storing and retrieving tweet IDs, the long string of numbers can
sometimes be interpreted as an object of type double (i.e., numeric) and
subsequently converted into scientific notation form. This loses the
specific identifying use of the string of numerical digits. Therefore,
we strongly recommend the second method, obtaining tweet IDs from the
tweet URL, which is why we have included
get_char_tweet_ids()
as an internal function in the
tidytags package.
The built-in default of pull_tweet_data()
is to simply
enter the dataframe retrieved from read_tags()
and
implement the second method, retrieving metadata starting with tweet
URLs. That is, pull_tweet_data(read_tags(example_url))
.
Take a quick look at the result, viewed with the glimpse()
function from the dplyr package:
<- pull_tweet_data(read_tags(tags_url))
example_after_rtweet ::glimpse(example_after_rtweet)
dplyr#> Rows: 2,195
#> Columns: 66
#> $ created_at <dttm> 2020-04-19 15:22:23, 2020-03-01 15:00:41, 2020…
#> $ id <dbl> 1.251954e+18, 1.234207e+18, 1.229405e+18, 1.225…
#> $ id_str <chr> "1251954312772812801", "1234206946732830720", "…
#> $ full_text <chr> "RT @RoutledgeEd: Congrats to authors Joseph Re…
#> $ truncated <lgl> FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE…
#> $ display_text_range <dbl> 140, 140, 140, 140, 268, 140, 140, 140, 140, 14…
#> $ entities <list> [[<data.frame[1 x 2]>], [<data.frame[1 x 2]>],…
#> $ source <chr> "<a href=\"https://mobile.twitter.com\" rel=\"n…
#> $ in_reply_to_status_id <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
#> $ in_reply_to_status_id_str <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
#> $ in_reply_to_user_id <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
#> $ in_reply_to_user_id_str <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
#> $ in_reply_to_screen_name <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
#> $ geo <list> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
#> $ coordinates <list> [<data.frame[1 x 3]>], [<data.frame[1 x 3]>], …
#> $ place <list> [<data.frame[1 x 3]>], [<data.frame[1 x 3]>], …
#> $ contributors <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
#> $ is_quote_status <lgl> FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE…
#> $ retweet_count <int> 4, 28, 2, 2, 2, 9, 9, 9, 9, 9, 1, 9, 9, 9, 9, 9…
#> $ favorite_count <int> 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0,…
#> $ favorited <lgl> FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE…
#> $ retweeted <lgl> FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE…
#> $ possibly_sensitive <lgl> NA, NA, NA, NA, FALSE, NA, NA, NA, NA, NA, FALS…
#> $ lang <chr> "en", "en", "en", "en", "en", "en", "en", "en",…
#> $ retweeted_status <list> [<data.frame[1 x 30]>], [<data.frame[1 x 30]>]…
#> $ quoted_status_id <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 1.21854…
#> $ quoted_status_id_str <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, "121854…
#> $ quoted_status_permalink <list> [<data.frame[1 x 3]>], [<data.frame[1 x 3]>], …
#> $ quoted_status <list> [<data.frame[1 x 26]>], [<data.frame[1 x 26]>]…
#> $ text <chr> "RT @RoutledgeEd: Congrats to authors Joseph Re…
#> $ favorited_by <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
#> $ scopes <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
#> $ display_text_width <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
#> $ quote_count <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
#> $ timestamp_ms <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
#> $ reply_count <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
#> $ filter_level <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
#> $ metadata <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
#> $ query <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
#> $ withheld_scope <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
#> $ withheld_copyright <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
#> $ withheld_in_countries <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
#> $ possibly_sensitive_appealable <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
#> $ user_id <dbl> 1.251952e+18, 3.294167e+09, 9.225363e+17, 8.048…
#> $ user_id_str <chr> "1251951804398669825", "3294167372", "922536306…
#> $ name <chr> "Harriet Watkins", "Augusta Avram", "AECT GSA",…
#> $ screen_name <chr> "Harriet96152202", "ELTAugusta", "gsa_aect", "A…
#> $ location <chr> "", "British Columbia, Canada", "", "", "Moscow…
#> $ description <chr> "Love educational technology, online learning a…
#> $ url <chr> "https://t.co/ztRaRj9BLo", "https://t.co/OpLrmt…
#> $ protected <lgl> FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE…
#> $ followers_count <int> 7, 789, 452, 2050, 2253, 452, 861, 1553, 1719, …
#> $ friends_count <int> 17, 1325, 47, 15, 1362, 47, 482, 714, 728, 0, 1…
#> $ listed_count <int> 0, 0, 4, 57, 178, 4, 6, 0, 149, 98, 124, 12, 12…
#> $ user_created_at <chr> "Sun Apr 19 19:12:33 +0000 2020", "Sun Jul 26 0…
#> $ favourites_count <int> 9, 5096, 147, 772, 4252, 147, 254, 4681, 6669, …
#> $ verified <lgl> FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE…
#> $ statuses_count <int> 9, 7313, 2351, 1388, 12144, 2351, 261, 4980, 11…
#> $ profile_image_url_https <chr> "https://pbs.twimg.com/profile_images/125195195…
#> $ profile_banner_url <chr> "https://pbs.twimg.com/profile_banners/12519518…
#> $ default_profile <lgl> TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, FA…
#> $ default_profile_image <lgl> FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE…
#> $ user_withheld_in_countries <list> [], [], [], [], [], [], [], [], [], [], [], []…
#> $ derived <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
#> $ user_withheld_scope <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,…
#> $ user_entities <list> [[<data.frame[1 x 5]>], [<data.frame[1 x 5]>]]…
At this point, the purpose of tidytags should be
restated. TAGS tweet trackers are easily set up and maintained, and they
do an excellent job passively collecting tweets over time. For instance,
the example TAGS tracker we demo here has collected thousands of tweets
related to the AECT 2019 annual convention since September 30, 2019. In
contrast, running this query now using
rtweet::search_tweets()
is limited by Twitter’s API,
meaning that an rtweet search can only go back in time
6-9 days, and is limited to returning at most 18,000 tweets per query.
So, if you are interested in tweets about AECT 2019, today you could get
almost no meaningful data using rtweet alone.
<-
rtweet_today ::search_tweets("#aect19 OR #aect2019 OR #aect19inspired") rtweet
You can see that an rtweet search for #AECT19 tweets run today returns 0tweets.
In sum, although a TAGS tracker is great for easily collecting tweets over time (breadth), it lacks depth in terms of metadata related to the gathered tweets. Specifically, TAGS returns information on at most 18 variables; in contrast, rtweet returns information on 66 variables. Thus, tidytags brings together the breadth of TAGS with the depth of rtweet.
The Twitter API only allows the looking up of 90,000 tweet IDs at a
time, a rate limit which resets after 15 minutes. Hence
rtweet::lookup_tweets()
will only return results for the
first 90,000 tweet IDs in your dataset. The function
tidytags::lookup_many_tweets()
will automatically divide
your dataset into batches of 90,000 tweets, looking up one batch per 15
minutes until finished. Note that lookup_many_tweets()
also
works for datasets with fewer than 90,000 tweets.
Because our AECT 2019 examples includes fewer than 90,000 tweets (and
because lookup_many_tweets()
involves waiting for 15
minutes between batches), we do not include an example here. However,
this function can be used in the same way as
pull_tweet_data()
.
If your research questions conceptualize your tweet dataset as a
conversation or affinity space, it may be useful to retrieve and add
additional tweets. Specifically, TAGS collects tweets that contain one
or more keywords or text strings. For example, the TAGS tracker we have
been working with in this vignette collected tweets containing the
keywords: #aect19
OR #aect2019
OR
#aect19inspired
. This is a reasonable approach, from a
researchers’ point of view. However, participants who have been
following or contributing to these hashtags would also see additional
tweets in these “conversations” because Twitter connects together tweets
that reply to other tweets into potentially lengthy reply
threads. Tweets in a reply thread are all displayed to a user
viewing tweets on Twitter’s platform, but because some tweets in a
thread may not contain the hashtag of interest, not all tweets in a
user’s experience of a conversation would be collected by TAGS.
Additionally, tweets contained in a reply thread but composed before the
TAGS tracker was initiated would also be left out of the dataset.
There is a solution to this problem. Because the Twitter API offers a
in_reply_to_status_id_str
column, it is possible to
iteratively reconstruct reply threads in an upstream direction,
that is, retrieving tweets composed earlier than replies in the dataset.
We include the get_upstream_tweets()
function in
tidytags to streamline this process. We also print
output at each iteration to demonstrate how the process is
progressing.
<-
example_with_upstream get_upstream_tweets(example_after_rtweet)
The dataset contained 2195 tweets at the start. Running
get_upstream_tweets()
added 29 new tweets.
Unfortunately, due to limitations in what information is provided by the Twitter API, it is not practical to retrieve downstream replies, or those tweets in a reply thread that follow a tweet in the dataset but neglect to include the hashtag or keyword.
After pull_tweet_data()
is used to collect additional
information from TAGS tweet IDs (in this case, the
example_after_rtweet
dataframe), the
tidytags function process_tweets()
can be
used to calculate additional attributes and add these to the dataframe
as new columns. Specifically, five new variables are added:
mentions_count, hashtags_count, urls_count, tweet_type, and
is_self_reply. This results in 71 variables associated with the
collected tweets.
<- process_tweets(example_after_rtweet) example_processed
Notice that you now have 71 variables associated 2195 tweets.
At this point, depending on your research questions, you may wish to calculate some descriptive statistics associated with this tweet data. For instance, the mean and standard deviation of hashtags per tweet:
<- round(mean(example_processed$hashtags_count), 2)
mean_hash <- round(sd(example_processed$hashtags_count), 2) sd_hash
This shows that the mean number of hashtags per tweet is 1.48 with a standard deviation of SD = 1.36.
Or, perhaps, the mean, median, and max number of mentions per tweet would be useful to know:
<- round(mean(example_processed$mentions_count), 2)
mean_mentions <- round(sd(example_processed$mentions_count), 2)
sd_mentions <- median(example_processed$mentions_count)
median_mentions <- max(example_processed$mentions_count) max_mentions
The mean number of mentions per tweet is 1.35 (SD = 1.31). The median is 1, and the maximum number of mentions in a tweet is 14.
The tidytags function get_url_domain()
combines the expand_urls()
function from the
longurl package and the domain()
function
from the urltools package to easily return the domain
names of any hyperlinks including in tweets.
As an example, get_url_domain()
finds that the domain in
the shortened URL bit.ly/2SfWO3K
is
aect.org
:
get_url_domain("bit.ly/2SfWO3K")
#> [1] "aect.org"
It may also be of interest to examine which websites are linked to
most often in your dataset. get_url_domain()
can be
combined with a function from base R like table()
to
calculate frequency counts for domains present in the dataset. This
process is useful to get a picture of to where else on the Internet
tweeters are directing their readers’ attention.
Keep in mind, however, that this process takes a bit of time.
<- dplyr::filter(example_processed, urls_count > 0)
example_urls <- list()
urls_list for(i in 1:nrow(example_urls)) {
<- example_urls$entities[[i]]$urls$expanded_url
urls_list[[i]]
}<- unlist(urls_list)
urls_vector <- get_url_domain(urls_vector)
example_domains <- tibble::as_tibble(table(example_domains))
domain_table <- dplyr::arrange(domain_table, desc(n))
domain_table_sorted head(domain_table_sorted, 20)
#> # A tibble: 20 × 2
#> example_domains n
#> <chr> <int>
#> 1 twitter.com 127
#> 2 convention2.allacademic.com 35
#> 3 instagram.com 24
#> 4 aect.org 20
#> 5 docs.google.com 12
#> 6 youtube.com 11
#> 7 drive.google.com 8
#> 8 caranorth.com 7
#> 9 nodexlgraphgallery.org 7
#> 10 sites.google.com 7
#> 11 apps.apple.com 6
#> 12 litnet.co.za 6
#> 13 isfsu.blogspot.com 5
#> 14 tecfa.unige.ch 5
#> 15 viral-notebook.com 5
#> 16 app.core-apps.com 4
#> 17 flipsnack.com 4
#> 18 linkedin.com 4
#> 19 play.google.com 4
#> 20 springer.com 4
Unsurprisingly, in this dataset, by far the most common domain (as of August 5, 2022) was “twitter.com”, meaning that AECT 2019 tweeters were linking most often to other Twitter content. Other common domains included “convention2.allacademic.com” (i.e., the host of the conference website, including the schedule and session information) as well as “instagram.com” and “youtube.com”, where tweeters likely shared conference-related content.
This function quickly subsets the data, returning just the tweets of
the type indicated (e.g., filter_by_tweet_type(df, "reply")
returns only reply tweets). The filter_by_tweet_type()
function can also be used to look at how many tweets of each type are
present in the dataset.
In the dataset of 2195 tweets, there are 62 replies, 1146 retweets, 100 quote tweets, and 457 tweets that are not replies, retweets, or quote tweets.
Another useful approach to social media research is social
network analysis. Getting started with social network analysis is
as simple as producing an edgelist, a two-column
dataframe listing senders and receivers. An edgelist
gives a complete accounting of whom is interacting with whom. In
Twitter, this is complicated somewhat by the number of ways a user is
able to interact with someone else, namely, through replying,
retweeting, quote tweeting, mentioning, and liking tweets. The
tidytags function create_edgelist()
uses
filter_by_tweet_type()
to create an edgelist that takes
into account three of these types of interaction.
create_edgelist()
returns a dataframe with three columns:
two for the sender and receiver Twitter handles, and a third column
listing the tweet type (i.e., the form of interaction). The default is
for create_edgelist()
to create an edgelist of all possible
interactions, but focusing on one type of interaction is easily
accomplished as well (e.g., looking at interactions through replies
using create_edgelist(df, "reply")
).
Run create_edgelist()
after completing
get_upstream_tweets()
and process_tweets()
for
a complete picture of the interactions.
<-
example_edgelist create_edgelist(process_tweets(example_with_upstream))
head(example_edgelist, 20)
#> tweet_type sender receiver
#> 1 reply nicolapallitt eromerohall
#> 2 reply jeroen69 vdennen
#> 3 reply jmenglund03 bonni208
#> 4 reply DKSch DKSch
#> 5 reply DKSch DKSch
#> 6 reply _valeriei eromerohall
#> 7 reply jmenglund03 SBarksway
#> 8 reply DrTerriC mete_akca
#> 9 reply pazureka SBarksway
#> 10 reply pazureka SBarksway
#> 11 reply TAmankwatia TAmankwatia
#> 12 reply PaulineMuljana robmoore3
#> 13 reply yinbk DrVirtuality
#> 14 reply arasbozkurt arasbozkurt
#> 15 reply arasbozkurt arasbozkurt
#> 16 reply arasbozkurt eromerohall
#> 17 reply correia65 AnnaRoseLeach
#> 18 reply jmenglund03 PaulineMuljana
#> 19 reply PaulineMuljana AmyLomellini_ID
#> 20 reply teacherrogers teacherrogers
We can then easily visualize the edgelist as a sociogram using the tidygraph and ggraph packages.
First, create a graph object using tidygraph:
if (requireNamespace("tidygraph", quietly = TRUE)) {
<-
example_graph ::as_tbl_graph(example_edgelist)
tidygraph<-
example_graph ::mutate(example_graph,
dplyrpopularity = tidygraph::centrality_degree(mode = 'in'))
}
Then plot using ggraph:
if (requireNamespace("ggraph", quietly = TRUE) &
requireNamespace("ggplot2", quietly = TRUE)
) {::ggraph(example_graph, layout = 'kk') +
ggraph::geom_edge_arc(alpha = .2,
ggraphwidth = .5,
strength = .5,
edge_colour = 'steelblue'
+
) ::geom_node_point(alpha = .4, ggplot2::aes(size = popularity)) +
ggraph::scale_size(range = c(1,10))
ggplot2 }
Running create_edgelist()
also provides a simple way to
re-look at how many tweets of each type are present in the dataset,
using the count()
function from dplyr.
::count(example_edgelist, tweet_type, sort = TRUE)
dplyr#> tweet_type n
#> 1 retweet 1146
#> 2 quote 108
#> 3 reply 71
Note that create_edgelist()
does not yet accept
type = "mention"
or type = "like"
parameters
due to the complicated ways mentions are included in tweets as well as
limitations of the information provided by the Twitter API.
Finally, tidytags also has functionality to add
user-level data to an edgelist through the function
add_users_data()
. These additional features are very useful
when taking an inferential approach to social network analysis, such as
building influence or selection models.
<- add_users_data(example_edgelist)
example_senders_receivers_data ::glimpse(example_senders_receivers_data)
dplyr#> Rows: 1,325
#> Columns: 47
#> $ tweet_type <chr> "reply", "reply", "reply", "reply", "reply",…
#> $ sender <chr> "nicolapallitt", "jeroen69", "jmenglund03", …
#> $ receiver <chr> "eromerohall", "vdennen", "bonni208", "DKSch…
#> $ sender_id <dbl> 1.183683e+08, 6.848632e+06, 6.476904e+07, 3.…
#> $ sender_id_str <chr> "118368334", "6848632", "64769037", "3865781…
#> $ sender_name <chr> "Dr Nicola Pallitt", "Jeroen", "jennιғer eng…
#> $ sender_location <chr> "Grahamstown, South Africa", "Boise, ID", "S…
#> $ sender_description <chr> "EdTech @Rhodes_Uni working in @CHERTL_RU & …
#> $ sender_url <chr> "https://t.co/p1veXbw0pP", "https://t.co/GEk…
#> $ sender_protected <lgl> FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FA…
#> $ sender_followers_count <int> 1753, 378, 663, 290, 290, 6324, 663, 5297, 1…
#> $ sender_friends_count <int> 1924, 379, 627, 86, 86, 6280, 627, 5825, 461…
#> $ sender_listed_count <int> 127, 7, 72, 15, 15, 416, 72, 261, 44, 44, 33…
#> $ sender_created_at <dttm> 2010-02-28 08:13:53, 2007-06-16 03:10:38, 2…
#> $ sender_favourites_count <int> 2040, 2847, 2052, 228, 228, 15749, 2052, 946…
#> $ sender_verified <lgl> FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FA…
#> $ sender_statuses_count <int> 7157, 1537, 2918, 643, 643, 57099, 2918, 269…
#> $ sender_profile_image_url_https <chr> "https://pbs.twimg.com/profile_images/122079…
#> $ sender_profile_banner_url <chr> "https://pbs.twimg.com/profile_banners/11836…
#> $ sender_default_profile <lgl> FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FA…
#> $ sender_default_profile_image <lgl> FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FA…
#> $ sender_withheld_in_countries <list> [], [], [], [], [], [], [], [], [], [], [],…
#> $ sender_derived <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
#> $ sender_withheld_scope <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
#> $ sender_entities <list> [[<data.frame[1 x 5]>], [<data.frame[1 x 5]…
#> $ receiver_id <dbl> 9.187479e+08, 1.423597e+08, 1.477788e+07, 3.…
#> $ receiver_id_str <chr> "918747876", "142359679", "14777884", "38657…
#> $ receiver_name <chr> "Dr. Enilda Romero-Hall (She/Her)", "Vanessa…
#> $ receiver_location <chr> "🇵🇦🇨🇦🇺🇸", "Tallahassee, FL", "Orange County,…
#> $ receiver_description <chr> "Associate Professor @UTKnoxville | Learning…
#> $ receiver_url <chr> "https://t.co/bIbSToCw8t", "https://t.co/2br…
#> $ receiver_protected <lgl> FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FA…
#> $ receiver_followers_count <int> 1773, 1151, 7415, 290, 290, 1773, 329, 764, …
#> $ receiver_friends_count <int> 1345, 759, 3538, 86, 86, 1345, 480, 501, 480…
#> $ receiver_listed_count <int> 87, 40, 294, 15, 15, 87, 5, 28, 5, 5, 33, 57…
#> $ receiver_created_at <dttm> 2012-11-01 06:56:04, 2010-05-10 13:39:35, 2…
#> $ receiver_favourites_count <int> 7326, 1097, 23383, 228, 228, 7326, 2160, 196…
#> $ receiver_verified <lgl> FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FA…
#> $ receiver_statuses_count <int> 422, 2102, 20642, 643, 643, 422, 428, 1942, …
#> $ receiver_profile_image_url_https <chr> "https://pbs.twimg.com/profile_images/141641…
#> $ receiver_profile_banner_url <chr> "https://pbs.twimg.com/profile_banners/91874…
#> $ receiver_default_profile <lgl> FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE…
#> $ receiver_default_profile_image <lgl> FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FA…
#> $ receiver_withheld_in_countries <list> [], [], [], [], [], [], [], [], [], [], [],…
#> $ receiver_derived <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
#> $ receiver_withheld_scope <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
#> $ receiver_entities <list> [[<data.frame[1 x 5]>], [<data.frame[1 x 5]…
{tidytags} is still a work in progress, so we fully expect that there are still some bugs to work out and functions to document better. If you find an issue, have a question, or think of something that you really wish {tidytags} would do for you, don’t hesitate to email Bret or reach out on Twitter: @bretsw and @jrosenberg6432.
You can also submit an issue on GitHub.
You may also wish to try some general troubleshooting strategies: