Social Network Analysis of the Twitter hashtag #intled

Soraya Campbell

June 16, 2021

#intled Twitter Network

Those in the international education (IE) community, which is mainly comprised of study abroad, international student and faculty services, and international admissions professionals, discuss and share news and ideas affecting the community through the use of the hashtag #intled.

Having observed this community for years, I am curious about the social network that has been created on Twitter surrounding this topic.

Purpose

For this independent analysis, I will construct a network from an edgelist of interactions surrounding #intled.

The research question I hope to answer is the following:

What are the patterns of peer interaction and the structure of peer networks surrounding #intled on Twitter?

By analyzing the Twitter network, IE professionals can gain an understanding of the actors engaging through this medium and discern their own meaning into the network of these interactions.

Methods

My analysis follows the work in Data Science in Education Using R: Exploring Relationship Using Social Network Analysis with Social Media Data. In order to create the social network for analysis, the following steps were followed:

  1. Pull twitter data
  2. Wrangle data
  3. Put edgelist together
  4. Plot

Pulling Tweets

I used to the rtweet package to pull the latest 500 tweets for the hashtag #intled and placed it into a dataframe. This resulted in 336 observations.

##authenticate
token<-create_token(
  app =app_name,
  consumer_key = api_key,
  consumer_secret=api_secret_key,
  access_token = access_token, 
  access_secret = access_token_secret)

intled_net <-search_tweets("#intled", n=500, include_rts = FALSE)

Tweet results

glimpse(intled_net)
## Rows: 336
## Columns: 90
## $ user_id                 <chr> "1040255396450127873", "1040255396450127873", ~
## $ status_id               <chr> "1404106463937769472", "1401207450833915907", ~
## $ created_at              <dttm> 2021-06-13 16:00:42, 2021-06-05 16:01:04, 202~
## $ screen_name             <chr> "SMIEConsulting", "SMIEConsulting", "SMIEConsu~
## $ text                    <chr> "Are you searching for a robust #IntlEd podcas~
## $ source                  <chr> "Hootsuite Inc.", "Hootsuite Inc.", "Hootsuite~
## $ display_text_width      <dbl> 257, 258, 238, 88, 201, 193, 251, 239, 249, 15~
## $ reply_to_status_id      <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
## $ reply_to_user_id        <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
## $ reply_to_screen_name    <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
## $ is_quote                <lgl> FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALS~
## $ is_retweet              <lgl> FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALS~
## $ favorite_count          <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0~
## $ retweet_count           <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0~
## $ quote_count             <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~
## $ hashtags                <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
## $ symbols                 <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
## $ urls_url                <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
## $ urls_t.co               <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
## $ urls_expanded_url       <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
## $ media_url               <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
## $ media_t.co              <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
## $ media_expanded_url      <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
## $ media_type              <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
## $ ext_media_url           <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
## $ ext_media_t.co          <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
## $ ext_media_expanded_url  <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
## $ ext_media_type          <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
## $ mentions_user_id        <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
## $ mentions_screen_name    <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
## $ lang                    <chr> "en", "en", "en", "en", "en", "en", "en", "en"~
## $ quoted_status_id        <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
## $ quoted_text             <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
## $ quoted_created_at       <dttm> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N~
## $ quoted_source           <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
## $ quoted_favorite_count   <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
## $ quoted_retweet_count    <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
## $ quoted_user_id          <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
## $ quoted_screen_name      <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
## $ quoted_name             <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
## $ quoted_followers_count  <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
## $ quoted_friends_count    <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
## $ quoted_statuses_count   <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
## $ quoted_location         <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
## $ quoted_description      <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
## $ quoted_verified         <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
## $ retweet_status_id       <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
## $ retweet_text            <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
## $ retweet_created_at      <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
## $ retweet_source          <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
## $ retweet_favorite_count  <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
## $ retweet_retweet_count   <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
## $ retweet_user_id         <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
## $ retweet_screen_name     <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
## $ retweet_name            <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
## $ retweet_followers_count <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
## $ retweet_friends_count   <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
## $ retweet_statuses_count  <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
## $ retweet_location        <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
## $ retweet_description     <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
## $ retweet_verified        <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
## $ place_url               <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
## $ place_name              <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
## $ place_full_name         <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
## $ place_type              <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
## $ country                 <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
## $ country_code            <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
## $ geo_coords              <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
## $ coords_coords           <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
## $ bbox_coords             <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
## $ status_url              <chr> "https://twitter.com/SMIEConsulting/status/140~
## $ name                    <chr> "Marty Bennett", "Marty Bennett", "Marty Benne~
## $ location                <chr> "Findlay, OH", "Findlay, OH", "Findlay, OH", "~
## $ description             <chr> "Social Media & Int'l Education Consulting: Se~
## $ url                     <chr> "https://t.co/7k3ESJb4Z8", "https://t.co/7k3ES~
## $ protected               <lgl> FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALS~
## $ followers_count         <dbl> 300, 300, 300, 300, 300, 300, 300, 300, 300, 3~
## $ friends_count           <dbl> 678, 678, 678, 678, 678, 678, 678, 678, 678, 6~
## $ listed_count            <dbl> 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6~
## $ statuses_count          <dbl> 4558, 4558, 4558, 4558, 4558, 4558, 4558, 4558~
## $ favourites_count        <dbl> 186, 186, 186, 186, 186, 186, 186, 186, 186, 1~
## $ account_created_at      <dttm> 2018-09-13 15:06:28, 2018-09-13 15:06:28, 201~
## $ verified                <lgl> FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALS~
## $ profile_url             <chr> "https://t.co/7k3ESJb4Z8", "https://t.co/7k3ES~
## $ profile_expanded_url    <chr> "http://www.smieconsulting.org", "http://www.s~
## $ account_lang            <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA~
## $ profile_banner_url      <chr> "https://pbs.twimg.com/profile_banners/1040255~
## $ profile_background_url  <chr> "http://abs.twimg.com/images/themes/theme1/bg.~
## $ profile_image_url       <chr> "http://pbs.twimg.com/profile_images/113083503~

Wrangle Data

Next, twitter mentions were extracted from the data. The functions regex 😑 and mutate were used to identify all the usernames in the tweets and unnest was used to move every mention to its own line. The tweets were put then into a dataframe called mentions.

#regex
regex <- "@([A-Za-z]+[A-Za-z0-9_]+)(?![A-Za-z0-9_]*\\.)"

intled_net_usernames <-
  intled_net %>%
  # Use regular expression to identify all the usernames in a tweet
  mutate(all_mentions = str_extract_all(text, regex)) %>%
  unnest(all_mentions)

mentions <-intled_net_usernames%>%
  mutate(all_mentions = str_trim(all_mentions))%>%
  select(sender=screen_name, all_mentions)

Living on the Edge

To put together the edgelist, the @ symbol was removed from the all_mentions column. The number of interactions were counted, then the list was filtered only to include users who sent more than one interaction based on the number of interactions.

#remove @
edgelist <- 
  mentions %>% 
  # remove "@" from all_mentions column
  mutate(all_mentions = str_sub(all_mentions, start = 2)) %>% 
  # rename all_mentions to receiver
  select(sender, receiver = all_mentions)
interactions_sent <- edgelist %>% 
  # this counts how many interactions each individual sent 
  count(sender) %>% 
  # arranges the df in descending order of the # of interactions sent
  arrange(desc(n))

edgelist <- edgelist %>% 
  # the first line filters to include only senders in the interactions_sent df
  # the second line does the same, for receivers
  filter(sender %in% interactions_sent$sender,
         receiver %in% interactions_sent$sender)

Create graph object

Now it’s time to plot. I used the as_tbl_graph() function from {tidygraph} to make the dataframe into an object with nodes and edges for a social network graph.

g<-as_tbl_graph(edgelist)
# A tbl_graph: 22 nodes and 22 edges
# A directed multigraph with 9 components
# Node Data: 22 x 1 (active)
  name           
  <chr>          
1 ShawnVanderziel
2 EstherAtNAFSA  
3 ThePIEReview   
4 eduKUDU        
# ... with 16 more rows
# Edge Data: 22 x 2
   from    to
  <int> <int>
1     1     2
2     1    15
3     1     2
# ... with 19 more rows

The Plot thickens

Finally, the plot was created using ggraph. The results, including the names of the actors, the network of interactions, and the measure of centrality were included in the results.

g %>% 
    # this calculates the centrality of each individual using the built-in centrality_authority() function
    mutate(centrality = centrality_authority()) %>% 
    ggraph(layout = "kk") + 
    geom_node_point(aes(size = centrality, color = centrality)) +
    # add label for names of actors 
    geom_node_label(aes(label=name), repel=TRUE)+
    # this line colors the points based upon their centrality
    scale_color_continuous(guide = 'legend') + 
    geom_edge_link(alpha = .2) +
    theme_graph()

Social Network #intled

Results

The plot shows a network with not a whole lot of connectivity. There are many dyad pairs represented here. Many of the actors are organizational accounts, and there is some interaction between organizations and individuals that are part of the organization. The actor @NAFSA, which is the account of the main professional organization for IE, is at the center of a group that includes its President, @EstherAtNAFSA, and users who are members.

This analysis used the measure centrality_authority which purports to measure how influential an individual may be based on the interactions observed. It identified the user @eddiepwest has having a large measure of centrality, or importance. However, it seems like this measure is not as useful in this context.

Discussion

This analysis is based on a small network of those who interact around the #intled hashtag on Twitter. Based on the results, the discussions taking place using this hashtag are a bit ‘closed’, with not much connectivity between the actors. Interactions taking place are really between people who are part or closely related to the same organization - the network is very homophilous.

The results illustrated an observation I had that the people using the hashtag mainly do so to disseminate information but do not really interact with one another. Since this analysis only looked at mentions from one actor to another, to improve upon things, it might be worth it to include in the edge data one or all of the following:

  • retweet count
  • favorite count
  • quote count

Final Thoughts

The #intled network on Twitter is not as active as some other education related hashtags, but it does have a good amount of users who disseminate information regularly. Based on this analysis, the interactions between users surrounding this topic is sparse. If IE professionals would like to engage on this topic, it might be worth it to look into other mediums, such as the professional organizations’ various discussion forums, list-servs, Facebook, or Discord.