| Type: | Package |
| Title: | Temporal Auditing of Social Interaction Networks |
| Version: | 0.1.0 |
| Description: | Tools for constructing, auditing, and visualizing temporal social interaction networks from event-log data. Supports graph construction from raw user-to-user interaction logs, longitudinal tracking of network structure, community dynamics, user role trajectories, and concentration of engagement over time. Designed for computational social science, platform analytics, and digital community health monitoring. Includes four longitudinal audit indices: the Network Drift Index ('NDI'), Community Fragmentation Index ('CFI'), Visibility Concentration Index ('VCI'), and Role Mobility Index ('RMI'). 'NDI', 'CFI', 'VCI', and 'RMI' are purpose-built composite scores for longitudinal platform auditing. |
| License: | GPL-3 |
| URL: | https://github.com/causalfragility-lab/socialdrift |
| BugReports: | https://github.com/causalfragility-lab/socialdrift/issues |
| Encoding: | UTF-8 |
| Depends: | R (≥ 4.1.0) |
| Imports: | dplyr (≥ 1.1.0), tibble (≥ 3.2.0), tidyr (≥ 1.3.0), purrr (≥ 1.0.0), ggplot2 (≥ 3.4.0), igraph (≥ 1.5.0), stats |
| Suggests: | testthat (≥ 3.0.0), knitr, rmarkdown, patchwork |
| RoxygenNote: | 7.3.3 |
| Config/testthat/edition: | 3 |
| VignetteBuilder: | knitr |
| NeedsCompilation: | no |
| Packaged: | 2026-04-19 03:27:55 UTC; Subir |
| Author: | Subir Hait |
| Maintainer: | Subir Hait <haitsubi@msu.edu> |
| Repository: | CRAN |
| Date/Publication: | 2026-04-21 19:52:45 UTC |
socialdrift: Temporal Auditing of Social Interaction Networks
Description
socialdrift provides a full workflow for constructing, auditing, and visualising temporal social interaction networks from raw event-log data.
Details
The package is organised into five functional modules:
- Data engineering
-
as_social_events(),validate_social_events(),build_graph_snapshot(),build_graph_series() - Structural metrics
-
network_density_ts(),reciprocity_ts(),clustering_ts(),degree_inequality_ts(),summarize_network_series() - Community dynamics
-
detect_communities_ts(),community_drift(),community_fragmentation_index() - Role trajectories
-
classify_user_roles(),role_trajectories(),role_mobility_index() - Drift & inequality auditing
-
network_drift(),network_drift_index(),visibility_concentration_index(),creator_concentration(),engagement_gap(),audit_group_disparities() - Plotting
-
plot_network_metrics(),plot_network_drift(),plot_role_trajectories()
Signature indices
-
NDI (Network Drift Index): composite measure of structural change between periods (
network_drift()). -
CFI (Community Fragmentation Index): degree to which communities have become siloed (
community_fragmentation_index()). -
VCI (Visibility Concentration Index): how concentrated incoming attention is (
visibility_concentration_index()). -
RMI (Role Mobility Index): how frequently users transition between structural roles (
role_mobility_index()).
Quick start
library(socialdrift)
data(sim_social_events)
ev <- as_social_events(sim_social_events,
actor_group = "actor_group",
target_group = "target_group")
gs <- build_graph_series(ev, window = "month")
summarize_network_series(gs)
network_drift(gs)
role_trajectories(gs)
audit_group_disparities(ev, gs)
Author(s)
Maintainer: Subir Hait haitsubi@msu.edu (ORCID)
See Also
Package vignette:
vignette("socialdrift-intro")
Coerce a data frame into a standardized social event table
Description
Validates and standardizes a data frame of user-to-user interaction events for use in temporal social network analysis with socialdrift.
Usage
as_social_events(
data,
actor = "actor_id",
target = "target_id",
time = "timestamp",
event_type = NULL,
weight = NULL,
actor_group = NULL,
target_group = NULL
)
Arguments
data |
A data frame or tibble containing interaction events. |
actor |
Column name (character) for the source actor. Default |
target |
Column name (character) for the target actor. Default |
time |
Column name (character) for the event timestamp. Must be
|
event_type |
Optional column name (character) for interaction type
(e.g., |
weight |
Optional column name (character) for edge weight. If |
actor_group |
Optional column name (character) for actor group membership (used in group disparity analyses). |
target_group |
Optional column name (character) for target group membership. |
Value
A tibble of class social_events with standardized columns:
actor_id, target_id, timestamp, event_type, weight, and
optionally actor_group, target_group.
Examples
events <- data.frame(
from = c("u1", "u1", "u2", "u3"),
to = c("u2", "u3", "u3", "u4"),
when = as.POSIXct(c("2025-01-01", "2025-01-03",
"2025-01-04", "2025-01-06"))
)
ev <- as_social_events(events, actor = "from", target = "to", time = "when")
ev
Audit network metrics by user group over time
Description
Computes per-group summaries of structural position (degree, betweenness) across all periods in a graph series. Useful for detecting systematic disparities in network access or visibility.
Usage
audit_group_disparities(
data,
graph_series,
group_var = "actor_group",
window = c("month", "week", "day", "quarter", "year")
)
Arguments
data |
A standardized social event tibble with group membership columns. |
graph_series |
A |
group_var |
Column name identifying actor groups. Default |
window |
Aggregation window. Default |
Value
A tibble with one row per period x group, including:
mean_indegree, mean_outdegree, mean_betweenness, isolation_rate
(proportion of isolated nodes), and n_users.
Examples
data(sim_social_events)
ev <- as_social_events(
sim_social_events,
actor_group = "actor_group",
target_group = "target_group"
)
gs <- build_graph_series(ev, window = "month")
audit_group_disparities(ev, gs)
Build a time series of graph snapshots
Description
Splits event data into non-overlapping time windows and builds one graph per window. Returns a named list of igraph objects.
Usage
build_graph_series(
data,
window = c("day", "week", "month", "quarter", "year"),
directed = TRUE,
weighted = TRUE,
remove_self_loops = TRUE
)
Arguments
data |
A standardized social event tibble (output of |
window |
Aggregation window: one of |
directed |
Logical; if |
weighted |
Logical; if |
remove_self_loops |
Logical; if |
Value
A named list of igraph objects of class social_graph_series.
Names are ISO date strings representing the start of each period.
Examples
data(sim_social_events)
ev <- as_social_events(sim_social_events)
gs <- build_graph_series(ev, window = "month")
length(gs)
names(gs)
Build a weighted graph snapshot from event data
Description
Aggregates event-level interactions into a directed or undirected igraph object for a specified time window.
Usage
build_graph_snapshot(
data,
start = NULL,
end = NULL,
directed = TRUE,
weighted = TRUE,
remove_self_loops = TRUE
)
Arguments
data |
A standardized social event tibble (output of |
start |
Optional start date/time (inclusive). Events before this are excluded. |
end |
Optional end date/time (exclusive). Events from this point are excluded. |
directed |
Logical; if |
weighted |
Logical; if |
remove_self_loops |
Logical; if |
Value
An igraph object. Returns an empty graph if no events fall in the specified window.
Examples
data(sim_social_events)
ev <- as_social_events(sim_social_events)
g <- build_graph_snapshot(ev)
igraph::vcount(g)
igraph::ecount(g)
Check that an object is a social_graph_series
Description
Check that an object is a social_graph_series
Usage
check_graph_series(x)
Arguments
x |
Object to check. |
Check that an object is an igraph
Description
Check that an object is an igraph
Usage
check_igraph(x)
Arguments
x |
Object to check. |
Classify structural roles of users in a graph
Description
Assigns each node a structural role based on its in-degree, out-degree, and betweenness centrality relative to the rest of the network.
Usage
classify_user_roles(graph)
Arguments
graph |
An igraph object. |
Details
Role classification rules (applied in order):
-
isolated — degree = 0 in both directions.
-
bridge — betweenness in top quartile.
-
core — both in- and out-degree in top quartile.
-
popular — in-degree in top quartile, out-degree below.
-
broadcaster — out-degree in top quartile, in-degree below.
-
peripheral — all other nodes.
Value
A tibble with columns:
- node
Node name.
- indegree
In-degree.
- outdegree
Out-degree.
- betweenness
Betweenness centrality.
- role
Assigned structural role.
Examples
data(sim_social_events)
ev <- as_social_events(sim_social_events)
g <- build_graph_snapshot(ev)
classify_user_roles(g)
Compute global clustering coefficient over time
Description
The global clustering coefficient (transitivity) measures the tendency of nodes to form tightly connected triangles. High values indicate clique-like structure; low values indicate sparse or tree-like networks.
Usage
clustering_ts(graph_series)
Arguments
graph_series |
A |
Value
A tibble with columns period and clustering.
Returns NA for periods with fewer than 3 nodes.
Examples
data(sim_social_events)
ev <- as_social_events(sim_social_events)
gs <- build_graph_series(ev, window = "month")
clustering_ts(gs)
Compute community drift between adjacent time periods
Description
Derives period-over-period changes in community structure metrics. Acts as a first-order approximation of how communities are evolving.
Usage
community_drift(community_tbl)
Arguments
community_tbl |
Output of |
Value
The input tibble augmented with columns:
- delta_n_communities
Change in number of communities.
- delta_modularity
Change in modularity.
- delta_largest_community
Change in size of largest community.
Examples
data(sim_social_events)
ev <- as_social_events(sim_social_events)
gs <- build_graph_series(ev, window = "month")
ct <- detect_communities_ts(gs)
community_drift(ct)
Community Fragmentation Index (CFI)
Description
Computes a composite Community Fragmentation Index for each period, combining modularity, number of communities, and singleton prevalence into a single bounded score between 0 and 1. Higher values indicate a more fragmented, siloed network.
Usage
community_fragmentation_index(community_tbl)
Arguments
community_tbl |
Output of |
Details
CFI is computed as:
CFI = 0.5 \cdot \hat{Q} + 0.3 \cdot \hat{C} + 0.2 \cdot \hat{S}
where \hat{Q} is min-max scaled modularity, \hat{C} is
scaled community count, and \hat{S} is singleton proportion.
Value
A tibble with columns period and cfi.
Examples
data(sim_social_events)
ev <- as_social_events(sim_social_events)
gs <- build_graph_series(ev, window = "month")
ct <- detect_communities_ts(gs)
community_fragmentation_index(ct)
Measure concentration of incoming attention over time
Description
Computes how concentrated incoming interactions (in-degree) are across the network. High concentration indicates a few nodes receive most attention.
Usage
creator_concentration(graph_series, p = 0.1)
Arguments
graph_series |
A |
p |
Proportion of top actors to include in concentration measures.
Default |
Value
A tibble with columns:
- period
Time period.
- indegree_gini
Gini coefficient of in-degree (0 = equal, 1 = monopoly).
- top_p_share
Share of total in-degree held by top-p actors.
Examples
data(sim_social_events)
ev <- as_social_events(sim_social_events)
gs <- build_graph_series(ev, window = "month")
creator_concentration(gs)
Compute degree inequality over time
Description
Uses the Gini coefficient of node degree as a measure of how unequally connections are distributed across the network. A Gini of 0 means perfect equality; 1 means one node holds all connections.
Usage
degree_inequality_ts(graph_series, mode = c("all", "in", "out"))
Arguments
graph_series |
A |
mode |
Degree mode: |
Value
A tibble with columns period, degree_gini, and degree_mean.
Examples
data(sim_social_events)
ev <- as_social_events(sim_social_events)
gs <- build_graph_series(ev, window = "month")
degree_inequality_ts(gs)
Detect communities over time using the Louvain method
Description
Applies the Louvain community detection algorithm to each snapshot in a graph series. Directed graphs are coerced to undirected for community detection (standard practice for modularity-based methods).
Usage
detect_communities_ts(graph_series)
Arguments
graph_series |
A |
Value
A tibble with columns:
- period
Time period (character).
- n_communities
Number of communities detected.
- modularity
Modularity score (higher = more modular community structure).
- largest_community_size
Size of the largest community.
- singleton_count
Number of isolated single-node communities.
Examples
data(sim_social_events)
ev <- as_social_events(sim_social_events)
gs <- build_graph_series(ev, window = "month")
detect_communities_ts(gs)
Compute engagement gap between user groups over time
Description
Compares average in-degree (received attention) and out-degree (initiated interactions) between two user groups defined in the original event data.
Usage
engagement_gap(
data,
graph_series,
group_var = "actor_group",
window = c("month", "week", "day", "quarter", "year")
)
Arguments
data |
A standardized social event tibble with |
graph_series |
A |
group_var |
Column in |
window |
Aggregation window matching the one used in |
Value
A tibble with columns period, group, mean_indegree,
mean_outdegree, and engagement_ratio (indegree / outdegree).
Examples
data(sim_social_events)
ev <- as_social_events(
sim_social_events,
actor_group = "actor_group",
target_group = "target_group"
)
gs <- build_graph_series(ev, window = "month")
engagement_gap(ev, gs, group_var = "actor_group", window = "month")
Floor timestamps to a time window
Description
Floor timestamps to a time window
Usage
floor_time_window(x, window = c("day", "week", "month", "quarter", "year"))
Arguments
x |
A POSIXct, POSIXt, or Date vector. |
window |
One of |
Value
A Date vector aligned to the start of each period.
Compute Gini coefficient
Description
Compute Gini coefficient
Usage
gini_coeff(x)
Arguments
x |
A non-negative numeric vector. |
Value
A scalar Gini coefficient between 0 and 1.
Compute network density over time
Description
Network density is the proportion of possible edges that are present. High density indicates a highly connected network; low density indicates sparse interaction.
Usage
network_density_ts(graph_series)
Arguments
graph_series |
A |
Value
A tibble with columns:
- period
Time period (character, ISO date).
- n_nodes
Number of active nodes.
- n_edges
Number of edges.
- density
Network density (0–1).
Examples
data(sim_social_events)
ev <- as_social_events(sim_social_events)
gs <- build_graph_series(ev, window = "month")
network_density_ts(gs)
Compute the Network Drift Index (NDI) over time
Description
The Network Drift Index quantifies how much a network's structure changes between consecutive time periods. It combines changes in edge turnover, degree distribution, community structure, and centralization into a single composite score.
Usage
network_drift(graph_series, w1 = 0.3, w2 = 0.25, w3 = 0.25, w4 = 0.2)
Arguments
graph_series |
A |
w1 |
Weight for edge turnover. Default |
w2 |
Weight for degree distribution shift. Default |
w3 |
Weight for community structure change. Default |
w4 |
Weight for centralization change. Default |
Details
NDI_t = w_1 \Delta_{edges} + w_2 \Delta_{degree} + w_3 \Delta_{community} + w_4 \Delta_{centrality}
Default weights: w1 = 0.30, w2 = 0.25, w3 = 0.25, w4 = 0.20.
Component definitions:
- edge_turnover
Jaccard distance between edge sets of adjacent snapshots.
- degree_shift
Jensen-Shannon-like divergence of degree distributions.
- modularity_change
Absolute change in community modularity.
- centralization_change
Absolute change in degree centralization.
Value
A tibble with columns period, edge_turnover,
degree_shift, modularity_change, centralization_change, and ndi.
Examples
data(sim_social_events)
ev <- as_social_events(sim_social_events)
gs <- build_graph_series(ev, window = "month")
network_drift(gs)
Compute the Network Drift Index (alias for network_drift)
Description
Compute the Network Drift Index (alias for network_drift)
Usage
network_drift_index(graph_series, w1 = 0.3, w2 = 0.25, w3 = 0.25, w4 = 0.2)
Arguments
graph_series |
A |
w1 |
Weight for edge turnover. Default |
w2 |
Weight for degree distribution shift. Default |
w3 |
Weight for community structure change. Default |
w4 |
Weight for centralization change. Default |
Value
See network_drift().
Plot the Network Drift Index over time
Description
Visualises the composite NDI and its four component scores across periods.
Usage
plot_network_drift(drift_tbl, show_components = TRUE)
Arguments
drift_tbl |
Output of |
show_components |
Logical; if |
Value
A ggplot object.
Examples
data(sim_social_events)
ev <- as_social_events(sim_social_events)
gs <- build_graph_series(ev, window = "month")
dt <- network_drift(gs)
plot_network_drift(dt)
Plot one or more time-varying network metrics
Description
Produces a line chart of a metric (or faceted chart for multiple metrics)
from the output of metric functions such as network_density_ts(),
reciprocity_ts(), or summarize_network_series().
Usage
plot_network_metrics(
data,
metric = NULL,
title = "Network Metrics Over Time",
colour = "#2c7bb6"
)
Arguments
data |
A tibble with a |
metric |
Character vector of column name(s) to plot. If more than one,
a faceted chart is produced. If |
title |
Plot title. Default |
colour |
Line colour. Default |
Value
A ggplot object.
Examples
data(sim_social_events)
ev <- as_social_events(sim_social_events)
gs <- build_graph_series(ev, window = "month")
tbl <- network_density_ts(gs)
plot_network_metrics(tbl, metric = "density")
Plot role composition over time
Description
Shows how the proportion of each structural role changes across periods as a stacked bar chart.
Usage
plot_role_trajectories(role_tbl, type = c("stacked", "line"))
Arguments
role_tbl |
Output of |
type |
|
Value
A ggplot object.
Examples
data(sim_social_events)
ev <- as_social_events(sim_social_events)
gs <- build_graph_series(ev, window = "month")
rt <- role_trajectories(gs)
plot_role_trajectories(rt)
Compute reciprocity over time
Description
Reciprocity is the proportion of edges that have a mutual counterpart. Applies to directed graphs only. High reciprocity suggests mutual engagement; low reciprocity suggests broadcast-like interaction.
Usage
reciprocity_ts(graph_series)
Arguments
graph_series |
A |
Value
A tibble with columns period and reciprocity.
Returns NA for undirected graphs or periods with no edges.
Examples
data(sim_social_events)
ev <- as_social_events(sim_social_events)
gs <- build_graph_series(ev, window = "month")
reciprocity_ts(gs)
Role Mobility Index (RMI)
Description
Quantifies how much users move between structural roles across time periods. A high RMI indicates a dynamic network where role transitions are frequent; a low RMI indicates structural stability.
Usage
role_mobility_index(role_tbl)
Arguments
role_tbl |
Output of |
Details
For each user observed in at least two consecutive periods, the RMI counts the proportion of adjacent-period pairs where the role changed. The overall RMI is the mean across all such users.
Value
A tibble with columns:
- rmi_global
Overall Role Mobility Index (0–1).
- n_users_tracked
Number of users with >= 2 observed periods.
- mean_transitions
Mean number of role transitions per user.
Examples
data(sim_social_events)
ev <- as_social_events(sim_social_events)
gs <- build_graph_series(ev, window = "month")
rt <- role_trajectories(gs)
role_mobility_index(rt)
Track user structural roles over time
Description
Applies classify_user_roles() to every snapshot in a graph series and
returns a longitudinal tibble of role assignments.
Usage
role_trajectories(graph_series)
Arguments
graph_series |
A |
Value
A tibble with columns period, node, indegree, outdegree,
betweenness, and role.
Examples
data(sim_social_events)
ev <- as_social_events(sim_social_events)
gs <- build_graph_series(ev, window = "month")
role_trajectories(gs)
Simulated social interaction event log
Description
A synthetic dataset of 591 user-to-user interaction events spanning January through June 2025. Designed for demonstrating the socialdrift workflow. Includes group membership columns for disparity analyses.
Format
A data frame with 591 rows and 7 variables:
- actor_id
Source user ID (character,
"u1"to"u60").- target_id
Target user ID (character).
- timestamp
Event timestamp (POSIXct, UTC).
- event_type
Type of interaction:
"follow","reply","mention","like", or"repost".- weight
Interaction weight (integer, always 1 in this dataset).
- actor_group
Group membership of the actor:
"A","B", or"C".- target_group
Group membership of the target:
"A","B", or"C".
Details
The dataset was generated with preferential attachment: earlier-indexed users have slightly higher probability of being selected as targets, creating realistic degree inequality. Event types are sampled with probabilities approximating typical social platform distributions.
Source
Simulated data. See data-raw/sim_social_events.R for the
generation script.
Examples
data(sim_social_events)
head(sim_social_events)
table(sim_social_events$event_type)
Summarize structural metrics across all periods in a graph series
Description
A convenience wrapper that computes density, reciprocity, clustering, and degree inequality for every period and returns a single wide tibble.
Usage
summarize_network_series(graph_series)
Arguments
graph_series |
A |
Value
A tibble with one row per period and columns for all key metrics.
Examples
data(sim_social_events)
ev <- as_social_events(sim_social_events)
gs <- build_graph_series(ev, window = "month")
summarize_network_series(gs)
Get top-p share of a distribution
Description
Get top-p share of a distribution
Usage
top_p_share(x, p = 0.1)
Arguments
x |
Non-negative numeric vector. |
p |
Proportion (0–1) of top actors. |
Value
Share of total held by top-p proportion.
Validate a standardized social event table
Description
Checks that a social events tibble contains required columns with valid
values. Called automatically by as_social_events().
Usage
validate_social_events(data)
Arguments
data |
A standardized social event tibble (output of |
Value
The validated tibble, invisibly.
Examples
data(sim_social_events)
ev <- as_social_events(sim_social_events)
validate_social_events(ev)
Visibility Concentration Index (VCI)
Description
A composite index measuring whether visibility (incoming attention) is concentrated in a small fraction of users. Combines the Gini coefficient and top-share into a single interpretable score.
Usage
visibility_concentration_index(graph_series)
Arguments
graph_series |
A |
Details
VCI = 0.6 \cdot Gini + 0.4 \cdot top\text{-}10\%\text{-}share
Values near 1 indicate extreme concentration; values near 0 indicate roughly equal attention distribution.
Value
A tibble with columns period and vci.
Examples
data(sim_social_events)
ev <- as_social_events(sim_social_events)
gs <- build_graph_series(ev, window = "month")
visibility_concentration_index(gs)