Skip to contents

Imaginary Network Motifs: Testing Systematic Perception Errors

People do not perceive social networks randomly—their errors follow systematic patterns (Tanaka & Vega Yon, 2023). This vignette demonstrates how to use imaginarycss to (1) compute observed imaginary-census motif counts, (2) generate a null distribution that preserves each perceiver’s tie-level accuracy, and (3) test which motif patterns are significantly elevated or reduced relative to chance.

Setup

library(imaginarycss)

# Load Krackhardt data
data(krackhardt_advice)
data(krackhardt_friendship)
data(krackhardt_friendship_perceptions)
data(krackhardt_advice_perceptions)

# Convert edge-list data frames to adjacency matrices
df_to_adjmat <- function(df) {
  n <- max(c(df$from, df$to))
  m <- matrix(0L, nrow = n, ncol = n)
  m[cbind(df$from, df$to)] <- df$value
  m
}

advice_matrix     <- df_to_adjmat(krackhardt_advice)
friendship_matrix <- df_to_adjmat(krackhardt_friendship)

Data Overview

n <- nrow(advice_matrix)

# Network summary
data.frame(
  Network    = c("Friendship", "Advice"),
  Edges      = c(sum(friendship_matrix), sum(advice_matrix)),
  Density    = round(c(
    sum(friendship_matrix) / (n * (n - 1)),
    sum(advice_matrix)     / (n * (n - 1))
  ), 3)
)
     Network Edges Density
1 Friendship   102   0.243
2     Advice   190   0.452

Creating the CSS Graphs

Each graph bundles the true network (first element) with every individual’s perception.

friendship_graph <- new_barry_graph(
  c(list(friendship_matrix), krackhardt_friendship_perceptions)
)
advice_graph <- new_barry_graph(
  c(list(advice_matrix), krackhardt_advice_perceptions)
)

Observed Motif Counts

The imaginary census classifies every perceiver–dyad pair into one of ten categories. The summary() method aggregates counts across perceivers.

friendship_observed <- count_imaginary_census(friendship_graph)
advice_observed     <- count_imaginary_census(advice_graph)

# Friendship motifs (top 6)
head(summary(friendship_observed))
                 Accurate null                  Accurate assym
                           2472                             529
Partial false positive (assym)   Partial false positive (null)
                            378                             276
                 Accurate full   Partial false negative (full)
                            269                             181 
# Advice motifs (top 6)
head(summary(advice_observed))
                Accurate assym                   Accurate null
                           1052                             992
                 Accurate full  Partial false negative (assym)
                            469                             463
Partial false positive (assym)   Partial false negative (full)
                            412                             395 

Null-Model Testing

The test_imaginary_census() function generates null CSS samples for each network. Each sample preserves every perceiver’s four accuracy rates (true-positive/true-negative for ego/alter dyads) but randomises which specific dyads are misperceived. It then computes z-scores and two-sided empirical p-values.

set.seed(331)
friendship_test <- test_imaginary_census(friendship_graph, n_sim = 100)
advice_test     <- test_imaginary_census(advice_graph, n_sim = 100)

Results

The plot() method for imaginarycss_test objects shows a horizontal barplot of z-scores for each motif. Motifs whose z-score exceeds the critical threshold (dashed red lines) are coloured steelblue; those within the expected range under the null model are shown in grey.

# Print significant motifs
friendship_test
Imaginary-census significance test
  Simulations: 100  | Alpha: 0.05

Significant motifs:
                           motif observed z_score p_value
 Partial false positive (assym)       378   26.95       0
                 Accurate assym       529  -15.55       0
                  Accurate null      2472   14.57       0
  Partial false positive (null)       276  -13.56       0
                    Mixed assym        98   13.30       0
 Partial false negative (assym)       171   -5.64       0
 Complete false positive (null)         3   -5.36       0
advice_test
Imaginary-census significance test
  Simulations: 100  | Alpha: 0.05

Significant motifs:
                           motif observed z_score p_value
 Partial false positive (assym)       412    7.87       0
                  Accurate null       992    7.38       0
  Partial false positive (null)       343   -6.12       0
                 Accurate assym      1052   -5.33       0
                    Mixed assym       173    3.59       0
 Complete false positive (null)        30   -3.58       0
# Visualise z-scores
plot(friendship_test, main = "Friendship: Motif Z-Scores vs Null")

plot(advice_test,     main = "Advice: Motif Z-Scores vs Null")

Full Summary

The summary() method shows all motifs with their test statistics.

summary(friendship_test)
Imaginary-census significance test
  Simulations: 100  | Alpha: 0.05
  Motifs tested: 10 | Significant: 7

                           motif observed null_mean null_sd z_score p_value
 Partial false positive (assym)       378     104.6   10.15   26.95    0.00
                 Accurate assym       529     790.0   16.78  -15.55    0.00
                  Accurate null      2472    2167.7   20.89   14.57    0.00
  Partial false positive (null)       276     546.3   19.94  -13.56    0.00
                    Mixed assym        98      33.3    4.86   13.30    0.00
 Partial false negative (assym)       171     248.0   13.65   -5.64    0.00
 Complete false positive (null)         3      37.0    6.34   -5.36    0.00
                  Accurate full       269     278.6   10.07   -0.95    0.34
  Partial false negative (full)       181     174.5    9.36    0.69    0.46
 Complete false negative (full)        33      29.9    5.46    0.57    0.62
 significant
        TRUE
        TRUE
        TRUE
        TRUE
        TRUE
        TRUE
        TRUE
       FALSE
       FALSE
       FALSE

Tie-Level Accuracy

friendship_acc <- tie_level_accuracy(friendship_graph)
advice_acc     <- tie_level_accuracy(advice_graph)

# Mean individual accuracy
data.frame(
  Network = c("Friendship", "Advice"),
  TP      = round(c(
    mean(friendship_acc$p_1_ego, na.rm = TRUE),
    mean(advice_acc$p_1_ego,     na.rm = TRUE)
  ), 3),
  TN      = round(c(
    mean(friendship_acc$p_0_ego, na.rm = TRUE),
    mean(advice_acc$p_0_ego,     na.rm = TRUE)
  ), 3)
)
     Network    TP    TN
1 Friendship 0.750 0.886
2     Advice 0.695 0.795

Conclusion

By comparing observed motif counts against null distributions that preserve individual-level accuracy, the imaginary census reveals which perceptual errors are systematic rather than random. Elevated motifs indicate cognitive schemas (e.g., balance, reciprocity) that distort network perception beyond what individual accuracy rates alone would predict.