Feed Analysis

Analyzing Feeds on Blue Sky

On Blue Sky users have the ability to create custom feeds based on specific keywords. These feeds aggregate content, for instance, a user might create a feed around the hashtag #rstats to gather all relevant content about. Let’s delve into the dynamics of such feeds created by users.

Load the package

library(atrrr)

Retrieving a Feed

Our starting point is to extract the posts from a feed. We’re focusing on a feed curated by “andrew.heiss.phd”.

# Fetching the feed posts
feeds <- get_feeds_created_by(actor = "andrew.heiss.phd") |>
  dplyr::glimpse()
#> Rows: 4
#> Columns: 20
#> $ uri                       <chr> "at://did:plc:2…
#> $ cid                       <chr> "bafyreidmykchh…
#> $ did                       <chr> "did:web:skyfee…
#> $ creator_did               <chr> "did:plc:2zcfjz…
#> $ creator_handle            <chr> "andrew.heiss.p…
#> $ creator_displayName       <chr> "Andrew Heiss",…
#> $ creator_avatar            <chr> "https://cdn.bs…
#> $ creator_viewer_muted      <lgl> FALSE, FALSE, F…
#> $ creator_viewer_blockedBy  <lgl> FALSE, FALSE, F…
#> $ creator_viewer_following  <chr> "at://did:plc:n…
#> $ creator_viewer_followedBy <chr> "at://did:plc:2…
#> $ creator_description       <chr> "Assistant prof…
#> $ creator_indexedAt         <chr> "2024-01-26T00:…
#> $ displayName               <chr> "Nonprofit Stud…
#> $ description               <chr> "A feed for non…
#> $ avatar                    <chr> "https://cdn.bs…
#> $ likeCount                 <int> 20, 81, 0, 102
#> $ indexedAt                 <chr> "2023-09-20T21:…
#> $ created_at                <dttm> 2023-09-20 21:1…
#> $ viewer_like               <chr> NA, NA, NA, "a…

# Filtering for a specific keyword, for example "#rstats"
rstat_feed <- feeds |>
  filter(displayName == "#rstats")

# Extracting posts from this curated feed
rstat_posts <- get_feed(rstat_feed$uri, limit = 200) |>
  dplyr::glimpse()
#> Rows: 200
#> Columns: 18
#> $ uri           <chr> "at://did:plc:vgvueqvmbqgoy…
#> $ cid           <chr> "bafyreie2uewopzpmtxwil3a5p…
#> $ author_handle <chr> "cranberriesfeed.bsky.socia…
#> $ author_name   <chr> "CRAN Package Updates Bot",…
#> $ text          <chr> "CRAN updates: lava MissMec…
#> $ author_data   <list> ["did:plc:vgvueqvmbqgoyxtc…
#> $ post_data     <list> ["app.bsky.feed.post", "20…
#> $ embed_data    <list> <NULL>, <NULL>, ["app.bsky…
#> $ reply_count   <int> 0, 0, 0, 0, 0, 0, 0, 0, 2, …
#> $ repost_count  <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, …
#> $ like_count    <int> 0, 0, 0, 0, 0, 0, 0, 0, 6, …
#> $ indexed_at    <dttm> 2024-03-05 13:02:18, 2024-…
#> $ in_reply_to   <chr> NA, NA, NA, NA, NA, NA, NA,…
#> $ in_reply_root <chr> NA, NA, NA, NA, NA, NA, NA,…
#> $ quotes        <chr> NA, NA, NA, NA, NA, NA, NA,…
#> $ tags          <list> "rstats", "rstats", "rstat…
#> $ mentions      <list> <NULL>, <NULL>, <NULL>, <N…
#> $ links         <list> <NULL>, <NULL>, <NULL>, <N…

Identifying Top Contributors

Who are the leading voices within a particular topic? This analysis highlights users who are frequently contributing to the #rstats feed.

library(ggplot2)

# Identifying the top 10 contributors
rstat_posts |>
  count(handle = author_handle, sort = T) |>
  slice(1:10) |>
  mutate(handle = forcats::fct_reorder(handle, n)) |>
  ggplot(aes(handle, n)) +
  geom_col() +
  coord_flip() +
  theme_minimal()
Top 10 #rstats contributors

Top 10 #rstats contributors

Recognizing Influential Voices

Volume doesn’t always translate to influence. Some users may post less frequently but their contributions resonate deeply with the community.

# Identifying top 10 influential voices based on likes
rstat_posts |>
  group_by(author_handle) |>
  summarize(like_count = sum(like_count)) |>
  ungroup() |>
  arrange(desc(like_count)) |>
  slice(1:10) |>
  mutate(handle = forcats::fct_reorder(author_handle, like_count)) |>
  ggplot(aes(handle, like_count)) +
  geom_col() +
  coord_flip() +
  theme_minimal()
Top 10 #rstats contributors based on likes

Top 10 #rstats contributors based on likes

Most Famous #rstats skeet

# Finding the standout post in the rstats feed
rstat_posts |>
  mutate(total_interactions = reply_count + repost_count + like_count) |>
  arrange(desc(total_interactions)) |>
  slice(1) |>
  select(author_handle, total_interactions, text) |>
  dplyr::glimpse() |>
  pull(text)
#> Rows: 1
#> Columns: 3
#> $ author_handle      <chr> "omearabrian.bsky.soci…
#> $ total_interactions <int> 42
#> $ text               <chr> "New paper! \"dentist:…
#> [1] "New paper! \"dentist: Quantifying uncertainty by sampling points around maximum likelihood estimates\". Easy thing to plug into R workflows for getting better confidence intervals and detecting potential identifiability issues. #OpenAccess paper at doi.org/10.1111/2041...\n\n#Rstats #OpenSource"