Some Graphs of the Social Connectedness Index

Author

Tin Skoric

Published

May 2026

1 The Social Connections Index

Over the past few months, META (formerly/currently known by everyone as Facebook) has been trickling out data for their “Facebook Social Connectedness Index” (SCI for short) and I thought it would be cool to make a few little maps with it. So, I’ve made the following:

  • A map of the county-to-county SCI values (binned) for just about every county in the U.S.; as well as

  • A “state-to-county” version where the highest SCI values for each county-to-county pair per state are combined (e.g., imagine if you took all the county-to-county maps from before, and layered them atop one another where the value kept for a county was the highest found on any one of those maps);

Fun. The link to all the produced plots is here. There are a handful of counties that don’t have anything; either because they aren’t in the SCI data (doubtful) or because the fips join with us_map() doesn’t yet have those codes; but it’s fine, they are few and far between.

2 Mapping Connections

We have two main types of charts to make here: two series of many charts of the same type, but across many counties individually; and two charts of the same type across all counties at once. As such, we are going to be doing slightly different things for each, even if the measure is similar. For each case, we will be using the us_counties.zip download from the SCI download page, which includes a list of pairs of user/friend fips codes and their respective (scaled) SCI value. We will take that dataset, and return geometries for the respective friend region fips codes (friend_region) using us_map("counties") (and drop the user_country and friend_country columns while we’re at it since we don’t need those). After this, our work diverges between the two types of charts. For the first (mapping each county individually), we create a process where we:

  • Grab a vector of the unique user_region fips codes in our data (n = 3204);

  • Create a for-loop iterating over the length of that vector; where for i in each loop

  • Create a truncated dataset consisting of only one specific fips code for that loop where data is rescaled and binned into groups reflecting the significance (magnitude) of the SCI index for a given user-friend pair; and

  • Create and save maps for that fips code to its respective state folder accordingly.

This process is reflected in the collapsed code chunk below. Here are the results for Rutland and Chittenden counties in Vermont:

Rutland County

Rutland County

Chittenden County

Chittenden County
user_regions <- unique(data_sf$user_region)
for(i in 1:length(user_regions)) {
  data_i <- data_sf %>% 
    filter(user_region == user_regions[[i]]) %>% 
    mutate(
      scaled_sci_bin = cut(log(round(rescale(scaled_sci, to = c(2, 100), from = c(min(scaled_sci), max(scaled_sci))), 4)), c(0, 1, 2, 3, 4)),
      scaled_sci_bin = case_when(
        scaled_sci_bin == "(0,1]" ~ "Most Insignificant",
        scaled_sci_bin == "(1,2]" ~ "Insignificant",
        scaled_sci_bin == "(2,3]" ~ "Significant",
        scaled_sci_bin == "(3,4]" ~ "Most Significant",
        TRUE ~ "Home"
      )
    ) %>% st_as_sf()
  plot_i <- ggplot() +
    geom_sf(
      data = us_map("counties"),
      mapping = aes(),
      size = 0.1, fill = "antiquewhite4", color = "antiquewhite4"
    ) +
    geom_sf(
      data = data_i,
      mapping = aes(color = scaled_sci_bin, fill = scaled_sci_bin),
      size = 0.1
    ) + theme_can_map() +
    scale_color_manual(
      breaks = c("Home", "Most Insignificant", "Insignificant", "Significant", "Most Significant"),
      values = c(canned_colors_get(,"danger"), "antiquewhite3", "#bd828a", "#b66278", canned_colors_get(,"danger")),
    ) +
    scale_fill_manual(
      breaks = c("Home", "Most Insignificant", "Insignificant", "Significant", "Most Significant"),
      values = c(canned_colors_get(,"danger"), "antiquewhite3", "#bd828a", "#b66278", canned_colors_get(,"danger")),
    ) +
    theme(legend.position = "none")
  plot_id <- c((us_map("counties") %>% filter(fips == user_regions[[i]]))[[3]], (us_map("counties") %>% filter(fips == user_regions[[i]]))[[4]])
  if(length(plot_id) == 2){
   ggsave(paste0("meta-social-connectedness/County_Maps/", plot_id[[1]], "/", plot_id[[2]], "_Plot.png"), plot_i) 
  } else {ggsave(paste0("meta-social-connectedness/County_Maps/", "Unknown", "/", i, "_Plot.png"), plot_i)}
  print(i)
}

For our second series of maps, (state-to-county), we follow a somewhat similar process, but instead iterate by individual states (with a nested loop to gather the data for each county in a state). The results for New York and Vermont look like this, respectively:

Vermont State-to-County Plot

Vermont State-to-County Plot

New York State-to-County Plot

New York State-to-County Plot
# nested for-loop bc if we take all counties per state at once, the bins are different
user_regions <- unique(substr(data_sf$user_region, 1, 2))
for(i in 1:length(user_regions)) {
  data_i <- data_sf %>% mutate(user_state = substr(user_region, 1, 2), friend_state = substr(friend_region, 1, 2)) %>% 
    filter(user_state == user_regions[[i]])
  user_regions_j <- unique(data_i$user_region)
  data_ij <- data.frame()
  for (j in 1:length(user_regions_j)) {
    data_j <- data_i %>% filter(user_region == user_regions_j[[j]]) %>% 
      mutate(
        scaled_sci_bin = cut(log(round(rescale(scaled_sci, to = c(2, 100), from = c(min(scaled_sci), max(scaled_sci))), 4)), c(0, 1, 2, 3, 4)),
        scaled_sci_bin_numeric = case_when(
          scaled_sci_bin == "(0,1]" ~ 0,
          scaled_sci_bin == "(1,2]" ~ 1,
          scaled_sci_bin == "(2,3]" ~ 2,
          scaled_sci_bin == "(3,4]" ~ 3,
          TRUE ~ 4
        )
      )
    data_ij <- plyr::rbind.fill(data_ij, data_j)
    print(j)
  }
  data_ij <- data_ij %>% group_by(friend_region) %>% filter(scaled_sci_bin_numeric == max(scaled_sci_bin_numeric)) %>% 
    ungroup() %>% select(user_state, friend_region, scaled_sci_bin_numeric) %>% unique() %>% 
    mutate(
      scaled_sci_bin = case_when(
        scaled_sci_bin_numeric == 0 ~ "Most Insignificant",
        scaled_sci_bin_numeric == 1 ~ "Insignificant",
        scaled_sci_bin_numeric == 2 ~ "Significant",
        scaled_sci_bin_numeric == 3 ~ "Most Significant",
        scaled_sci_bin_numeric == 4 ~ "Home",
        TRUE ~ "Home"
      )
    ) %>% 
  left_join(us_map("counties") %>% rename(friend_region = fips) %>% select(friend_region)) %>% 
  st_as_sf()
  plot_i <- ggplot() +
    geom_sf(
      data = us_map("counties"),
      mapping = aes(),
      size = 0.1, fill = "antiquewhite4", color = "antiquewhite4"
    ) +
    geom_sf(
      data = data_ij,
      mapping = aes(color = scaled_sci_bin, fill = scaled_sci_bin),
      size = 0.1
    ) + theme_can_map() +
    scale_color_manual(
      breaks = c("Home", "Most Insignificant", "Insignificant", "Significant", "Most Significant"),
      values = c(canned_colors_get(,"danger"), "antiquewhite3", "#bd828a", "#b66278", canned_colors_get(,"danger")),
    ) +
    scale_fill_manual(
      breaks = c("Home", "Most Insignificant", "Insignificant", "Significant", "Most Significant"),
      values = c(canned_colors_get(,"danger"), "antiquewhite3", "#bd828a", "#b66278", canned_colors_get(,"danger")),
    ) +
    theme(legend.position = "none")
  plot_id <- unique((us_map("counties") %>% filter(substr(fips, 1, 2) == unique(data_ij %>% select(user_state))[[1]]))[[3]])
  if(length(plot_id) == 1){
   ggsave(paste0("meta-social-connectedness/State_Maps/", plot_id, "_Plot.png"), plot_i) 
  } else {ggsave(paste0("meta-social-connectedness/State_Maps/Unknown/", "Unknown_Plot_", i, ".png"), plot_i)}
  print(i)
}