digipol 1 – Italy replication

Published

November 24, 2025

Setting forlder, dataset and packages

Define data MP_DATASET

# 1a. Construct the data_MP dataset ---------------------------------------------
data_MP <- EUPeopleIta %>%
  # Select the relevant variables (uso LERI_ita_or, non LERI)
  dplyr::select(
    DIG02_1:DIG02_8, DEM02, DEM02R, VOTEI02_ITA, DEM01, 
    LERI_ita_or, POLINT, POLINF_1:POLINF_3
  ) %>%
  # Convert variables to factors
  dplyr::mutate(across(
    c(DIG02_1:DIG02_8, DEM02R, VOTEI02_ITA, DEM01, 
      LERI_ita_or, POLINT, POLINF_1:POLINF_3),
    haven::as_factor
  )) %>%
  # Order the 1–8 digital use frequency variables
  dplyr::mutate(across(
    c(DIG02_1:DIG02_8),
    ~ factor(.x,
             levels = c("Never", "Less often", "Several times a month",
                        "Several times a week", "Once a day",
                        "Several times a day", "Almost all the time"),
             ordered = TRUE)
  )) %>%
  # Create numeric versions
  dplyr::mutate(across(
    c(DIG02_1:DIG02_8),
    as.integer,
    .names = "{.col}_num"
  )) %>%
  # Rename variables
  dplyr::rename(
    YouTube_      = DIG02_1,
    WhatsApp_     = DIG02_2,
    TwitterX_     = DIG02_3,
    Instagram_    = DIG02_4,
    TikTok_       = DIG02_5,
    Facebook_     = DIG02_6,
    LinkedIn_     = DIG02_7,
    Telegram_     = DIG02_8,
    YouTube       = DIG02_1_num,
    WhatsApp      = DIG02_2_num,
    Twitter_X     = DIG02_3_num,
    Instagram     = DIG02_4_num,
    TikTok        = DIG02_5_num,
    Facebook      = DIG02_6_num,
    Linkedin      = DIG02_7_num,
    Telegram      = DIG02_8_num,
    Age           = DEM02,
    Age_cat       = DEM02R,
    Vote          = VOTEI02_ITA,
    Sex           = DEM01,
    Left_Right    = LERI_ita_or,
    Pol_int       = POLINT,
    Inf_disagr    = POLINF_1,
    Inf_check     = POLINF_2,
    Inf_confirm   = POLINF_3
  ) %>%
  # Recode VOTEI02_ITA levels → Other party / Did not vote
  dplyr::mutate(
    Vote = forcats::fct_recode(
      Vote,
      "Other party" = "Noi Moderati",
      "Other party" = "Impegno Civico-Centro Democratico",
      "Other party" = "Italexit per l'Italia",
      "Other party" = "Unione Popolare",
      "Other party" = "Italia Sovrana e Popolare",
      "Other party" = "Vita",
      "Other party" = "Altro partito",
      
      "Did not vote" = "Non sono andato a votare",
      "Did not vote" = "Ho votato scheda bianca / scheda nulla"
    )
  )

# ---- vote recode
# Code 20 ("Prefer not to answer") → NA
data_MP <- data_MP %>%
  mutate(
    Vote_num = as.integer(EUPeopleIta$VOTEI02_ITA),
    Vote = case_when(
      Vote_num == 20 ~ NA_character_,
      TRUE ~ as.character(Vote)
    ),
    Vote = factor(Vote)
  ) %>%
  select(-Vote_num)

# ---- RECODE LERI_ita_or 
# # original variable: 1-11 = scale 0-10, 12 = "Not placed", 13 = NA
data_MP <- data_MP %>%
  mutate(
    Left_Right_num = as.integer(EUPeopleIta$LERI_ita_or),
    
    Left_Right = case_when(
      Left_Right_num %in% 1:11 ~ as.character(Left_Right_num - 1),
      Left_Right_num == 12 ~ "Not placed",
      Left_Right_num == 13 ~ NA_character_,
      TRUE ~ NA_character_
    ),
    
    Left_Right = factor(
      Left_Right,
      levels = c(as.character(0:10), "Not placed"),
      ordered = FALSE
    )
  ) %>%
  select(-Left_Right_num)

Define the USES_DATASET

# 1b. Construct the data_USES dataset ------------------------------------

data_USES <- EUPeopleNet %>%
  dplyr::select(dplyr::starts_with("dig03_"))

platforms <- c("YouTube", "WhatsApp", "TwitterX", "Instagram",
               "TikTok", "Facebook", "LinkedIn", "Telegram")

platform_prefixes <- paste0("dig03_", 1:8, "_")

purpose_labels <- c(
  "friends", "family", "inf_socially", "sup_soc_causes",
  "inf_pol", "sup_pol_causes", "connect_profess",
  "promote_profess", "other"
)

purpose_suffixes <- 1:9

# Compute binary indicators platform x scope
platform_long <- list()

for (p in seq_along(platforms)) {
  plat   <- platforms[p]
  prefix <- platform_prefixes[p]
  
  for (i in seq_along(purpose_suffixes)) {
    pattern_i <- paste0("^", prefix, purpose_suffixes[i], "$")
    cols_i <- grep(pattern_i, names(data_USES), value = TRUE)
    
    if (length(cols_i) > 0) {
      platform_long[[length(platform_long) + 1]] <- data_USES %>%
        mutate(
          Platform = plat,
          Purpose  = purpose_labels[i],
          Response = ifelse(
            rowSums(across(all_of(cols_i)), na.rm = TRUE) > 0,
            "Yes", "No"
          )
        ) %>%
        dplyr::select(Platform, Purpose, Response)
    }
  }
}

data_platform_use <- dplyr::bind_rows(platform_long)

# Summary of "YES" answers
summary_platform_use <- data_platform_use %>%
  dplyr::filter(Response == "Yes") %>%
  dplyr::group_by(Platform, Purpose) %>%
  dplyr::summarise(n = n(), .groups = "drop") %>%
  dplyr::group_by(Platform) %>%
  dplyr::mutate(Percentage = n / sum(n) * 100) %>%
  dplyr::ungroup() %>%
  dplyr::mutate(Purpose = factor(Purpose, levels = purpose_labels))

# Graph per platform
#| label: fig_social_media_use_by_purpose
#| fig-width: 9
#| fig-height: 6
#| message: false
#| warning: false

# panels order as ES data
summary_platform_use_plot <- summary_platform_use %>%
  dplyr::mutate(
    Platform = factor(
      Platform,
      levels = c("Facebook", "Instagram", "LinkedIn", "Telegram",
                 "TikTok", "TwitterX", "WhatsApp", "YouTube")
    )
  )

ggplot(summary_platform_use_plot,
       aes(x = Purpose, y = Percentage)) +
  geom_col(fill = "darkorange", color = "white", width = 0.75) +
  geom_text(
    aes(label = sprintf("%.1f%%", Percentage)),
    vjust = -0.25,
    size  = 2.2,
    color = "black"
  ) +
  facet_wrap(~ Platform, ncol = 4) +
  labs(
    title    = "Use of Social Media Platform by Purpose",
    subtitle = "Percentage of respondents using each platform for each purpose (Yes responses)",
    x        = "Purpose of Use",
    y        = "Percentage of Respondents"
  ) +
  scale_y_continuous(
    limits = c(0, 50),                  
    breaks = seq(0, 50, 10),
    expand = expansion(mult = c(0, 0.08))
  ) +
  theme_minimal(base_size = 11) +
  theme(
    plot.title        = element_text(face = "bold", size = 12),
    plot.subtitle     = element_text(size = 10),
    axis.title.x      = element_text(size = 10, margin = margin(t = 7)),
    axis.title.y      = element_text(size = 10, margin = margin(r = 7)),
    axis.text.x       = element_text(
      angle = 90, hjust = 1, vjust = 0.5, size = 7
    ),
    axis.text.y       = element_text(size = 7),
    strip.text        = element_text(face = "bold", size = 10),
    panel.grid.major.x = element_blank(),
    panel.grid.minor.x = element_blank(),
    panel.grid.minor.y = element_blank(),
    plot.margin       = margin(t = 9, r = 9, b = 9, l = 9)
  )

Set platform per purpose

# 1c. ANY PLATFORM PER PURPOSE (Yes / No ) ---------------------

data_any <- EUPeopleNet %>%
  dplyr::select(dplyr::starts_with("dig03_"))

labels_use <- c(
  "friends", "family", "inf_socially", "sup_soc_causes",
  "inf_pol", "sup_pol_causes", "connect_profess",
  "promote_profess", "other"
)

purpose_suffixes <- 1:9

for (i in seq_along(labels_use)) {
  pattern_i <- paste0("_", purpose_suffixes[i], "$")
  cols_i <- grep(pattern_i, names(data_any), value = TRUE)
  
  if (length(cols_i) > 0) {
    data_any[[labels_use[i]]] <- ifelse(
      rowSums(data_any[, cols_i], na.rm = TRUE) > 0, 1, 0
    )
  } else {
    message("⚠️ No columns found for purpose: ", labels_use[i])
  }
}

existing_labels <- intersect(labels_use, names(data_any))

data_any <- data_any %>%
  dplyr::mutate(
    dplyr::across(
      all_of(existing_labels),
      ~ factor(.x, levels = c(0, 1), labels = c("No", "Yes"))
    )
  )

summary_uses <- data_any %>%
  tidyr::pivot_longer(
    cols = all_of(existing_labels),
    names_to = "Purpose", values_to = "Response"
  ) %>%
  count(Purpose, Response) %>%
  group_by(Purpose) %>%
  mutate(Percentage = n / sum(n) * 100) %>%
  ungroup()

ggplot(summary_uses, aes(x = Purpose, y = Percentage, fill = Response)) +
  geom_col(position = "dodge") +
  scale_fill_manual(values = c("grey70", "darkorange")) +
  labs(
    title = "Use of ANY Social Media Platform by Purpose",
    subtitle = "Percentages within each purpose (Yes vs No)",
    x = "Purpose",
    y = "Percentage of Respondents",
    fill = "Response"
  ) +
  theme_minimal(base_size = 10) +
  theme(
    axis.text.x = element_text(angle = 45, hjust = 1),
    plot.title  = element_text(face = "bold")
  )

# 1c-bis. political and sociopolitical purposes indicators --------

data_any <- data_any %>%
  mutate(
    # political use (any platform)
    PolInf_smed = inf_pol,

    # political causes (any platform)
    PolSup_smed = sup_pol_causes,

    # sociopolitical use:
    # (social info, social causes support, political information, political causes support)
    PolSocial_smed = ifelse(
      inf_socially == "Yes" | sup_soc_causes == "Yes" |
        inf_pol == "Yes"      | sup_pol_causes == "Yes",
      "Yes", "No"
    ),

    # political info & support (more strict definition)
    PolInfSup_smed = ifelse(
      inf_pol == "Yes" | sup_pol_causes == "Yes",
      "Yes", "No"
    )
  ) %>%
  mutate(
    across(
      c(PolInf_smed, PolSup_smed, PolSocial_smed, PolInfSup_smed),
      ~ factor(.x, levels = c("No", "Yes"))
    )
  )


###Tables
#| label: tables_indicators
#| message: false
#| warning: false

library(dplyr)
library(tidyr)
library(knitr)

# indicators selection
indicators_long <- data_any %>%
  dplyr::select(PolInf_smed, PolSup_smed, PolSocial_smed, PolInfSup_smed) %>%
  tidyr::pivot_longer(
    cols      = everything(),
    names_to  = "Indicator",
    values_to = "Value"
  ) %>%
  dplyr::group_by(Indicator, Value) %>%
  dplyr::summarise(
    n   = dplyr::n(),
    pct = 100 * n / sum(n),
    .groups = "drop"
  )

knitr::kable(
  indicators_long,
  digits  = 1,
  caption = "Distribution of political/socio-political use (ANY platform)"
)
Distribution of political/socio-political use (ANY platform)
Indicator Value n pct
PolInfSup_smed No 426 100
PolInfSup_smed Yes 875 100
PolInf_smed No 441 100
PolInf_smed Yes 860 100
PolSocial_smed No 274 100
PolSocial_smed Yes 1027 100
PolSup_smed No 607 100
PolSup_smed Yes 694 100
### crosstab purposes 
#| label: crosstab_PolInf_PolSup
#| message: false
#| warning: false

crosstab_inf_sup <- table(
  Information = data_any$PolInf_smed,
  Support     = data_any$PolSup_smed
)

# Converts in data.frame & adds row percentage 
crosstab_df <- as.data.frame.matrix(crosstab_inf_sup)
crosstab_df$Row_Total <- rowSums(crosstab_df)

# Counts table
knitr::kable(
  crosstab_df,
  caption = "Table: political information vs political causes support (counts)"
)
Table: political information vs political causes support (counts)
No Yes Row_Total
No 426 15 441
Yes 181 679 860
# Row percentage
prop_row <- prop.table(crosstab_inf_sup, margin = 1) * 100
prop_row_df <- as.data.frame.matrix(round(prop_row, 1))

knitr::kable(
  prop_row_df,
  caption = "Table: political information vs political causes support (row percentages)"
)
Table: political information vs political causes support (row percentages)
No Yes
No 96.6 3.4
Yes 21.0 79.0

Descriptive plots: platform use and purposes

# 2. Descriptive graphs ======================================
## 2.1a Use frequency per platform (DIG02) – count

data_long <- data_MP %>%
  tidyr::pivot_longer(
    cols = YouTube_:Telegram_,
    names_to = "Platform",
    values_to = "Frequency"
  )

ggplot(data_long, aes(x = Frequency)) +
  geom_bar(fill = "darkorange") +
  geom_text(
    stat = "count",
    aes(label = after_stat(count)),  # FIX: after_stat() instead of ..count..
    vjust = -0.5,
    size = 2
  ) +
  facet_wrap(~ Platform, scales = "free_y", ncol = 4) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 90, hjust = 1)) +
  labs(
    title = "Social Media Frequency Use (Counts)",
    x = NULL,
    y = "Count"
  ) +
  scale_y_continuous(expand = expansion(mult = c(0, 0.15)))

## 2.1b Use frequency per platform (DIG02) – percentages

data_long_pct <- data_long %>%
  dplyr::group_by(Platform, Frequency) %>%
  dplyr::summarise(n = n(), .groups = "drop") %>%
  dplyr::group_by(Platform) %>%
  dplyr::mutate(pct = 100 * n / sum(n)) %>%
  dplyr::ungroup()

ggplot(data_long_pct, aes(x = Frequency, y = pct)) +
  geom_col(fill = "darkorange") +
  geom_text(
    aes(label = sprintf("%.1f%%", pct)),
    vjust = -0.3,
    size = 2
  ) +
  facet_wrap(~ Platform, scales = "free_y") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 90, hjust = 1)) +
  labs(
    title = "Social Media Frequency Use (Percentages)",
    x = NULL,
    y = "Percentages"
  ) +
  scale_y_continuous(expand = expansion(mult = c(0, 0.15)))

## 2.2 Platform use per purpose (from multiple choice var DIG03)

# Count "YES" per platform × purpose
data_long_uses <- data_platform_use %>%
  dplyr::filter(Response == "Yes") %>%
  dplyr::group_by(Platform, Purpose) %>%
  dplyr::summarise(n = n(), .groups = "drop")

ggplot(data_long_uses, aes(x = Purpose, y = n)) +
  geom_col(fill = "darkorange") +
  geom_text(
    aes(label = n),
    vjust = -0.3,
    size = 2
  ) +
  facet_wrap(~ Platform, scales = "free_y") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 90, hjust = 1)) +
  labs(
    title = "Uses of Social Media Platforms (Counts)",
    x = NULL,
    y = "Count"
  ) +
  scale_y_continuous(expand = expansion(mult = c(0, 0.15)))

# Percentage "YES" per platform × purpose
data_long_uses_pct <- data_platform_use %>%
  dplyr::filter(Response == "Yes") %>%
  dplyr::group_by(Platform, Purpose) %>%
  dplyr::summarise(n = n(), .groups = "drop") %>%
  dplyr::group_by(Platform) %>%
  dplyr::mutate(pct = 100 * n / sum(n)) %>%
  dplyr::ungroup()

ggplot(data_long_uses_pct, aes(x = Purpose, y = pct)) +
  geom_col(fill = "darkorange") +
  geom_text(
    aes(label = sprintf("%.1f%%", pct)),
    vjust = -0.3,
    size = 2
  ) +
  facet_wrap(~ Platform, scales = "free_y") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 90, hjust = 1)) +
  labs(
    title = "Uses of Social Media Platforms (Percentages)",
    x = NULL,
    y = "Percentages"
  ) +
  scale_y_continuous(expand = expansion(mult = c(0, 0.15)))

Sociopolitical variables and platform use

## 2.3 Indicators: political and sociopolitical use per platform
# define data_any from EUPeopleNet for safety
data_any <- EUPeopleNet %>%
  dplyr::select(dplyr::starts_with("dig03_"))

labels_use <- c(
  "friends", "family", "inf_socially", "sup_soc_causes",
  "inf_pol", "sup_pol_causes", "connect_profess",
  "promote_profess", "other"
)

purpose_suffixes <- 1:9

for (i in seq_along(labels_use)) {
  pattern_i <- paste0("_", purpose_suffixes[i], "$")
  cols_i <- grep(pattern_i, names(data_any), value = TRUE)
  
  if (length(cols_i) > 0) {
    data_any[[labels_use[i]]] <- ifelse(
      rowSums(data_any[, cols_i], na.rm = TRUE) > 0, 1, 0
    )
  }
}

# indexes
data_any <- data_any %>%
  mutate(
    PolInf_smed = ifelse(inf_pol == 1, 1, 0),
    PolSup_smed = ifelse(sup_pol_causes == 1, 1, 0),
    PolInfSup_smed = ifelse(inf_pol == 1 | sup_pol_causes == 1, 1, 0),
    PolSocial_smed = ifelse(
      inf_socially == 1 | sup_soc_causes == 1 |
        inf_pol == 1 | sup_pol_causes == 1,
      1, 0
    )
  ) %>%
  mutate(
    across(
      c(PolInf_smed, PolSup_smed, PolSocial_smed, PolInfSup_smed),
      ~ factor(.x, levels = c(0, 1), labels = c("No", "Yes"))
    )
  )

# single graphs
ggplot(data_any, aes(x = PolInf_smed)) +
  geom_bar(fill = "darkgreen") +
  theme_minimal() +
  labs(
    title = "Use of Social Media to Inform Oneself Politically (Any Platform)",
    x = NULL,
    y = "Count"
  )

ggplot(data_any, aes(x = PolSup_smed)) +
  geom_bar(fill = "darkgreen") +
  theme_minimal() +
  labs(
    title = "Use of Social Media to Support Political Causes (Any Platform)",
    x = NULL,
    y = "Count"
  )

ggplot(data_any, aes(x = PolSocial_smed)) +
  geom_bar(fill = "darkgreen") +
  theme_minimal() +
  labs(
    title = "Use of Social Media for Social/Political Information or Support",
    x = NULL,
    y = "Count"
  )

# Facet with all indicators
data_long_2 <- data_any %>%
  tidyr::pivot_longer(
    cols  = c(PolInf_smed, PolSup_smed, PolSocial_smed, PolInfSup_smed),
    names_to = "Indicator",
    values_to = "Value"
  )

ggplot(data_long_2, aes(x = Value)) +
  geom_bar(fill = "darkorange") +
  facet_wrap(~ Indicator, scales = "free_y") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 90, hjust = 1)) +
  labs(
    title = "Political/Social Uses of Social Media (Any Platform)",
    x = NULL,
    y = "Count"
  )

Sociopolitical variables descriptives

## 2.4 sociopolitical descriptives (from data_MP)

# age
ggplot(data_MP, aes(x = Age)) +
  geom_histogram(binwidth = 5, fill = "darkorange", color = "white") +
  theme_minimal() +
  labs(
    title = "Age",
    x = "How old are you?",
    y = "Count"
  ) +
  theme(axis.text.x = element_text(angle = 90, hjust = 1))

# Gender
ggplot(data_MP, aes(x = Sex)) +
  geom_bar(fill = "darkorange") +
  theme_minimal() +
  labs(
    title = "Sex",
    x = "Sex",
    y = "Count"
  ) +
  theme(axis.text.x = element_text(angle = 90, hjust = 1))

# Vote in general elections (2022) 
ggplot(data_MP %>% filter(!is.na(Vote)), aes(x = Vote)) +
  geom_bar(fill = "darkorange") +
  theme_minimal() +
  labs(
    title = "Vote in the Last National Elections (Italy)",
    x = "Which party did you vote for in the last national elections?",
    y = "Count"
  ) +
  theme(axis.text.x = element_text(angle = 90, hjust = 1))

# Left-Right ideological placement (plus do not placed)
ggplot(data_MP %>% filter(!is.na(Left_Right)), aes(x = Left_Right)) +
  geom_bar(fill = "darkorange") +
  theme_minimal() +
  labs(
    title = "Left–Right self-location",
    x = "Left–Right",
    y = "Count"
  ) +
  theme(axis.text.x = element_text(angle = 90, hjust = 1))

# Political interest
ggplot(data_MP, aes(x = Pol_int)) +
  geom_bar(fill = "darkorange") +
  theme_minimal() +
  labs(
    title = "Political interest",
    x = "Political interest",
    y = "Count"
  ) +
  theme(axis.text.x = element_text(angle = 90, hjust = 1))

# Information disagreement exposure
ggplot(data_MP, aes(x = Inf_disagr)) +
  geom_bar(fill = "darkorange") +
  theme_minimal() +
  labs(
    title = "Frequency of exposure to information you disagree with (online)",
    x = "How often do you read, watch or listen to something you disagree with?",
    y = "Count"
  ) +
  theme(axis.text.x = element_text(angle = 90, hjust = 1))

PCA

PCA preparation

# 4. PCA Preparation ----------------------------------------------------

# 4.1 Select variables: 8 supplementary qualitative + 8 quantitative active
data_PCA1 <- data_MP %>%
  dplyr::select(
    Age_cat, Vote, Sex, Left_Right, Pol_int,
    Inf_disagr, Inf_check, Inf_confirm,
    YouTube, WhatsApp, Twitter_X, Instagram,
    TikTok, Facebook, Linkedin, Telegram
  )

# 4.2 Recoding to fit with ES recoding 

data_PCA1 <- data_PCA1 %>%
  mutate(
    Left_Right = recode(
      as.character(Left_Right),
      
      "0"  = "Ext_left",
      "1"  = "Ext_left",
      
      "2"  = "Left",
      "3"  = "Left",
      
      "4"  = "Center",
      "5"  = "Center",
      "6"  = "Center",
      
      "7"  = "Right",
      "8"  = "Right",
      
      "9"  = "Ext_right",
      "10" = "Ext_right",
      
      "Not placed" = "No_position",
      
      .default = NA_character_
    ),
    
    Left_Right = factor(
      Left_Right,
      levels = c("Ext_left", "Left", "Center", "Right", "Ext_right", "No_position")
    )
  )

# 5. Data Suitability Tests for the PCA ---------------------------------

# 5.0 Correlation matrix of platform variables
cor_matrix <- cor(
  data_PCA1[, 9:16],
  use = "pairwise.complete.obs"
)

# 5.1 Kaiser–Meyer–Olkin (KMO) Measure
psych::KMO(cor_matrix)
Kaiser-Meyer-Olkin factor adequacy
Call: psych::KMO(r = cor_matrix)
Overall MSA =  0.84
MSA for each item = 
  YouTube  WhatsApp Twitter_X Instagram    TikTok  Facebook  Linkedin  Telegram 
     0.89      0.72      0.81      0.83      0.87      0.84      0.84      0.87 
# 5.2 Bartlett’s Test of Sphericity (to test whether correlation matrix differs from identity matrix)

psych::cortest.bartlett(cor_matrix, n = nrow(data_PCA1))
$chisq
[1] 2351.818

$p.value
[1] 0

$df
[1] 28
# 5.3 Multicollinearity and Redundancy (check for variables where r > 0.9)
round(cor_matrix, 2)
          YouTube WhatsApp Twitter_X Instagram TikTok Facebook Linkedin
YouTube      1.00     0.22      0.33      0.31   0.36     0.20     0.30
WhatsApp     0.22     1.00      0.07      0.36   0.15     0.28     0.11
Twitter_X    0.33     0.07      1.00      0.32   0.45     0.16     0.53
Instagram    0.31     0.36      0.32      1.00   0.40     0.33     0.35
TikTok       0.36     0.15      0.45      0.40   1.00     0.21     0.41
Facebook     0.20     0.28      0.16      0.33   0.21     1.00     0.21
Linkedin     0.30     0.11      0.53      0.35   0.41     0.21     1.00
Telegram     0.33     0.16      0.49      0.40   0.41     0.20     0.44
          Telegram
YouTube       0.33
WhatsApp      0.16
Twitter_X     0.49
Instagram     0.40
TikTok        0.41
Facebook      0.20
Linkedin      0.44
Telegram      1.00
caret::findCorrelation(cor_matrix, cutoff = 0.9)
integer(0)

PCA Estimation & visualization

# 6. PCA Estimation and Visualization -----------------------------------

# Here the 8 active variables are platforms,the 8 supplementary variables are: Age_cat, Vote, Sex, Left_Right, Pol_int, Inf_disagr, Inf_check, Inf_confirm

PCA1_result <- FactoMineR::PCA(
  data_PCA1,
  quali.sup = 1:8,   
  graph     = FALSE
)
Warning in FactoMineR::PCA(data_PCA1, quali.sup = 1:8, graph = FALSE): Missing
values are imputed by the mean of the variable: you should use the imputePCA
function of the missMDA package
# 6.1 Summary of eigenvalues, contributions, cos², etc.
summary(PCA1_result)

Call:
FactoMineR::PCA(X = data_PCA1, quali.sup = 1:8, graph = FALSE) 


Eigenvalues
                       Dim.1   Dim.2   Dim.3   Dim.4   Dim.5   Dim.6   Dim.7
Variance               3.159   1.207   0.768   0.698   0.620   0.572   0.518
% of var.             39.491  15.090   9.595   8.722   7.749   7.150   6.474
Cumulative % of var.  39.491  54.581  64.176  72.898  80.647  87.797  94.271
                       Dim.8
Variance               0.458
% of var.              5.729
Cumulative % of var. 100.000

Individuals (the 10 first)
                            Dist    Dim.1    ctr   cos2    Dim.2    ctr   cos2
1                       |  0.000 |  0.000  0.000  0.222 |  0.000  0.000  0.956
2                       |  2.944 |  1.380  0.046  0.220 | -0.175  0.002  0.004
3                       |  3.457 |  2.479  0.150  0.514 |  1.286  0.105  0.138
4                       |  1.917 | -0.564  0.008  0.087 |  0.551  0.019  0.083
5                       |  3.821 |  0.725  0.013  0.036 | -0.106  0.001  0.001
6                       |  2.831 | -1.359  0.045  0.230 | -0.369  0.009  0.017
7                       |  2.084 | -1.008  0.025  0.234 |  0.477  0.014  0.052
8                       |  3.095 |  2.772  0.187  0.802 | -0.867  0.048  0.078
9                       |  0.537 | -0.138  0.000  0.066 |  0.033  0.000  0.004
10                      |  3.723 |  1.833  0.082  0.242 | -1.668  0.177  0.201
                           Dim.3    ctr   cos2  
1                       |  0.000  0.000  0.002 |
2                       | -1.875  0.352  0.406 |
3                       |  0.837  0.070  0.059 |
4                       | -0.767  0.059  0.160 |
5                       |  2.811  0.791  0.541 |
6                       |  1.932  0.374  0.466 |
7                       |  0.679  0.046  0.106 |
8                       | -0.337  0.011  0.012 |
9                       | -0.098  0.001  0.033 |
10                      |  0.635  0.040  0.029 |

Variables
                           Dim.1    ctr   cos2    Dim.2    ctr   cos2    Dim.3
YouTube                 |  0.601 11.419  0.361 |  0.040  0.136  0.002 |  0.581
WhatsApp                |  0.389  4.791  0.151 |  0.714 42.224  0.510 |  0.252
Twitter_X               |  0.704 15.682  0.495 | -0.406 13.640  0.165 | -0.074
Instagram               |  0.688 14.987  0.473 |  0.309  7.914  0.096 | -0.036
TikTok                  |  0.695 15.276  0.483 | -0.163  2.195  0.026 |  0.093
Facebook                |  0.459  6.671  0.211 |  0.523 22.686  0.274 | -0.545
Linkedin                |  0.693 15.183  0.480 | -0.308  7.847  0.095 | -0.231
Telegram                |  0.711 15.991  0.505 | -0.201  3.360  0.041 | -0.036
                           ctr   cos2  
YouTube                 43.965  0.337 |
WhatsApp                 8.253  0.063 |
Twitter_X                0.714  0.005 |
Instagram                0.166  0.001 |
TikTok                   1.138  0.009 |
Facebook                38.676  0.297 |
Linkedin                 6.923  0.053 |
Telegram                 0.165  0.001 |

Supplementary categories (the 10 first)
                             Dist     Dim.1    cos2  v.test     Dim.2    cos2
18_24                   |   1.418 |   1.108   0.611   6.486 |  -0.233   0.027
25_34                   |   0.891 |   0.796   0.798   5.984 |  -0.138   0.024
35_44                   |   0.816 |   0.747   0.839   6.248 |   0.121   0.022
45_54                   |   0.239 |   0.127   0.280   1.255 |   0.182   0.579
55_64                   |   0.334 |  -0.268   0.644  -2.525 |   0.138   0.172
65_+                    |   0.992 |  -0.930   0.879 -11.961 |  -0.149   0.023
+Europa                 |   0.623 |   0.043   0.005   0.155 |  -0.203   0.106
Alleanza Verdi-Sinistra |   0.445 |   0.392   0.776   1.836 |  -0.092   0.042
Azione-Italia Viva      |   0.419 |  -0.075   0.032  -0.416 |  -0.189   0.205
Did not vote            |   0.240 |  -0.090   0.141  -0.716 |  -0.198   0.681
                         v.test     Dim.3    cos2  v.test  
18_24                    -2.203 |   0.592   0.174   7.028 |
25_34                    -1.681 |   0.077   0.007   1.175 |
35_44                     1.634 |  -0.085   0.011  -1.441 |
45_54                     2.922 |  -0.013   0.003  -0.256 |
55_64                     2.111 |  -0.076   0.052  -1.454 |
65_+                     -3.098 |  -0.092   0.009  -2.411 |
+Europa                  -1.169 |   0.110   0.031   0.799 |
Alleanza Verdi-Sinistra  -0.695 |  -0.033   0.006  -0.315 |
Azione-Italia Viva       -1.705 |   0.115   0.076   1.302 |
Did not vote             -2.544 |   0.070   0.086   1.132 |
# 6.1.1 Variables relation to Dim1 and Dim2
PCA1_desc <- FactoMineR::dimdesc(PCA1_result, axes = 1:2, proba = 0.05)
PCA1_desc$Dim.1

Link between the variable and the continuous variables (R-square)
=================================================================================
          correlation       p.value
Telegram    0.7107833 1.041739e-200
Twitter_X   0.7038717 3.480574e-195
TikTok      0.6946969 4.276470e-188
Linkedin    0.6925912 1.661726e-186
Instagram   0.6881031 3.654681e-183
YouTube     0.6006333 2.210095e-128
Facebook    0.4590983  8.225746e-69
WhatsApp    0.3890403  2.895111e-48

Link between the variable and the categorical variable (1-way anova)
=============================================
                    R2      p.value
Age_cat     0.16327212 6.198418e-48
Inf_check   0.06810038 6.392291e-19
Inf_disagr  0.06628292 2.200328e-18
Inf_confirm 0.05654758 1.564022e-15
Left_Right  0.02422511 1.796380e-05
Vote        0.02712709 9.909615e-05

Link between variable and the categories of the categorical variables
================================================================
                                     Estimate      p.value
Age_cat=18_24                       0.8448049 6.314004e-11
Age_cat=35_44                       0.4837189 3.139509e-10
Age_cat=25_34                       0.5330018 1.714502e-09
Inf_check=Inf_check_Very often      0.8497859 1.457769e-08
Inf_disagr=Inf_disagr_Very often    0.8356138 7.353664e-08
Inf_disagr=Inf_disagr_Often         0.4127128 1.234073e-05
Inf_confirm=Inf_confirm_Very often  0.6980323 1.294134e-05
Inf_check=Inf_check_Often           0.3993228 1.547763e-04
Vote=Forza Italia                   0.8322058 3.113801e-04
Inf_confirm=Inf_confirm_Often       0.3868089 1.154004e-03
Left_Right=Ext_right                0.3924648 1.316871e-03
Vote=Movimento 5 Stelle             0.2151232 9.891616e-03
Left_Right=Right                    0.2026920 2.072619e-02
Sex=Non-binary                      1.0454188 4.902130e-02
Left_Right=No_position             -0.3202688 3.374237e-02
Age_cat=55_64                      -0.5312895 1.150529e-02
Left_Right=Left                    -0.3648603 3.203779e-03
Vote=Partito Democratico           -0.4564384 2.558011e-04
Inf_confirm=Inf_confirm_Rarely     -0.4923457 4.336972e-06
Inf_disagr=Inf_disagr_Rarely       -0.4953230 3.847349e-06
Inf_check=Inf_check_Rarely         -0.5263152 5.858813e-07
Inf_disagr=Inf_disagr_Never        -0.7667999 2.008965e-08
Inf_check=Inf_check_Never          -0.7816178 1.656179e-08
Inf_confirm=Inf_confirm_Never      -0.7632705 2.767379e-09
Age_cat=65_+                       -1.1933958 8.630145e-35
PCA1_desc$Dim.2

Link between the variable and the continuous variables (R-square)
=================================================================================
          correlation       p.value
WhatsApp    0.7139505 2.701010e-203
Facebook    0.5233166  2.280502e-92
Instagram   0.3090819  3.383618e-30
TikTok     -0.1627844  3.519636e-09
Telegram   -0.2013846  2.266075e-13
Linkedin   -0.3077723  6.067580e-30
Twitter_X  -0.4057790  9.692650e-53

Link between the variable and the categorical variable (1-way anova)
=============================================
                    R2      p.value
Sex        0.037135620 2.156569e-11
Age_cat    0.020498489 6.094449e-05
Vote       0.022809086 9.041707e-04
Left_Right 0.011570927 1.961848e-02
Inf_check  0.008981723 1.971118e-02

Link between variable and the categories of the categorical variables
================================================================
                                 Estimate      p.value
Sex=Female                      0.3038516 2.406963e-12
Age_cat=45_54                   0.1952296 3.438103e-03
Left_Right=Ext_left             0.2183157 2.284974e-02
Vote=Partito Democratico        0.1603081 3.239774e-02
Age_cat=55_64                   0.1515135 3.474535e-02
Age_cat=18_24                  -0.2195176 2.757226e-02
Vote=Did not vote              -0.1609720 1.091000e-02
Left_Right=No_position         -0.1506509 1.028280e-02
Inf_check=Inf_check_Very often -0.2023231 1.938446e-03
Age_cat=65_+                   -0.1358246 1.922577e-03
Vote=Other party               -0.3415773 1.809898e-03
Sex=Male                       -0.1192441 4.004205e-12
# 6.2 Initial biplot – active variables (social media platforms’ use)
p <- factoextra::fviz_pca_var(
  PCA1_result,
  col.var       = "contrib",
  gradient.cols = c("#00AFBB", "#E7B800", "#FC4E07"),
  repel         = TRUE
)
Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
ℹ Please use `linewidth` instead.
ℹ The deprecated feature was likely used in the ggpubr package.
  Please report the issue at <https://github.com/kassambara/ggpubr/issues>.
Warning: `aes_string()` was deprecated in ggplot2 3.0.0.
ℹ Please use tidy evaluation idioms with `aes()`.
ℹ See also `vignette("ggplot2-in-packages")` for more information.
ℹ The deprecated feature was likely used in the factoextra package.
  Please report the issue at <https://github.com/kassambara/factoextra/issues>.
p

Centroids of Supplementary Qualitative Variables in the PCA of Social Media Platforms

# 7. Categorical Supplementary Variables (Centroids) --------------------

# Extract centroides of qualitative supplementary variables
get_sup_coords <- function(pca_result, variable_name, dims = 2) {
  # 1) data extraction
  quali_sup_data <- pca_result$call$quali.sup
  if ("quali.sup" %in% names(quali_sup_data)) {
    quali_sup_data <- quali_sup_data$quali.sup
  }
  
  # 2) check variables
  if (!variable_name %in% names(quali_sup_data)) {
    stop(paste("Variable", variable_name, "not found among supplementary qualitative variables."))
  }
  
  # 3) centroids (avg per category)
  bary <- pca_result$call$quali.sup$barycentre
  
  # Rows selection for variables categories
  var_categories <- levels(quali_sup_data[[variable_name]])
  bary_var <- bary[rownames(bary) %in% var_categories, , drop = FALSE]
  
  if (nrow(bary_var) == 0) {
    stop(paste("No barycentres found for variable", variable_name))
  }
  
  # 4) Avg and st.dev used in PCA
  means <- pca_result$call$centre
  sds   <- pca_result$call$ecart.type
  
  # Centroides standardization
  bary_scaled <- sweep(bary_var, 2, means, "-")
  bary_scaled <- sweep(bary_scaled, 2, sds, "/")
  
  # 5) PCA axis projection
  loadings  <- pca_result$var$coord
  projected <- as.matrix(bary_scaled) %*% as.matrix(loadings[, 1:dims])
  
  # 6) Output in data frame
  projected_df <- as.data.frame(projected)
  colnames(projected_df) <- paste0("Dim.", 1:dims)
  projected_df$Category  <- rownames(projected_df)
  projected_df$Variable  <- variable_name
  
  return(projected_df)
}

# Centroides coordinates per each supplementary variable
age_coords      <- get_sup_coords(PCA1_result, "Age_cat")
vote_coords     <- get_sup_coords(PCA1_result, "Vote")
Pol_int_coords  <- get_sup_coords(PCA1_result, "Pol_int")
LRight_coords   <- get_sup_coords(PCA1_result, "Left_Right")
Sex_coords      <- get_sup_coords(PCA1_result, "Sex")
infdis_coords   <- get_sup_coords(PCA1_result, "Inf_disagr")
infcheck_coords <- get_sup_coords(PCA1_result, "Inf_check")
infconf_coords  <- get_sup_coords(PCA1_result, "Inf_confirm")

# 7.1 Biplot with vote centroids
p + 
  geom_point(
    data = vote_coords,
    aes(x = Dim.1, y = Dim.2),
    color = "darkblue", size = 3, shape = 20
  ) +
  ggrepel::geom_text_repel(
    data = vote_coords,
    aes(x = Dim.1, y = Dim.2, label = Category),
    color = "darkblue",
    size  = 3.5
  )

# 7.2 Biplot with age centroids
p + 
  geom_point(
    data = age_coords,
    aes(x = Dim.1, y = Dim.2),
    color = "darkblue", size = 3, shape = 20
  ) +
  ggrepel::geom_text_repel(
    data = age_coords,
    aes(x = Dim.1, y = Dim.2, label = Category),
    color = "darkblue",
    size  = 3.5
  )

# 7.4 Biplot with political interest centroids
p + 
  geom_point(
    data = Pol_int_coords,
    aes(x = Dim.1, y = Dim.2),
    color = "darkblue", size = 3, shape = 20
  ) +
  ggrepel::geom_text_repel(
    data = Pol_int_coords,
    aes(x = Dim.1, y = Dim.2, label = Category),
    color = "darkblue",
    size  = 3.5
  )

# 7.5 Biplot with ideological placement centroids
p + 
  geom_point(
    data = LRight_coords,
    aes(x = Dim.1, y = Dim.2),
    color = "darkblue", size = 3, shape = 20
  ) +
  ggrepel::geom_text_repel(
    data = LRight_coords,
    aes(x = Dim.1, y = Dim.2, label = Category),
    color = "darkblue",
    size  = 3.5
  )

# 7.6 Biplot with gender centroids
p + 
  geom_point(
    data = Sex_coords,
    aes(x = Dim.1, y = Dim.2),
    color = "darkblue", size = 3, shape = 20
  ) +
  ggrepel::geom_text_repel(
    data = Sex_coords,
    aes(x = Dim.1, y = Dim.2, label = Category),
    color = "darkblue",
    size  = 3.5
  )

# 7.7 Biplot with information disagreement centroids
p + 
  geom_point(
    data = infdis_coords,
    aes(x = Dim.1, y = Dim.2),
    color = "darkblue", size = 3, shape = 20
  ) +
  ggrepel::geom_text_repel(
    data = infdis_coords,
    aes(x = Dim.1, y = Dim.2, label = Category),
    color = "darkblue",
    size  = 3.5
  )

# 7.8 Biplot with inf_check centroids
p + 
  geom_point(
    data = infcheck_coords,
    aes(x = Dim.1, y = Dim.2),
    color = "darkblue", size = 3, shape = 20
  ) +
  ggrepel::geom_text_repel(
    data = infcheck_coords,
    aes(x = Dim.1, y = Dim.2, label = Category),
    color = "darkblue",
    size  = 3.5
  )

# 7.9 Biplot with info_confirmation centroids
p + 
  geom_point(
    data = infconf_coords,
    aes(x = Dim.1, y = Dim.2),
    color = "darkblue", size = 3, shape = 20
  ) +
  ggrepel::geom_text_repel(
    data = infconf_coords,
    aes(x = Dim.1, y = Dim.2, label = Category),
    color = "darkblue",
    size  = 3.5
  )

Principal Component Analysis Including Numerical Supplementary Variables: Political and Social Uses of Social Media

# 8. Numerical Supplementary Variables: Political/Social Uses of Social Media ----

# New dataset for PCA with following variables: inf_socially, inf_pol, sup_soc_causes, sup_pol_causes 

data_PCA2 <- data_PCA1 %>%
  dplyr::bind_cols(
    data_any %>%
      dplyr::select(inf_socially, inf_pol, sup_soc_causes, sup_pol_causes)
  ) %>%
  # check numerical
  dplyr::mutate(
    dplyr::across(
      c(inf_socially, inf_pol, sup_soc_causes, sup_pol_causes),
      ~ as.numeric(.x)
    )
  )

# Check
 str(data_PCA2)  
tibble [1,301 × 20] (S3: tbl_df/tbl/data.frame)
 $ Age_cat       : Factor w/ 7 levels "0_17","18_24",..: 5 3 5 5 2 2 6 3 5 3 ...
  ..- attr(*, "label")= chr "EDAD RECODE"
 $ Vote          : Factor w/ 10 levels "+Europa","Alleanza Verdi-Sinistra",..: 7 NA 5 2 10 5 5 6 10 9 ...
 $ Sex           : Factor w/ 3 levels "Male","Female",..: 1 2 2 1 2 1 2 2 2 1 ...
  ..- attr(*, "label")= chr "Which gender do you identify with?"
 $ Left_Right    : Factor w/ 6 levels "Ext_left","Left",..: 3 NA 3 2 NA 3 6 NA 3 3 ...
 $ Pol_int       : Factor w/ 4 levels "Very interested",..: 3 3 4 2 3 2 3 2 3 2 ...
  ..- attr(*, "label")= chr "How interested would you say you are in politics - are you...?"
 $ Inf_disagr    : Factor w/ 5 levels "Very often","Often",..: 5 3 5 2 5 5 4 3 3 3 ...
  ..- attr(*, "label")= chr "Read, watch or listen to something online you disagree with_When looking for new"
 $ Inf_check     : Factor w/ 5 levels "Very often","Often",..: 5 3 5 2 5 5 4 3 3 2 ...
  ..- attr(*, "label")= chr "Check a news source that’s different from what you normally read, watch or lis"
 $ Inf_confirm   : Factor w/ 5 levels "Very often","Often",..: 5 3 5 2 5 5 4 3 3 2 ...
  ..- attr(*, "label")= chr "Try to confirm information you find by searching online for another source_When"
 $ YouTube       : int [1:1301] NA 2 7 3 7 6 6 5 4 6 ...
 $ WhatsApp      : int [1:1301] NA 6 7 6 6 5 5 6 6 5 ...
 $ Twitter_X     : int [1:1301] NA NA NA 1 1 1 1 6 NA 6 ...
 $ Instagram     : int [1:1301] NA 6 7 5 7 5 4 5 3 2 ...
 $ TikTok        : int [1:1301] NA NA 7 1 7 1 1 6 NA 6 ...
 $ Facebook      : int [1:1301] NA 6 7 5 1 1 5 6 5 5 ...
 $ Linkedin      : int [1:1301] NA 6 NA 4 1 1 1 4 NA 1 ...
 $ Telegram      : int [1:1301] NA 5 NA 1 2 1 1 5 NA 7 ...
 $ inf_socially  : num [1:1301] 0 1 0 1 0 0 0 1 1 1 ...
 $ inf_pol       : num [1:1301] 0 1 0 0 0 0 0 1 1 0 ...
 $ sup_soc_causes: num [1:1301] 0 1 0 0 0 0 0 1 0 1 ...
 $ sup_pol_causes: num [1:1301] 0 1 0 0 0 0 0 1 0 0 ...
# NEW PCA estimation
#Active variables: the eight social media platforms 
#Supplementary qualitative variables: Age_cat, Vote, Sex, Left_Right, Pol_int, Inf_disagr, Inf_check, and Inf_confirm.
#Supplementary quantitative variables: inf_socially, inf_pol, sup_soc_causes, and sup_pol_causes.

PCA2_result <- FactoMineR::PCA(
  data_PCA2,
  quanti.sup = 17:20,  # supplementari numeriche
  quali.sup  = 1:8,    # supplementari qualitative
  graph      = FALSE
)
Warning in FactoMineR::PCA(data_PCA2, quanti.sup = 17:20, quali.sup = 1:8, :
Missing values are imputed by the mean of the variable: you should use the
imputePCA function of the missMDA package
# Biplot of active variables with numerical supplementary variables
factoextra::fviz_pca_var(
  PCA2_result,
  col.var       = "contrib",
  gradient.cols = c("#00AFBB", "#E7B800", "#FC4E07"),
  repel         = TRUE
)

Factor Analysis of online and offline political participation

# 9. Factor Analysis of online and offline political participation ----

# 9.0 Dictionary: original items -> new variable names -> activities ----
participation_dict <- tibble::tibble(
  var_bin = c(
    # --- ONLINE (13) ---
    "parton_1",  "parton_2",  "parton_3",  "parton_4",  "parton_5",
    "parton_6",  "parton_7",  "parton_8",  "parton_9",  "parton_10",
    "parton_11", "parton_12", "parton_13",
    # --- OFFLINE (13) ---
    "partoff_1",  "partoff_2",  "partoff_3",  "partoff_4",  "partoff_5",
    "partoff_6",  "partoff_7",  "partoff_8",  "partoff_9",  "partoff_10",
    "partoff_11", "partoff_12", "partoff_13"
  ),
  new_name = c(
    # --- ONLINE ---
    "pol_inf_on",      # parton_1  – actively searched for political information online
    "liked_on",        # parton_2  – liked/followed political content
    "shared_on",       # parton_3  – shared/retweeted political content
    "posted_on",       # parton_4  – posted own political content
    "discuss_on",      # parton_5  – discussed politics online
    "comment_on",      # parton_6  – commented on political content
    "profile_on",      # parton_7  – changed profile picture/status for political reasons
    "vol_party_on",    # parton_8  – volunteered online for party/candidate
    "donat_party_on",  # parton_9  – donated money online to party/candidate
    "donat_NGO_on",    # parton_10 – donated money online to NGO/association
    "vol_social_on",   # parton_11 – volunteered online for NGO/association
    "contact_on",      # parton_12 – contacted politician/official online
    "petition_on",     # parton_13 – signed online petition
    # --- OFFLINE ---
    "pol_meet_off",      # partoff_1  – attended political meeting/rally
    "strike_off",        # partoff_2  – took part in strike
    "demonst_off",       # partoff_3  – took part in demonstration/march
    "org_demonst_off",   # partoff_4  – helped organise demonstration
    "discuss_off",       # partoff_5  – discussed politics face-to-face
    "vol_party_off",     # partoff_6  – volunteered offline for party/candidate
    "donat_party_off",   # partoff_7  – donated money offline to party/candidate
    "donat_NGO_off",     # partoff_8  – donated money offline to NGO/association
    "contact_off",       # partoff_9  – contacted politician/official offline
    "read_campaign_off", # partoff_10 – read leaflets/campaign material
    "petition_off",      # partoff_11 – signed paper petition
    "boycott_off",       # partoff_12 – (boy)cott/buycott participation
    "button_off"         # partoff_13 – wore badge/button/sticker
  ),
  activity = c(
    # --- ONLINE (descrizione sintetica) ---
    "Search political information online",
    "Like/follow political content",
    "Share/retweet political content",
    "Post own political content",
    "Discuss politics online",
    "Comment on political content",
    "Change profile/status for politics",
    "Volunteer online for party/candidate",
    "Donate money online to party/candidate",
    "Donate money online to NGO/association",
    "Volunteer online for NGO/association",
    "Contact politician/official online",
    "Sign online petition",
    # --- OFFLINE ---
    "Attend political meeting/rally",
    "Take part in strike",
    "Take part in demonstration/march",
    "Help organise demonstration",
    "Discuss politics face-to-face",
    "Volunteer offline for party/candidate",
    "Donate money offline to party/candidate",
    "Donate money offline to NGO/association",
    "Contact politician/official offline",
    "Read leaflets/campaign material",
    "Sign paper petition",
    "Take part in (boy)cott/buycott",
    "Wear badge/button/sticker"
  )
)

# 9.1 Build data_FACTOR with online + offline items ---------------------

data_FACTOR <- EUPeopleNet %>%
  dplyr::mutate(id = dplyr::row_number()) %>%
  dplyr::select(
    id,
    dplyr::all_of(participation_dict$var_bin)
  )

# Values are already 0/1; in case "9 = prefer not to answer" is present, recode to NA
data_FACTOR <- data_FACTOR %>%
  dplyr::mutate(
    dplyr::across(
      -id,
      ~ dplyr::na_if(.x, 9)
    )
  ) %>%
  dplyr::mutate(
    dplyr::across(
      -id,
      ~ as.numeric(.x)
    )
  )

# >>> QUI LA CORREZIONE IMPORTANTE <<<
# new_name = old_name
rename_vec <- stats::setNames(
  participation_dict$var_bin,   # valori = vecchi nomi (parton_1, partoff_1, ...)
  participation_dict$new_name   # nomi  = nuovi nomi (pol_inf_on, pol_meet_off, ...)
)

data_FACTOR <- data_FACTOR %>%
  dplyr::rename(!!!rename_vec)

# 9.2 Prepare and test suitability for Factor Analysis ------------------

# Drop rows with too many missing values (> 50%)
data_FACTOR <- data_FACTOR %>%
  dplyr::filter(
    rowMeans(is.na(dplyr::across(-id))) < 0.5
  )

# List of item variables
part_vars <- setdiff(names(data_FACTOR), "id")

# Correlation matrix (pairwise)
cor_matrix_part <- cor(
  dplyr::select(data_FACTOR, dplyr::all_of(part_vars)),
  use = "pairwise.complete.obs"
)

# KMO
psych::KMO(cor_matrix_part)
Kaiser-Meyer-Olkin factor adequacy
Call: psych::KMO(r = cor_matrix_part)
Overall MSA =  0.92
MSA for each item = 
       pol_inf_on          liked_on         shared_on         posted_on 
             0.89              0.91              0.94              0.95 
       discuss_on        comment_on        profile_on      vol_party_on 
             0.91              0.91              0.95              0.95 
   donat_party_on      donat_NGO_on     vol_social_on        contact_on 
             0.94              0.82              0.95              0.93 
      petition_on      pol_meet_off        strike_off       demonst_off 
             0.92              0.95              0.95              0.94 
  org_demonst_off       discuss_off     vol_party_off   donat_party_off 
             0.94              0.86              0.93              0.94 
    donat_NGO_off       contact_off read_campaign_off      petition_off 
             0.82              0.91              0.93              0.92 
      boycott_off        button_off 
             0.95              0.94 
# Bartlett’s test
psych::cortest.bartlett(
  cor_matrix_part,
  n = nrow(data_FACTOR)
)
$chisq
[1] 10451.93

$p.value
[1] 0

$df
[1] 325
# 9.3 Exploratory Factor Analysis --------------------------------------

# Polychoric correlation (good for binary/ordinal items)
cor_poly <- psych::polychoric(
  dplyr::select(data_FACTOR, dplyr::all_of(part_vars))
)$rho

# Parallel analysis (decide nfactors; here we keep 5 as in Spanish script)
fa.parallel(
  cor_poly,
  n.obs = nrow(data_FACTOR),
  fm    = "minres",
  fa    = "fa"
)

Parallel analysis suggests that the number of factors =  8  and the number of components =  NA 
# EFA with 5 factors, oblimin rotation
efa_result <- psych::fa(
  dplyr::select(data_FACTOR, dplyr::all_of(part_vars)),
  nfactors = 5,
  rotate   = "oblimin",
  fm       = "minres",
  scores   = "regression"
)

# Inspect loadings (only > .30)
print(efa_result$loadings, cutoff = 0.30)

Loadings:
                  MR1    MR2    MR3    MR5    MR4   
pol_inf_on                0.309                0.476
liked_on                  0.509                     
shared_on                 0.555                     
posted_on                 0.540                     
discuss_on                0.708                     
comment_on                0.682                     
profile_on         0.440                            
vol_party_on       0.484                            
donat_party_on     0.333                            
donat_NGO_on                     0.792              
vol_social_on                                       
contact_on                              0.535       
petition_on                                         
pol_meet_off       0.314                0.300       
strike_off         0.455                            
demonst_off        0.617                            
org_demonst_off    0.488                            
discuss_off                                    0.483
vol_party_off      0.687                            
donat_party_off    0.432                            
donat_NGO_off                    0.715              
contact_off                             0.759       
read_campaign_off                              0.408
petition_off       0.393                            
boycott_off                                    0.302
button_off         0.610                            

                 MR1   MR2   MR3   MR5   MR4
SS loadings    2.932 2.130 1.417 1.176 1.148
Proportion Var 0.113 0.082 0.055 0.045 0.044
Cumulative Var 0.113 0.195 0.249 0.294 0.339
# Variance explained and fit indices
efa_result$Vaccounted
                            MR1        MR2        MR3        MR5        MR4
SS loadings           3.5954713 2.58411074 1.68179565 1.60764309 1.32603612
Proportion Var        0.1382874 0.09938887 0.06468445 0.06183243 0.05100139
Cumulative Var        0.1382874 0.23767623 0.30236068 0.36419311 0.41519450
Proportion Explained  0.3330665 0.23937908 0.15579313 0.14892400 0.12283734
Cumulative Proportion 0.3330665 0.57244553 0.72823865 0.87716266 1.00000000
efa_result$TLI
[1] 0.917059
efa_result$RMSEA
     RMSEA      lower      upper confidence 
0.04523795 0.04174861 0.04882587 0.90000000 
# Optional: diagram
psych::fa.diagram(
  efa_result,
  main   = "Exploratory Factor Analysis – Political Participation",
  simple = FALSE
)

# Optional: 2D plot of first two factors
loadings_df <- as.data.frame(efa_result$loadings[1:length(part_vars), ])
loadings_df$variable <- rownames(loadings_df)

ggplot(loadings_df, aes(x = MR1, y = MR2, label = variable)) +
  geom_point(color = "steelblue", size = 3) +
  geom_text(vjust = -0.5, size = 3) +
  geom_hline(yintercept = 0, linetype = "dashed", color = "gray60") +
  geom_vline(xintercept = 0, linetype = "dashed", color = "gray60") +
  theme_minimal() +
  labs(
    title = "Factor Loadings (EFA)",
    x = "Factor 1",
    y = "Factor 2"
  )

# 9.4 Save factor scores and merge with PCA dataset --------------------

# Extract factor scores
factor_scores <- as.data.frame(efa_result$scores)

# Rename factors
factor_scores <- factor_scores %>%
  dplyr::rename(
    Info_Online      = MR1,
    Partisan_mobil   = MR2,
    Civic_Engagement = MR3,
    Protest_Action   = MR4,
    Info_Offline     = MR5
  ) %>%
  dplyr::mutate(id = data_FACTOR$id)

# Merge factor scores into PCA dataset (data_PCA2 -> data_PCA3)
data_PCA3 <- data_PCA2 %>%
  dplyr::mutate(id = dplyr::row_number()) %>%
  dplyr::left_join(factor_scores, by = "id") %>%
  dplyr::select(-id)

New PCA with factors as supplementary numerical variables

# 10. New PCA with factors as supplementary numerical variables ---------

# Optional check to see if variables exist
names(data_PCA3)
 [1] "Age_cat"          "Vote"             "Sex"              "Left_Right"      
 [5] "Pol_int"          "Inf_disagr"       "Inf_check"        "Inf_confirm"     
 [9] "YouTube"          "WhatsApp"         "Twitter_X"        "Instagram"       
[13] "TikTok"           "Facebook"         "Linkedin"         "Telegram"        
[17] "inf_socially"     "inf_pol"          "sup_soc_causes"   "sup_pol_causes"  
[21] "Info_Online"      "Partisan_mobil"   "Civic_Engagement" "Info_Offline"    
[25] "Protest_Action"  
# vectors of indexes FactoMineR::PCA
quali_sup_idx <- c(
  which(names(data_PCA3) == "Age_cat"),
  which(names(data_PCA3) == "Vote"),
  which(names(data_PCA3) == "Sex"),
  which(names(data_PCA3) == "Left_Right"),
  which(names(data_PCA3) == "Pol_int"),
  which(names(data_PCA3) == "Inf_disagr"),
  which(names(data_PCA3) == "Inf_check"),
  which(names(data_PCA3) == "Inf_confirm")
)

quanti_sup_idx <- c(
  which(names(data_PCA3) == "inf_socially"),
  which(names(data_PCA3) == "inf_pol"),
  which(names(data_PCA3) == "sup_soc_causes"),
  which(names(data_PCA3) == "sup_pol_causes"),
  which(names(data_PCA3) == "Info_Online"),
  which(names(data_PCA3) == "Partisan_mobil"),
  which(names(data_PCA3) == "Civic_Engagement"),
  which(names(data_PCA3) == "Protest_Action"),
  which(names(data_PCA3) == "Info_Offline")
)

# PCA3: active platforms, specific uses + supplementary factors
PCA3_result <- FactoMineR::PCA(
  data_PCA3,
  quali.sup = quali_sup_idx,
  quanti.sup = quanti_sup_idx,
  graph = FALSE
)
Warning in FactoMineR::PCA(data_PCA3, quali.sup = quali_sup_idx, quanti.sup =
quanti_sup_idx, : Missing values are imputed by the mean of the variable: you
should use the imputePCA function of the missMDA package
# Summary of the PCA:
summary(PCA3_result)

Call:
FactoMineR::PCA(X = data_PCA3, quanti.sup = quanti_sup_idx, quali.sup = quali_sup_idx,  
     graph = FALSE) 


Eigenvalues
                       Dim.1   Dim.2   Dim.3   Dim.4   Dim.5   Dim.6   Dim.7
Variance               3.159   1.207   0.768   0.698   0.620   0.572   0.518
% of var.             39.491  15.090   9.595   8.722   7.749   7.150   6.474
Cumulative % of var.  39.491  54.581  64.176  72.898  80.647  87.797  94.271
                       Dim.8
Variance               0.458
% of var.              5.729
Cumulative % of var. 100.000

Individuals (the 10 first)
                            Dist    Dim.1    ctr   cos2    Dim.2    ctr   cos2
1                       |  0.000 |  0.000  0.000  0.222 |  0.000  0.000  0.956
2                       |  2.944 |  1.380  0.046  0.220 | -0.175  0.002  0.004
3                       |  3.457 |  2.479  0.150  0.514 |  1.286  0.105  0.138
4                       |  1.917 | -0.564  0.008  0.087 |  0.551  0.019  0.083
5                       |  3.821 |  0.725  0.013  0.036 | -0.106  0.001  0.001
6                       |  2.831 | -1.359  0.045  0.230 | -0.369  0.009  0.017
7                       |  2.084 | -1.008  0.025  0.234 |  0.477  0.014  0.052
8                       |  3.095 |  2.772  0.187  0.802 | -0.867  0.048  0.078
9                       |  0.537 | -0.138  0.000  0.066 |  0.033  0.000  0.004
10                      |  3.723 |  1.833  0.082  0.242 | -1.668  0.177  0.201
                           Dim.3    ctr   cos2  
1                       |  0.000  0.000  0.002 |
2                       | -1.875  0.352  0.406 |
3                       |  0.837  0.070  0.059 |
4                       | -0.767  0.059  0.160 |
5                       |  2.811  0.791  0.541 |
6                       |  1.932  0.374  0.466 |
7                       |  0.679  0.046  0.106 |
8                       | -0.337  0.011  0.012 |
9                       | -0.098  0.001  0.033 |
10                      |  0.635  0.040  0.029 |

Variables
                           Dim.1    ctr   cos2    Dim.2    ctr   cos2    Dim.3
YouTube                 |  0.601 11.419  0.361 |  0.040  0.136  0.002 |  0.581
WhatsApp                |  0.389  4.791  0.151 |  0.714 42.224  0.510 |  0.252
Twitter_X               |  0.704 15.682  0.495 | -0.406 13.640  0.165 | -0.074
Instagram               |  0.688 14.987  0.473 |  0.309  7.914  0.096 | -0.036
TikTok                  |  0.695 15.276  0.483 | -0.163  2.195  0.026 |  0.093
Facebook                |  0.459  6.671  0.211 |  0.523 22.686  0.274 | -0.545
Linkedin                |  0.693 15.183  0.480 | -0.308  7.847  0.095 | -0.231
Telegram                |  0.711 15.991  0.505 | -0.201  3.360  0.041 | -0.036
                           ctr   cos2  
YouTube                 43.965  0.337 |
WhatsApp                 8.253  0.063 |
Twitter_X                0.714  0.005 |
Instagram                0.166  0.001 |
TikTok                   1.138  0.009 |
Facebook                38.676  0.297 |
Linkedin                 6.923  0.053 |
Telegram                 0.165  0.001 |

Supplementary continuous variables
                           Dim.1   cos2    Dim.2   cos2    Dim.3   cos2  
inf_socially            |  0.330  0.109 |  0.112  0.013 |  0.046  0.002 |
inf_pol                 |  0.348  0.121 |  0.037  0.001 |  0.096  0.009 |
sup_soc_causes          |  0.356  0.127 |  0.066  0.004 |  0.052  0.003 |
sup_pol_causes          |  0.359  0.129 |  0.049  0.002 |  0.055  0.003 |
Info_Online             |  0.264  0.070 | -0.078  0.006 | -0.052  0.003 |
Partisan_mobil          |  0.270  0.073 | -0.005  0.000 | -0.017  0.000 |
Civic_Engagement        |  0.095  0.009 | -0.084  0.007 | -0.009  0.000 |
Protest_Action          |  0.017  0.000 |  0.034  0.001 |  0.059  0.004 |
Info_Offline            |  0.230  0.053 | -0.058  0.003 | -0.073  0.005 |

Supplementary categories (the 10 first)
                             Dist     Dim.1    cos2  v.test     Dim.2    cos2
18_24                   |   1.418 |   1.108   0.611   6.486 |  -0.233   0.027
25_34                   |   0.891 |   0.796   0.798   5.984 |  -0.138   0.024
35_44                   |   0.816 |   0.747   0.839   6.248 |   0.121   0.022
45_54                   |   0.239 |   0.127   0.280   1.255 |   0.182   0.579
55_64                   |   0.334 |  -0.268   0.644  -2.525 |   0.138   0.172
65_+                    |   0.992 |  -0.930   0.879 -11.961 |  -0.149   0.023
+Europa                 |   0.623 |   0.043   0.005   0.155 |  -0.203   0.106
Alleanza Verdi-Sinistra |   0.445 |   0.392   0.776   1.836 |  -0.092   0.042
Azione-Italia Viva      |   0.419 |  -0.075   0.032  -0.416 |  -0.189   0.205
Did not vote            |   0.240 |  -0.090   0.141  -0.716 |  -0.198   0.681
                         v.test     Dim.3    cos2  v.test  
18_24                    -2.203 |   0.592   0.174   7.028 |
25_34                    -1.681 |   0.077   0.007   1.175 |
35_44                     1.634 |  -0.085   0.011  -1.441 |
45_54                     2.922 |  -0.013   0.003  -0.256 |
55_64                     2.111 |  -0.076   0.052  -1.454 |
65_+                     -3.098 |  -0.092   0.009  -2.411 |
+Europa                  -1.169 |   0.110   0.031   0.799 |
Alleanza Verdi-Sinistra  -0.695 |  -0.033   0.006  -0.315 |
Azione-Italia Viva       -1.705 |   0.115   0.076   1.302 |
Did not vote             -2.544 |   0.070   0.086   1.132 |
# Description of the dimensions of the PCA:
PCA3_desc <- FactoMineR::dimdesc(PCA3_result, axes = 1:2, proba = 0.05)

# First dimension
PCA3_desc$Dim.1

Link between the variable and the continuous variables (R-square)
=================================================================================
                 correlation       p.value
Telegram          0.71078325 1.041739e-200
Twitter_X         0.70387174 3.480574e-195
TikTok            0.69469692 4.276470e-188
Linkedin          0.69259115 1.661726e-186
Instagram         0.68810309 3.654681e-183
YouTube           0.60063333 2.210095e-128
Facebook          0.45909834  8.225746e-69
WhatsApp          0.38904027  2.895111e-48
sup_pol_causes    0.35876171  8.389189e-41
sup_soc_causes    0.35589341  3.890533e-40
inf_pol           0.34752598  3.125067e-38
inf_socially      0.32963437  2.387166e-34
Partisan_mobil    0.27029646  3.228874e-23
Info_Online       0.26409260  3.357295e-22
Info_Offline      0.22951271  5.178604e-17
Civic_Engagement  0.09532225  5.758285e-04

Link between the variable and the categorical variable (1-way anova)
=============================================
                    R2      p.value
Age_cat     0.16327212 6.198418e-48
Inf_check   0.06810038 6.392291e-19
Inf_disagr  0.06628292 2.200328e-18
Inf_confirm 0.05654758 1.564022e-15
Left_Right  0.02422511 1.796380e-05
Vote        0.02712709 9.909615e-05

Link between variable and the categories of the categorical variables
================================================================
                                     Estimate      p.value
Age_cat=18_24                       0.8448049 6.314004e-11
Age_cat=35_44                       0.4837189 3.139509e-10
Age_cat=25_34                       0.5330018 1.714502e-09
Inf_check=Inf_check_Very often      0.8497859 1.457769e-08
Inf_disagr=Inf_disagr_Very often    0.8356138 7.353664e-08
Inf_disagr=Inf_disagr_Often         0.4127128 1.234073e-05
Inf_confirm=Inf_confirm_Very often  0.6980323 1.294134e-05
Inf_check=Inf_check_Often           0.3993228 1.547763e-04
Vote=Forza Italia                   0.8322058 3.113801e-04
Inf_confirm=Inf_confirm_Often       0.3868089 1.154004e-03
Left_Right=Ext_right                0.3924648 1.316871e-03
Vote=Movimento 5 Stelle             0.2151232 9.891616e-03
Left_Right=Right                    0.2026920 2.072619e-02
Sex=Non-binary                      1.0454188 4.902130e-02
Left_Right=No_position             -0.3202688 3.374237e-02
Age_cat=55_64                      -0.5312895 1.150529e-02
Left_Right=Left                    -0.3648603 3.203779e-03
Vote=Partito Democratico           -0.4564384 2.558011e-04
Inf_confirm=Inf_confirm_Rarely     -0.4923457 4.336972e-06
Inf_disagr=Inf_disagr_Rarely       -0.4953230 3.847349e-06
Inf_check=Inf_check_Rarely         -0.5263152 5.858813e-07
Inf_disagr=Inf_disagr_Never        -0.7667999 2.008965e-08
Inf_check=Inf_check_Never          -0.7816178 1.656179e-08
Inf_confirm=Inf_confirm_Never      -0.7632705 2.767379e-09
Age_cat=65_+                       -1.1933958 8.630145e-35
# Second dimension
PCA3_desc$Dim.2

Link between the variable and the continuous variables (R-square)
=================================================================================
                 correlation       p.value
WhatsApp          0.71395047 2.701010e-203
Facebook          0.52331660  2.280502e-92
Instagram         0.30908189  3.383618e-30
inf_socially      0.11211703  5.058913e-05
sup_soc_causes    0.06568003  1.782087e-02
Info_Offline     -0.05801716  3.640328e-02
Info_Online      -0.07777316  5.003858e-03
Civic_Engagement -0.08401083  2.424021e-03
TikTok           -0.16278444  3.519636e-09
Telegram         -0.20138465  2.266075e-13
Linkedin         -0.30777231  6.067580e-30
Twitter_X        -0.40577897  9.692650e-53

Link between the variable and the categorical variable (1-way anova)
=============================================
                    R2      p.value
Sex        0.037135620 2.156569e-11
Age_cat    0.020498489 6.094449e-05
Vote       0.022809086 9.041707e-04
Left_Right 0.011570927 1.961848e-02
Inf_check  0.008981723 1.971118e-02

Link between variable and the categories of the categorical variables
================================================================
                                 Estimate      p.value
Sex=Female                      0.3038516 2.406963e-12
Age_cat=45_54                   0.1952296 3.438103e-03
Left_Right=Ext_left             0.2183157 2.284974e-02
Vote=Partito Democratico        0.1603081 3.239774e-02
Age_cat=55_64                   0.1515135 3.474535e-02
Age_cat=18_24                  -0.2195176 2.757226e-02
Vote=Did not vote              -0.1609720 1.091000e-02
Left_Right=No_position         -0.1506509 1.028280e-02
Inf_check=Inf_check_Very often -0.2023231 1.938446e-03
Age_cat=65_+                   -0.1358246 1.922577e-03
Vote=Other party               -0.3415773 1.809898e-03
Sex=Male                       -0.1192441 4.004205e-12
# New biplot with factors as supplementary numerical variables
factoextra::fviz_pca_var(
  PCA3_result,
  col.var = "contrib",
  gradient.cols = c("#00AFBB", "#E7B800", "#FC4E07"),
  repel = TRUE
)
Warning: ggrepel: 3 unlabeled data points (too many overlaps). Consider
increasing max.overlaps

Canonical Correlation Analysis

# 11. Canonical Correlation Analysis (CCA) -------------------
# relationship between platform uses (3 PCA COMPONENTS) & latent dimensions of political participation (5 EFA factors)

social_vars <- c("YouTube","WhatsApp","Twitter_X","Instagram",
                 "TikTok","Facebook","Linkedin","Telegram")

factor_vars <- c("Info_Online", "Partisan_mobil",
                 "Civic_Engagement", "Protest_Action", "Info_Offline")

# check only complete cases
complete_ids <- complete.cases(
  data_PCA3[, social_vars],
  data_PCA3[, factor_vars]
)

message("✅ Using ", sum(complete_ids),
        " respondents with complete data on platforms and factors.")
✅ Using 995 respondents with complete data on platforms and factors.
pca_data <- data_PCA3[complete_ids, social_vars]
efa_data <- data_PCA3[complete_ids, factor_vars]

# 11.1 PCA platforms (3 components, as per ES script analyses)
pca_res <- psych::principal(
  pca_data,
  nfactors = 3,
  rotate   = "none",
  scores   = TRUE
)

pca_scores <- as.data.frame(pca_res$scores)
colnames(pca_scores) <- paste0("PC", 1:3)   # PC1, PC2, PC3

# Participation factors (already estimated) – standardized
efa_scores <- as.data.frame(scale(efa_data))

# 11.2 Correlation matrix of PCA components e EFA factors
cor_matrix_pca_efa <- cor(
  cbind(pca_scores, efa_scores),
  use = "pairwise.complete.obs"
)

corrplot::corrplot(
  cor_matrix_pca_efa,
  method = "color",
  type   = "upper",
  tl.col = "black",
  tl.cex = 0.8,
  addCoef.col = "black",
  number.cex = 0.6,
  title = "Correlations between PCA Components and EFA Factors",
  mar   = c(0,0,2,0)
)

# 11.3 Canonical Correlation Analysis (CCA)

if (!requireNamespace("CCA", quietly = TRUE)) {
  stop("Il pacchetto 'CCA' non è installato. Esegui: install.packages('CCA')")
}
if (!requireNamespace("CCP", quietly = TRUE)) {
  stop("Il pacchetto 'CCP' non è installato. Esegui: install.packages('CCP')")
}


# Blocks for CCA
X_pca <- pca_scores                           # 3 PCA components 
Y_efa <- efa_scores                           # 5 EFA factors

dim(X_pca)
[1] 995   3
dim(Y_efa)
[1] 995   5
# 11.3.1 CCA execution
cca_result <- CCA::cc(X_pca, Y_efa)

# CCA
cca_result$cor
[1] 0.39421385 0.13937680 0.05488145
# loadings
cca_result$xcoef  # for PCA components
          [,1]       [,2]       [,3]
PC1 -0.9428084  0.3178548 -0.1004023
PC2  0.2275569  0.8338335  0.5029309
PC3 -0.2435779 -0.4513202  0.8584753
cca_result$ycoef  # for EFA factors
                        [,1]       [,2]        [,3]
Info_Online      -0.48913811 -0.2289978 -0.87115583
Partisan_mobil   -0.65513891  0.8300949 -0.24011844
Civic_Engagement  0.07386196 -0.7479003 -0.45467961
Protest_Action    0.33416540  0.2894763  0.03472063
Info_Offline     -0.12160833 -0.2787729  1.47357619
# 11.3.2 Significance test (Wilks’ Lambda)
rho <- cca_result$cor
n   <- nrow(X_pca)
p   <- ncol(X_pca)
q   <- ncol(Y_efa)

cca_test <- CCP::p.asym(rho, n, p, q, tstat = "Wilks")
Wilks' Lambda, using F-approximation (Rao's F):
              stat     approx df1      df2     p.value
1 to 3:  0.8256939 13.0521557  15 2725.074 0.000000000
2 to 3:  0.9776206  2.8111228   8 1976.000 0.004232957
3 to 3:  0.9969880  0.9959472   3  989.000 0.393967752
cca_test
$id
[1] "Wilks"

$stat
[1] 0.8256939 0.9776206 0.9969880

$approx
[1] 13.0521557  2.8111228  0.9959472

$df1
[1] 15  8  3

$df2
[1] 2725.074 1976.000  989.000

$p.value
[1] 0.000000000 0.004232957 0.393967752
# 11.4 Visualization

# Plot of Canonical Variates
U <- as.data.frame(as.matrix(scale(X_pca)) %*% cca_result$xcoef)
V <- as.data.frame(as.matrix(scale(Y_efa)) %*% cca_result$ycoef)

colnames(U) <- paste0("U", 1:ncol(U))
colnames(V) <- paste0("V", 1:ncol(V))

cca_df <- cbind(U, V)

# 11.4.1 Canonical Correlation between PCA (Social Media) and EFA (Political Engagement)
ggplot(cca_df, aes(x = U1, y = V1)) +
  geom_point(alpha = 0.6) +
  geom_smooth(method = "lm", color = "coral") +
  labs(
    title = "Canonical Correlation between PCA (Social Media) and EFA (Political Engagement)",
    x = "First Canonical Variate (PCA block)",
    y = "First Canonical Variate (EFA block)"
  ) +
  theme_minimal()
`geom_smooth()` using formula = 'y ~ x'

# 11.4.2 Canonical Correlation (all functions)
data.frame(
  Canonical_Function = 1:length(cca_result$cor),
  Correlation        = cca_result$cor
) %>%
  ggplot(aes(x = Canonical_Function, y = Correlation)) +
  geom_col(fill = "coral") +
  geom_text(aes(label = round(Correlation, 2)), vjust = -0.3) +
  labs(
    title = "Canonical Correlations between PCA and EFA Latent Sets",
    x = "Canonical Function",
    y = "Correlation"
  ) +
  theme_minimal()

Hierarchical clustering on PCA results

# 12. Hierarchical clustering on PCA results


# 12.1 HCPC su PCA2_result -------------

hcpc_res <- FactoMineR::HCPC(
  PCA2_result,
  nb.clust = -1,   
  graph    = FALSE
)

# Dataset structure
str(hcpc_res$call$X)
'data.frame':   1301 obs. of  6 variables:
 $ Dim.1: num  -3.76 -3.76 -3.76 -3.76 -3.76 ...
 $ Dim.2: num  -3.04 -3.04 -3.04 -3.04 -3.04 ...
 $ Dim.3: num  -0.869 -0.869 -0.869 -0.869 -0.869 ...
 $ Dim.4: num  0.173 0.173 0.173 0.173 0.173 ...
 $ Dim.5: num  -1.01 -1.01 -1.01 -1.01 -1.01 ...
 $ clust: Factor w/ 3 levels "1","2","3": 1 1 1 1 1 1 1 1 1 1 ...
# Cluster description (quantitative and qualitative variables)
print(hcpc_res$desc.var$quanti)
$`1`
                   v.test Mean in category Overall mean sd in category
inf_pol         -8.619589        0.4444444    0.6610300      0.4969040
sup_pol_causes  -8.638983        0.3046595    0.5334358      0.4602631
Twitter_X       -8.647238        1.5208886    2.3879870      1.2570367
sup_soc_causes  -9.494062        0.3118280    0.5618755      0.4632400
Linkedin        -9.557636        1.4937609    2.3449111      1.0114933
inf_socially   -10.029012        0.5017921    0.7363566      0.4999968
TikTok         -10.676741        1.3567245    2.5052293      1.0014777
Telegram       -11.251364        1.7333518    2.9435939      1.3722745
YouTube        -11.756496        3.0788530    4.1284047      1.6872548
WhatsApp       -18.754809        4.5585063    5.8232558      1.9894849
Instagram      -20.772240        1.6525179    4.0525078      1.3191793
Facebook       -23.084470        2.2688172    4.6645963      1.7748125
               Overall sd       p.value
inf_pol         0.4733596  6.719496e-18
sup_pol_causes  0.4988808  5.671564e-18
Twitter_X       1.8890319  5.276066e-18
sup_soc_causes  0.4961567  2.222026e-21
Linkedin        1.6776605  1.204775e-21
inf_socially    0.4406081  1.136478e-23
TikTok          2.0264803  1.307819e-26
Telegram        2.0263543  2.280375e-29
YouTube         1.6817996  6.539233e-32
WhatsApp        1.2703992  1.768531e-78
Instagram       2.1765789  7.717460e-96
Facebook        1.9551280 6.631616e-118

$`2`
                 v.test Mean in category Overall mean sd in category Overall sd
WhatsApp      11.460297        6.2032356    5.8232558      0.5104873  1.2703992
Facebook      11.325052        5.2424791    4.6645963      1.4653822  1.9551280
Instagram      4.132437        4.2872575    4.0525078      2.0144862  2.1765789
inf_socially   2.131661        0.7608696    0.7363566      0.4265525  0.4406081
YouTube       -3.064133        3.9939097    4.1284047      1.5427273  1.6817996
Telegram      -9.914354        2.4192645    2.9435939      1.7175343  2.0263543
TikTok       -10.546046        1.9474576    2.5052293      1.5944161  2.0264803
Linkedin     -12.174441        1.8118494    2.3449111      1.1343184  1.6776605
Twitter_X    -14.666328        1.6649092    2.3879870      1.1924886  1.8890319
                  p.value
WhatsApp     2.087968e-30
Facebook     9.862073e-30
Instagram    3.589379e-05
inf_socially 3.303475e-02
YouTube      2.183022e-03
Telegram     3.605820e-23
TikTok       5.298021e-26
Linkedin     4.252967e-34
Twitter_X    1.059250e-48

$`3`
                  v.test Mean in category Overall mean sd in category
Twitter_X      24.930347        4.6194453    2.3879870      1.7327380
Linkedin       22.934829        4.1680543    2.3449111      1.7239945
TikTok         22.124288        4.6296126    2.5052293      1.9230664
Telegram       21.942131        5.0503553    2.9435939      1.4616608
Instagram      14.825351        5.5814835    4.0525078      1.1727849
YouTube        14.575831        5.2899301    4.1284047      1.1968981
sup_soc_causes  9.155220        0.7771084    0.5618755      0.4161862
sup_pol_causes  9.034122        0.7469880    0.5334358      0.4347378
Facebook        8.768383        5.4768952    4.6645963      1.3007396
inf_pol         8.666931        0.8554217    0.6610300      0.3516752
inf_socially    7.001561        0.8825301    0.7363566      0.3219794
WhatsApp        4.537405        6.0963855    5.8232558      0.8588933
               Overall sd       p.value
Twitter_X       1.8890319 3.488870e-137
Linkedin        1.6776605 2.088283e-116
TikTok          2.0264803 1.845264e-108
Telegram        2.0263543 1.029628e-106
Instagram       2.1765789  1.004540e-49
YouTube         1.6817996  4.002215e-48
sup_soc_causes  0.4961567  5.424727e-20
sup_pol_causes  0.4988808  1.653240e-19
Facebook        1.9551280  1.812509e-18
inf_pol         0.4733596  4.439233e-18
inf_socially    0.4406081  2.531263e-12
WhatsApp        1.2703992  5.695056e-06
print(hcpc_res$desc.var$quali)
NULL
# Cluster map on PCA
plot(hcpc_res, choice = "map")

# Dendrogram
plot(hcpc_res, choice = "tree")

# 12.2 Cluster assignment--------

clusters <- hcpc_res$data.clust %>%
  dplyr::select(clust) %>%
  dplyr::mutate(ID = dplyr::row_number())

data_clustered <- data_PCA3 %>%
  dplyr::mutate(ID = dplyr::row_number()) %>%
  dplyr::left_join(clusters, by = "ID")


# 12.3 Variables identification ----------------

num_vars <- names(dplyr::select(data_clustered, where(is.numeric))) %>%
  setdiff("ID")

cat_vars <- names(dplyr::select(data_clustered, where(is.factor)))


# 12.4 Summarize of variables by cluster -------------

cat("===== Quantitative Variables by Cluster =====\n")
===== Quantitative Variables by Cluster =====
num_summary <- data_clustered %>%
  group_by(clust) %>%
  summarise(
    across(all_of(num_vars),
           list(mean = mean, sd = sd),
           .names = "{.col}_{.fn}"),
    .groups = "drop"
  )

print(num_summary)
# A tibble: 3 × 35
  clust YouTube_mean YouTube_sd WhatsApp_mean WhatsApp_sd Twitter_X_mean
  <fct>        <dbl>      <dbl>         <dbl>       <dbl>          <dbl>
1 1             3.08       1.69         NA         NA                 NA
2 2            NA         NA            NA         NA                 NA
3 3            NA         NA             6.10       0.860             NA
# ℹ 29 more variables: Twitter_X_sd <dbl>, Instagram_mean <dbl>,
#   Instagram_sd <dbl>, TikTok_mean <dbl>, TikTok_sd <dbl>,
#   Facebook_mean <dbl>, Facebook_sd <dbl>, Linkedin_mean <dbl>,
#   Linkedin_sd <dbl>, Telegram_mean <dbl>, Telegram_sd <dbl>,
#   inf_socially_mean <dbl>, inf_socially_sd <dbl>, inf_pol_mean <dbl>,
#   inf_pol_sd <dbl>, sup_soc_causes_mean <dbl>, sup_soc_causes_sd <dbl>,
#   sup_pol_causes_mean <dbl>, sup_pol_causes_sd <dbl>, …

Anova per each variable

# --- ANOVA per each variable ---
anova_results <- sapply(num_vars, function(v) {
  if (all(is.na(data_clustered[[v]]))) return(NA)
  fit <- aov(data_clustered[[v]] ~ data_clustered$clust)
  summary(fit)[[1]][["Pr(>F)"]][1]
})

anova_results <- sort(na.omit(anova_results))

cat("\n--- ANOVA p-values (quantitative vars) ---\n")

--- ANOVA p-values (quantitative vars) ---
print(anova_results)
       Twitter_X         Facebook         Linkedin        Instagram 
   1.852602e-185    1.426057e-149    1.827589e-149    2.398475e-139 
          TikTok         Telegram         WhatsApp          YouTube 
   9.243475e-138    1.427796e-136     6.313985e-90     3.765550e-66 
  sup_soc_causes   sup_pol_causes     inf_socially          inf_pol 
    3.301317e-31     5.920672e-28     1.824587e-27     1.075924e-26 
  Partisan_mobil      Info_Online     Info_Offline Civic_Engagement 
    2.391023e-22     3.984051e-16     4.431335e-13     5.259269e-05 
  Protest_Action 
    3.739654e-01 

Summarize of categorical variables per cluster

# 12.5 Summarize of categorical variables per cluster --------------

cat("\n===== Categorical Variables by Cluster =====\n")

===== Categorical Variables by Cluster =====
for (v in cat_vars) {
  cat("\n###", v, "###\n")
  
  tab <- table(data_clustered[[v]], data_clustered$clust)
  print(tab)
  
  test <- suppressWarnings(chisq.test(tab))
  print(test)
}

### Age_cat ###
       
          1   2   3
  0_17    0   0   0
  18_24   8  46  46
  25_34  20  71  66
  35_44  18 101  70
  45_54  40 145  66
  55_64  48 144  39
  65_+  145 183  45

    Pearson's Chi-squared test

data:  tab
X-squared = NaN, df = 12, p-value = NA


### Vote ###
                         
                            1   2   3
  +Europa                  11  16  12
  Alleanza Verdi-Sinistra  11  32  23
  Azione-Italia Viva       24  41  26
  Did not vote             39  95  39
  Forza Italia              7  20  17
  Fratelli d'Italia        37  90  39
  Lega                     11  37  11
  Movimento 5 Stelle       24  93  50
  Other party              21  27  29
  Partito Democratico      64 166  54

    Pearson's Chi-squared test

data:  tab
X-squared = 37.656, df = 18, p-value = 0.0043


### Sex ###
            
               1   2   3
  Male       165 285 174
  Female     113 403 156
  Non-binary   1   2   2

    Pearson's Chi-squared test

data:  tab
X-squared = 29.797, df = 4, p-value = 5.384e-06


### Left_Right ###
             
                1   2   3
  Ext_left     28  91  26
  Left         64 162  55
  Center       67 162  92
  Right        30  87  56
  Ext_right    23  64  40
  No_position  58 112  50

    Pearson's Chi-squared test

data:  tab
X-squared = 23.897, df = 10, p-value = 0.007879


### Pol_int ###
                       
                          1   2   3
  Very interested        46 142  73
  Somewhat interested   141 292 172
  Not very interested    61 198  62
  Not at all interested  31  58  25

    Pearson's Chi-squared test

data:  tab
X-squared = 20.757, df = 6, p-value = 0.002028


### Inf_disagr ###
            
               1   2   3
  Very often  24  61  65
  Often       71 225 129
  sometimes   97 242 106
  Rarely      47  95  21
  Never       40  67  11

    Pearson's Chi-squared test

data:  tab
X-squared = 70.25, df = 8, p-value = 4.383e-12


### Inf_check ###
            
               1   2   3
  Very often  28  69  75
  Often       81 224 133
  sometimes   88 244  95
  Rarely      45  91  20
  Never       37  62   9

    Pearson's Chi-squared test

data:  tab
X-squared = 74.82, df = 8, p-value = 5.359e-13


### Inf_confirm ###
            
               1   2   3
  Very often  32  84  72
  Often       89 256 132
  sometimes   74 216  99
  Rarely      42  73  18
  Never       42  61  11

    Pearson's Chi-squared test

data:  tab
X-squared = 58.171, df = 8, p-value = 1.064e-09


### clust ###
   
      1   2   3
  1 279   0   0
  2   0 690   0
  3   0   0 332

    Pearson's Chi-squared test

data:  tab
X-squared = 2602, df = 4, p-value < 2.2e-16
# 12.6 Visualization: boxplot for most significant variables----------

top_num <- names(head(anova_results, 3))

for (v in top_num) {
  p <- ggplot(data_clustered, aes(x = clust, y = .data[[v]], fill = clust)) +
    geom_boxplot(alpha = 0.7) +
    theme_minimal() +
    labs(title = paste("Distribution of", v, "by Cluster"),
         x = "Cluster", y = v) +
    theme(legend.position = "none") +
    scale_fill_brewer(palette = "Dark2")
  
  print(p)
}
Warning: Removed 69 rows containing non-finite outside the scale range
(`stat_boxplot()`).

Warning: Removed 13 rows containing non-finite outside the scale range
(`stat_boxplot()`).

Warning: Removed 63 rows containing non-finite outside the scale range
(`stat_boxplot()`).

# 12.7 HCPC Internal Descriptions -----------------------

cat("\n===== HCPC Internal Descriptions =====\n")

===== HCPC Internal Descriptions =====
cat("\n--- Quantitative Variables ---\n")

--- Quantitative Variables ---
print(hcpc_res$desc.var$quanti)
$`1`
                   v.test Mean in category Overall mean sd in category
inf_pol         -8.619589        0.4444444    0.6610300      0.4969040
sup_pol_causes  -8.638983        0.3046595    0.5334358      0.4602631
Twitter_X       -8.647238        1.5208886    2.3879870      1.2570367
sup_soc_causes  -9.494062        0.3118280    0.5618755      0.4632400
Linkedin        -9.557636        1.4937609    2.3449111      1.0114933
inf_socially   -10.029012        0.5017921    0.7363566      0.4999968
TikTok         -10.676741        1.3567245    2.5052293      1.0014777
Telegram       -11.251364        1.7333518    2.9435939      1.3722745
YouTube        -11.756496        3.0788530    4.1284047      1.6872548
WhatsApp       -18.754809        4.5585063    5.8232558      1.9894849
Instagram      -20.772240        1.6525179    4.0525078      1.3191793
Facebook       -23.084470        2.2688172    4.6645963      1.7748125
               Overall sd       p.value
inf_pol         0.4733596  6.719496e-18
sup_pol_causes  0.4988808  5.671564e-18
Twitter_X       1.8890319  5.276066e-18
sup_soc_causes  0.4961567  2.222026e-21
Linkedin        1.6776605  1.204775e-21
inf_socially    0.4406081  1.136478e-23
TikTok          2.0264803  1.307819e-26
Telegram        2.0263543  2.280375e-29
YouTube         1.6817996  6.539233e-32
WhatsApp        1.2703992  1.768531e-78
Instagram       2.1765789  7.717460e-96
Facebook        1.9551280 6.631616e-118

$`2`
                 v.test Mean in category Overall mean sd in category Overall sd
WhatsApp      11.460297        6.2032356    5.8232558      0.5104873  1.2703992
Facebook      11.325052        5.2424791    4.6645963      1.4653822  1.9551280
Instagram      4.132437        4.2872575    4.0525078      2.0144862  2.1765789
inf_socially   2.131661        0.7608696    0.7363566      0.4265525  0.4406081
YouTube       -3.064133        3.9939097    4.1284047      1.5427273  1.6817996
Telegram      -9.914354        2.4192645    2.9435939      1.7175343  2.0263543
TikTok       -10.546046        1.9474576    2.5052293      1.5944161  2.0264803
Linkedin     -12.174441        1.8118494    2.3449111      1.1343184  1.6776605
Twitter_X    -14.666328        1.6649092    2.3879870      1.1924886  1.8890319
                  p.value
WhatsApp     2.087968e-30
Facebook     9.862073e-30
Instagram    3.589379e-05
inf_socially 3.303475e-02
YouTube      2.183022e-03
Telegram     3.605820e-23
TikTok       5.298021e-26
Linkedin     4.252967e-34
Twitter_X    1.059250e-48

$`3`
                  v.test Mean in category Overall mean sd in category
Twitter_X      24.930347        4.6194453    2.3879870      1.7327380
Linkedin       22.934829        4.1680543    2.3449111      1.7239945
TikTok         22.124288        4.6296126    2.5052293      1.9230664
Telegram       21.942131        5.0503553    2.9435939      1.4616608
Instagram      14.825351        5.5814835    4.0525078      1.1727849
YouTube        14.575831        5.2899301    4.1284047      1.1968981
sup_soc_causes  9.155220        0.7771084    0.5618755      0.4161862
sup_pol_causes  9.034122        0.7469880    0.5334358      0.4347378
Facebook        8.768383        5.4768952    4.6645963      1.3007396
inf_pol         8.666931        0.8554217    0.6610300      0.3516752
inf_socially    7.001561        0.8825301    0.7363566      0.3219794
WhatsApp        4.537405        6.0963855    5.8232558      0.8588933
               Overall sd       p.value
Twitter_X       1.8890319 3.488870e-137
Linkedin        1.6776605 2.088283e-116
TikTok          2.0264803 1.845264e-108
Telegram        2.0263543 1.029628e-106
Instagram       2.1765789  1.004540e-49
YouTube         1.6817996  4.002215e-48
sup_soc_causes  0.4961567  5.424727e-20
sup_pol_causes  0.4988808  1.653240e-19
Facebook        1.9551280  1.812509e-18
inf_pol         0.4733596  4.439233e-18
inf_socially    0.4406081  2.531263e-12
WhatsApp        1.2703992  5.695056e-06
cat("\n--- Qualitative Variables ---\n")

--- Qualitative Variables ---
print(hcpc_res$desc.var$quali)
NULL

Anova Analysis

Anova platform use (DV) per sociopolitical variables

# 13. ANOVA: platform use x age, ideological...

# Platform use
social_vars <- c("YouTube", "WhatsApp", "Twitter_X", "Instagram",
                 "TikTok", "Facebook", "Linkedin", "Telegram")

# 13.1 Platform and ideology (Left_Right) ---------

# Descriptives
desc_stats <- data_PCA3 %>%
  tidyr::pivot_longer(
    cols      = dplyr::all_of(social_vars),
    names_to  = "Platform",
    values_to = "Frequency"
  ) %>%
  dplyr::group_by(Platform, Left_Right) %>%
  dplyr::summarise(
    n    = dplyr::n(),
    mean = mean(Frequency, na.rm = TRUE),
    sd   = sd(Frequency, na.rm = TRUE),
    se   = sd / sqrt(n),
    .groups = "drop"
  )

knitr::kable(
  desc_stats,
  digits  = 2,
  caption = "Descriptives per platform & ideology"
)
Descriptives per platform & ideology
Platform Left_Right n mean sd se
Facebook Ext_left 145 4.65 1.88 0.16
Facebook Left 281 4.51 1.94 0.12
Facebook Center 321 4.71 1.96 0.11
Facebook Right 173 4.83 1.86 0.14
Facebook Ext_right 127 5.11 2.00 0.18
Facebook No_position 220 4.41 2.08 0.14
Facebook NA 34 4.77 1.99 0.34
Instagram Ext_left 145 4.06 2.28 0.19
Instagram Left 281 3.91 2.23 0.13
Instagram Center 321 4.22 2.11 0.12
Instagram Right 173 4.20 2.16 0.16
Instagram Ext_right 127 4.15 2.28 0.20
Instagram No_position 220 3.75 2.20 0.15
Instagram NA 34 4.52 2.19 0.38
Linkedin Ext_left 145 2.02 1.63 0.14
Linkedin Left 281 2.17 1.55 0.09
Linkedin Center 321 2.50 1.75 0.10
Linkedin Right 173 2.59 1.83 0.14
Linkedin Ext_right 127 2.47 1.91 0.17
Linkedin No_position 220 2.21 1.65 0.11
Linkedin NA 34 2.93 1.96 0.34
Telegram Ext_left 145 2.35 1.82 0.15
Telegram Left 281 2.74 2.00 0.12
Telegram Center 321 2.95 2.04 0.11
Telegram Right 173 3.27 2.07 0.16
Telegram Ext_right 127 3.43 2.34 0.21
Telegram No_position 220 2.98 2.12 0.14
Telegram NA 34 3.52 2.08 0.36
TikTok Ext_left 145 2.36 2.08 0.17
TikTok Left 281 2.07 1.80 0.11
TikTok Center 321 2.41 2.02 0.11
TikTok Right 173 2.90 2.14 0.16
TikTok Ext_right 127 3.15 2.32 0.21
TikTok No_position 220 2.48 2.08 0.14
TikTok NA 34 3.48 2.32 0.40
Twitter_X Ext_left 145 2.22 1.83 0.15
Twitter_X Left 281 2.18 1.79 0.11
Twitter_X Center 321 2.57 2.02 0.11
Twitter_X Right 173 2.64 2.06 0.16
Twitter_X Ext_right 127 2.76 2.21 0.20
Twitter_X No_position 220 2.09 1.77 0.12
Twitter_X NA 34 2.41 1.89 0.32
WhatsApp Ext_left 145 5.93 1.21 0.10
WhatsApp Left 281 5.89 1.15 0.07
WhatsApp Center 321 5.87 1.23 0.07
WhatsApp Right 173 5.81 1.23 0.09
WhatsApp Ext_right 127 6.05 1.17 0.10
WhatsApp No_position 220 5.53 1.55 0.10
WhatsApp NA 34 5.50 1.48 0.25
YouTube Ext_left 145 4.01 1.54 0.13
YouTube Left 281 3.91 1.63 0.10
YouTube Center 321 4.22 1.71 0.10
YouTube Right 173 4.17 1.65 0.13
YouTube Ext_right 127 4.44 1.75 0.16
YouTube No_position 220 4.08 1.80 0.12
YouTube NA 34 4.60 1.73 0.30
# Welch ANOVA + eta squared per each platform
anova_results <- data_PCA3 %>%
  tidyr::pivot_longer(
    cols      = dplyr::all_of(social_vars),
    names_to  = "Platform",
    values_to = "Frequency"
  ) %>%
  dplyr::group_by(Platform) %>%
  dplyr::summarise(
    Welch_p = oneway.test(Frequency ~ Left_Right,
                          data = dplyr::cur_data(),
                          var.equal = FALSE)$p.value,
    eta_sq  = {
      eta_res <- rstatix::eta_squared(aov(Frequency ~ Left_Right,
                                          data = dplyr::cur_data()))
      if (is.data.frame(eta_res)) eta_res$Eta2[1] else as.numeric(eta_res[1])
    },
    .groups = "drop"
  )
Warning: There was 1 warning in `dplyr::summarise()`.
ℹ In argument: `Welch_p = `$`(...)`.
ℹ In group 1: `Platform = "Facebook"`.
Caused by warning:
! `cur_data()` was deprecated in dplyr 1.1.0.
ℹ Please use `pick()` instead.
knitr::kable(
  anova_results,
  digits  = 3,
  caption = "Welch ANOVA with eta-squared (per ideology)"
)
Welch ANOVA with eta-squared (per ideology)
Platform Welch_p eta_sq
Facebook 0.027 0.011
Instagram 0.142 0.007
Linkedin 0.009 0.013
Telegram 0.000 0.020
TikTok 0.000 0.026
Twitter_X 0.003 0.015
WhatsApp 0.017 0.014
YouTube 0.057 0.009
# Games–Howell post-hoc per each platform
gh_results <- data_PCA3 %>%
  tidyr::pivot_longer(
    cols      = dplyr::all_of(social_vars),
    names_to  = "Platform",
    values_to = "Frequency"
  ) %>%
  dplyr::group_by(Platform) %>%
  rstatix::games_howell_test(Frequency ~ Left_Right) %>%
  dplyr::mutate(
    p_sig = dplyr::case_when(
      p.adj < .001 ~ "***",
      p.adj < .01  ~ "**",
      p.adj < .05  ~ "*",
      TRUE        ~ ""
    )
  ) %>%
  dplyr::select(
    Platform, group1, group2,
    mean_difference = estimate, p.adj, p_sig
  )

knitr::kable(
  gh_results,
  digits  = 3,
  caption = "Comparison post-hoc Games–Howell (per ideology)"
)
Comparison post-hoc Games–Howell (per ideology)
Platform group1 group2 mean_difference p.adj p_sig
Facebook Ext_left Left -0.139 0.981
Facebook Ext_left Center 0.060 1.000
Facebook Ext_left Right 0.187 0.951
Facebook Ext_left Ext_right 0.466 0.369
Facebook Ext_left No_position -0.234 0.879
Facebook Left Center 0.199 0.813
Facebook Left Right 0.325 0.484
Facebook Left Ext_right 0.605 0.056
Facebook Left No_position -0.095 0.995
Facebook Center Right 0.126 0.981
Facebook Center Ext_right 0.406 0.384
Facebook Center No_position -0.294 0.569
Facebook Right Ext_right 0.280 0.824
Facebook Right No_position -0.420 0.290
Facebook Ext_right No_position -0.700 0.028 *
Instagram Ext_left Left -0.150 0.988
Instagram Ext_left Center 0.163 0.979
Instagram Ext_left Right 0.145 0.993
Instagram Ext_left Ext_right 0.096 0.999
Instagram Ext_left No_position -0.311 0.799
Instagram Left Center 0.313 0.495
Instagram Left Right 0.295 0.738
Instagram Left Ext_right 0.246 0.915
Instagram Left No_position -0.161 0.967
Instagram Center Right -0.018 1.000
Instagram Center Ext_right -0.067 1.000
Instagram Center No_position -0.474 0.135
Instagram Right Ext_right -0.049 1.000
Instagram Right No_position -0.456 0.328
Instagram Ext_right No_position -0.407 0.597
Linkedin Ext_left Left 0.153 0.941
Linkedin Ext_left Center 0.480 0.055
Linkedin Ext_left Right 0.567 0.051
Linkedin Ext_left Ext_right 0.445 0.342
Linkedin Ext_left No_position 0.185 0.908
Linkedin Left Center 0.327 0.164
Linkedin Left Right 0.413 0.154
Linkedin Left Ext_right 0.292 0.683
Linkedin Left No_position 0.031 1.000
Linkedin Center Right 0.086 0.996
Linkedin Center Ext_right -0.035 1.000
Linkedin Center No_position -0.296 0.377
Linkedin Right Ext_right -0.121 0.995
Linkedin Right No_position -0.382 0.297
Linkedin Ext_right No_position -0.261 0.812
Telegram Ext_left Left 0.391 0.351
Telegram Ext_left Center 0.605 0.023 *
Telegram Ext_left Right 0.923 0.001 ***
Telegram Ext_left Ext_right 1.077 0.001 ***
Telegram Ext_left No_position 0.626 0.040 *
Telegram Left Center 0.214 0.801
Telegram Left Right 0.532 0.093
Telegram Left Ext_right 0.687 0.067
Telegram Left No_position 0.236 0.818
Telegram Center Right 0.318 0.599
Telegram Center Ext_right 0.473 0.388
Telegram Center No_position 0.022 1.000
Telegram Right Ext_right 0.155 0.993
Telegram Right No_position -0.296 0.750
Telegram Ext_right No_position -0.451 0.513
TikTok Ext_left Left -0.288 0.731
TikTok Ext_left Center 0.048 1.000
TikTok Ext_left Right 0.539 0.225
TikTok Ext_left Ext_right 0.787 0.048 *
TikTok Ext_left No_position 0.119 0.995
TikTok Left Center 0.336 0.280
TikTok Left Right 0.827 0.001 ***
TikTok Left Ext_right 1.075 0.000 ***
TikTok Left No_position 0.407 0.228
TikTok Center Right 0.491 0.147
TikTok Center Ext_right 0.739 0.026 *
TikTok Center No_position 0.071 0.999
TikTok Right Ext_right 0.248 0.938
TikTok Right No_position -0.420 0.402
TikTok Ext_right No_position -0.669 0.096
Twitter_X Ext_left Left -0.037 1.000
Twitter_X Ext_left Center 0.351 0.445
Twitter_X Ext_left Right 0.417 0.421
Twitter_X Ext_left Ext_right 0.542 0.279
Twitter_X Ext_left No_position -0.130 0.986
Twitter_X Left Center 0.388 0.141
Twitter_X Left Right 0.454 0.187
Twitter_X Left Ext_right 0.579 0.130
Twitter_X Left No_position -0.093 0.993
Twitter_X Center Right 0.067 0.999
Twitter_X Center Ext_right 0.192 0.964
Twitter_X Center No_position -0.480 0.052
Twitter_X Right Ext_right 0.125 0.997
Twitter_X Right No_position -0.547 0.081
Twitter_X Ext_right No_position -0.672 0.060
WhatsApp Ext_left Left -0.045 0.999
WhatsApp Ext_left Center -0.063 0.996
WhatsApp Ext_left Right -0.123 0.947
WhatsApp Ext_left Ext_right 0.117 0.966
WhatsApp Ext_left No_position -0.401 0.067
WhatsApp Left Center -0.018 1.000
WhatsApp Left Right -0.078 0.985
WhatsApp Left Ext_right 0.161 0.786
WhatsApp Left No_position -0.356 0.054
WhatsApp Center Right -0.060 0.995
WhatsApp Center Ext_right 0.179 0.702
WhatsApp Center No_position -0.338 0.079
WhatsApp Right Ext_right 0.239 0.523
WhatsApp Right No_position -0.278 0.358
WhatsApp Ext_right No_position -0.518 0.007 **
YouTube Ext_left Left -0.097 0.991
YouTube Ext_left Center 0.217 0.753
YouTube Ext_left Right 0.162 0.946
YouTube Ext_left Ext_right 0.432 0.278
YouTube Ext_left No_position 0.071 0.999
YouTube Left Center 0.314 0.200
YouTube Left Right 0.258 0.586
YouTube Left Ext_right 0.529 0.054
YouTube Left No_position 0.167 0.893
YouTube Center Right -0.055 0.999
YouTube Center Ext_right 0.215 0.853
YouTube Center No_position -0.146 0.935
YouTube Right Ext_right 0.270 0.763
YouTube Right No_position -0.091 0.995
YouTube Ext_right No_position -0.361 0.460
# Grafico: avg 
ggplot(desc_stats,
       aes(x = Left_Right, y = mean, fill = Left_Right)) +
  geom_col(position = "dodge", color = "black") +
  geom_errorbar(aes(ymin = mean - se, ymax = mean + se),
                width = 0.2,
                position = position_dodge(0.9)) +
  facet_wrap(~ Platform, scales = "free_y") +
  labs(
    title = "Platform use frequency and ideology",
    x     = "Ideology Left-Right",
    y     = "Use frequency (avg ±SE)"
  ) +
  scale_fill_viridis_d() +
  theme_minimal() +
  theme(
    legend.position = "none",
    axis.text.x = element_text(angle = 90, hjust = 1)
  )

# 13.2 Platforms & vote in general elections  --------------------

# Descriptives platforms & vote
desc_stats_vote <- data_PCA3 %>%
  tidyr::pivot_longer(
    cols      = dplyr::all_of(social_vars),
    names_to  = "Platform",
    values_to = "Frequency"
  ) %>%
  dplyr::group_by(Platform, Vote) %>%
  dplyr::summarise(
    n    = dplyr::n(),
    mean = mean(Frequency, na.rm = TRUE),
    sd   = sd(Frequency, na.rm = TRUE),
    se   = sd / sqrt(n),
    .groups = "drop"
  )

knitr::kable(
  desc_stats_vote,
  digits  = 2,
  caption = "Descriptives of platforms & vote in general elections"
)
Descriptives of platforms & vote in general elections
Platform Vote n mean sd se
Facebook +Europa 39 3.85 2.01 0.32
Facebook Alleanza Verdi-Sinistra 66 4.70 1.86 0.23
Facebook Azione-Italia Viva 91 4.20 2.14 0.22
Facebook Did not vote 173 4.37 1.94 0.15
Facebook Forza Italia 44 5.20 1.95 0.29
Facebook Fratelli d’Italia 166 4.79 1.95 0.15
Facebook Lega 59 5.16 2.01 0.26
Facebook Movimento 5 Stelle 167 5.03 1.79 0.14
Facebook Other party 77 4.38 2.16 0.25
Facebook Partito Democratico 284 4.72 1.92 0.11
Facebook NA 135 4.62 1.96 0.17
Instagram +Europa 39 4.15 2.23 0.36
Instagram Alleanza Verdi-Sinistra 66 4.52 1.97 0.24
Instagram Azione-Italia Viva 91 4.20 2.21 0.23
Instagram Did not vote 173 3.87 2.15 0.16
Instagram Forza Italia 44 5.02 1.85 0.28
Instagram Fratelli d’Italia 166 3.93 2.25 0.17
Instagram Lega 59 4.12 2.23 0.29
Instagram Movimento 5 Stelle 167 4.28 2.20 0.17
Instagram Other party 77 3.76 2.19 0.25
Instagram Partito Democratico 284 3.79 2.27 0.13
Instagram NA 135 4.17 2.13 0.18
Linkedin +Europa 39 2.66 1.82 0.29
Linkedin Alleanza Verdi-Sinistra 66 2.86 1.84 0.23
Linkedin Azione-Italia Viva 91 2.44 1.70 0.18
Linkedin Did not vote 173 2.31 1.71 0.13
Linkedin Forza Italia 44 2.86 1.86 0.28
Linkedin Fratelli d’Italia 166 1.96 1.49 0.12
Linkedin Lega 59 2.12 1.58 0.21
Linkedin Movimento 5 Stelle 167 2.46 1.86 0.14
Linkedin Other party 77 2.61 1.84 0.21
Linkedin Partito Democratico 284 2.25 1.67 0.10
Linkedin NA 135 2.27 1.68 0.14
Telegram +Europa 39 2.95 1.93 0.31
Telegram Alleanza Verdi-Sinistra 66 3.23 2.29 0.28
Telegram Azione-Italia Viva 91 2.63 2.04 0.21
Telegram Did not vote 173 2.98 2.06 0.16
Telegram Forza Italia 44 3.60 2.07 0.31
Telegram Fratelli d’Italia 166 3.12 2.18 0.17
Telegram Lega 59 2.87 2.08 0.27
Telegram Movimento 5 Stelle 167 3.03 2.15 0.17
Telegram Other party 77 3.42 1.93 0.22
Telegram Partito Democratico 284 2.57 1.95 0.12
Telegram NA 135 3.01 2.08 0.18
TikTok +Europa 39 3.13 2.36 0.38
TikTok Alleanza Verdi-Sinistra 66 2.62 2.21 0.27
TikTok Azione-Italia Viva 91 2.11 1.79 0.19
TikTok Did not vote 173 2.58 2.05 0.16
TikTok Forza Italia 44 3.57 2.50 0.38
TikTok Fratelli d’Italia 166 2.49 2.00 0.16
TikTok Lega 59 2.46 2.06 0.27
TikTok Movimento 5 Stelle 167 2.96 2.26 0.17
TikTok Other party 77 3.01 2.17 0.25
TikTok Partito Democratico 284 2.05 1.88 0.11
TikTok NA 135 2.26 1.88 0.16
Twitter_X +Europa 39 2.39 1.88 0.30
Twitter_X Alleanza Verdi-Sinistra 66 2.75 1.98 0.24
Twitter_X Azione-Italia Viva 91 2.74 1.97 0.21
Twitter_X Did not vote 173 2.37 1.89 0.14
Twitter_X Forza Italia 44 3.05 2.33 0.35
Twitter_X Fratelli d’Italia 166 2.29 1.89 0.15
Twitter_X Lega 59 2.21 2.04 0.27
Twitter_X Movimento 5 Stelle 167 2.63 2.07 0.16
Twitter_X Other party 77 2.93 2.23 0.25
Twitter_X Partito Democratico 284 2.12 1.82 0.11
Twitter_X NA 135 1.93 1.60 0.14
WhatsApp +Europa 39 6.00 1.38 0.22
WhatsApp Alleanza Verdi-Sinistra 66 5.86 1.12 0.14
WhatsApp Azione-Italia Viva 91 5.69 1.47 0.15
WhatsApp Did not vote 173 5.60 1.51 0.11
WhatsApp Forza Italia 44 5.93 1.30 0.20
WhatsApp Fratelli d’Italia 166 5.92 1.12 0.09
WhatsApp Lega 59 5.90 1.28 0.17
WhatsApp Movimento 5 Stelle 167 5.89 1.16 0.09
WhatsApp Other party 77 5.71 1.36 0.16
WhatsApp Partito Democratico 284 5.86 1.19 0.07
WhatsApp NA 135 5.82 1.30 0.11
YouTube +Europa 39 3.69 1.36 0.22
YouTube Alleanza Verdi-Sinistra 66 4.30 1.48 0.18
YouTube Azione-Italia Viva 91 4.24 1.74 0.18
YouTube Did not vote 173 4.17 1.72 0.13
YouTube Forza Italia 44 4.82 1.54 0.23
YouTube Fratelli d’Italia 166 4.30 1.70 0.13
YouTube Lega 59 4.09 1.83 0.24
YouTube Movimento 5 Stelle 167 4.40 1.55 0.12
YouTube Other party 77 4.25 1.77 0.20
YouTube Partito Democratico 284 3.75 1.69 0.10
YouTube NA 135 4.01 1.76 0.15
# Welch ANOVA + eta squared per vote
anova_results_vote <- data_PCA3 %>%
  tidyr::pivot_longer(
    cols      = dplyr::all_of(social_vars),
    names_to  = "Platform",
    values_to = "Frequency"
  ) %>%
  dplyr::group_by(Platform) %>%
  dplyr::summarise(
    Welch_p = oneway.test(Frequency ~ Vote,
                          data = dplyr::cur_data(),
                          var.equal = FALSE)$p.value,
    eta_sq  = {
      eta_res <- rstatix::eta_squared(aov(Frequency ~ Vote,
                                          data = dplyr::cur_data()))
      if (is.data.frame(eta_res)) eta_res$Eta2[1] else as.numeric(eta_res[1])
    },
    .groups = "drop"
  )

knitr::kable(
  anova_results_vote,
  digits  = 3,
  caption = "Welch ANOVA con eta-squared (per party voted)"
)
Welch ANOVA con eta-squared (per party voted)
Platform Welch_p eta_sq
Facebook 0.001 0.027
Instagram 0.005 0.018
Linkedin 0.007 0.021
Telegram 0.008 0.020
TikTok 0.000 0.038
Twitter_X 0.014 0.021
WhatsApp 0.560 0.008
YouTube 0.000 0.028
# Games–Howell post-hoc per vote
gh_results_vote <- data_PCA3 %>%
  tidyr::pivot_longer(
    cols      = dplyr::all_of(social_vars),
    names_to  = "Platform",
    values_to = "Frequency"
  ) %>%
  dplyr::group_by(Platform) %>%
  rstatix::games_howell_test(Frequency ~ Vote) %>%
  dplyr::mutate(
    p_sig = dplyr::case_when(
      p.adj < .001 ~ "***",
      p.adj < .01  ~ "**",
      p.adj < .05  ~ "*",
      TRUE        ~ ""
    )
  ) %>%
  dplyr::select(
    Platform, group1, group2,
    mean_difference = estimate, p.adj, p_sig
  )

knitr::kable(
  gh_results_vote,
  digits  = 3,
  caption = "Comparison post-hoc Games–Howell (per party voted)"
)
Comparison post-hoc Games–Howell (per party voted)
Platform group1 group2 mean_difference p.adj p_sig
Facebook +Europa Alleanza Verdi-Sinistra 0.851 0.494
Facebook +Europa Azione-Italia Viva 0.352 0.996
Facebook +Europa Did not vote 0.523 0.896
Facebook +Europa Forza Italia 1.358 0.072
Facebook +Europa Fratelli d’Italia 0.948 0.213
Facebook +Europa Lega 1.312 0.067
Facebook +Europa Movimento 5 Stelle 1.184 0.041 *
Facebook +Europa Other party 0.535 0.946
Facebook +Europa Partito Democratico 0.876 0.261
Facebook Alleanza Verdi-Sinistra Azione-Italia Viva -0.499 0.865
Facebook Alleanza Verdi-Sinistra Did not vote -0.328 0.971
Facebook Alleanza Verdi-Sinistra Forza Italia 0.508 0.935
Facebook Alleanza Verdi-Sinistra Fratelli d’Italia 0.097 1.000
Facebook Alleanza Verdi-Sinistra Lega 0.461 0.948
Facebook Alleanza Verdi-Sinistra Movimento 5 Stelle 0.333 0.963
Facebook Alleanza Verdi-Sinistra Other party -0.315 0.995
Facebook Alleanza Verdi-Sinistra Partito Democratico 0.025 1.000
Facebook Azione-Italia Viva Did not vote 0.171 1.000
Facebook Azione-Italia Viva Forza Italia 1.007 0.179
Facebook Azione-Italia Viva Fratelli d’Italia 0.596 0.459
Facebook Azione-Italia Viva Lega 0.960 0.161
Facebook Azione-Italia Viva Movimento 5 Stelle 0.833 0.058
Facebook Azione-Italia Viva Other party 0.184 1.000
Facebook Azione-Italia Viva Partito Democratico 0.524 0.540
Facebook Did not vote Forza Italia 0.835 0.270
Facebook Did not vote Fratelli d’Italia 0.425 0.607
Facebook Did not vote Lega 0.789 0.240
Facebook Did not vote Movimento 5 Stelle 0.661 0.043 *
Facebook Did not vote Other party 0.013 1.000
Facebook Did not vote Partito Democratico 0.353 0.687
Facebook Forza Italia Fratelli d’Italia -0.411 0.963
Facebook Forza Italia Lega -0.047 1.000
Facebook Forza Italia Movimento 5 Stelle -0.174 1.000
Facebook Forza Italia Other party -0.823 0.503
Facebook Forza Italia Partito Democratico -0.483 0.873
Facebook Fratelli d’Italia Lega 0.364 0.972
Facebook Fratelli d’Italia Movimento 5 Stelle 0.236 0.979
Facebook Fratelli d’Italia Other party -0.412 0.919
Facebook Fratelli d’Italia Partito Democratico -0.072 1.000
Facebook Lega Movimento 5 Stelle -0.128 1.000
Facebook Lega Other party -0.776 0.506
Facebook Lega Partito Democratico -0.436 0.885
Facebook Movimento 5 Stelle Other party -0.649 0.407
Facebook Movimento 5 Stelle Partito Democratico -0.308 0.786
Facebook Other party Partito Democratico 0.340 0.963
Instagram +Europa Alleanza Verdi-Sinistra 0.369 0.997
Instagram +Europa Azione-Italia Viva 0.044 1.000
Instagram +Europa Did not vote -0.280 0.999
Instagram +Europa Forza Italia 0.869 0.661
Instagram +Europa Fratelli d’Italia -0.227 1.000
Instagram +Europa Lega -0.029 1.000
Instagram +Europa Movimento 5 Stelle 0.125 1.000
Instagram +Europa Other party -0.397 0.996
Instagram +Europa Partito Democratico -0.368 0.993
Instagram Alleanza Verdi-Sinistra Azione-Italia Viva -0.325 0.994
Instagram Alleanza Verdi-Sinistra Did not vote -0.649 0.465
Instagram Alleanza Verdi-Sinistra Forza Italia 0.500 0.941
Instagram Alleanza Verdi-Sinistra Fratelli d’Italia -0.597 0.614
Instagram Alleanza Verdi-Sinistra Lega -0.398 0.990
Instagram Alleanza Verdi-Sinistra Movimento 5 Stelle -0.244 0.998
Instagram Alleanza Verdi-Sinistra Other party -0.766 0.480
Instagram Alleanza Verdi-Sinistra Partito Democratico -0.737 0.213
Instagram Azione-Italia Viva Did not vote -0.324 0.980
Instagram Azione-Italia Viva Forza Italia 0.825 0.422
Instagram Azione-Italia Viva Fratelli d’Italia -0.271 0.995
Instagram Azione-Italia Viva Lega -0.073 1.000
Instagram Azione-Italia Viva Movimento 5 Stelle 0.081 1.000
Instagram Azione-Italia Viva Other party -0.441 0.956
Instagram Azione-Italia Viva Partito Democratico -0.412 0.876
Instagram Did not vote Forza Italia 1.149 0.024 *
Instagram Did not vote Fratelli d’Italia 0.052 1.000
Instagram Did not vote Lega 0.251 0.999
Instagram Did not vote Movimento 5 Stelle 0.405 0.797
Instagram Did not vote Other party -0.117 1.000
Instagram Did not vote Partito Democratico -0.089 1.000
Instagram Forza Italia Fratelli d’Italia -1.097 0.044 *
Instagram Forza Italia Lega -0.898 0.470
Instagram Forza Italia Movimento 5 Stelle -0.744 0.426
Instagram Forza Italia Other party -1.266 0.037 *
Instagram Forza Italia Partito Democratico -1.238 0.007 **
Instagram Fratelli d’Italia Lega 0.199 1.000
Instagram Fratelli d’Italia Movimento 5 Stelle 0.352 0.916
Instagram Fratelli d’Italia Other party -0.170 1.000
Instagram Fratelli d’Italia Partito Democratico -0.141 1.000
Instagram Lega Movimento 5 Stelle 0.154 1.000
Instagram Lega Other party -0.368 0.995
Instagram Lega Partito Democratico -0.339 0.989
Instagram Movimento 5 Stelle Other party -0.522 0.792
Instagram Movimento 5 Stelle Partito Democratico -0.493 0.420
Instagram Other party Partito Democratico 0.029 1.000
Linkedin +Europa Alleanza Verdi-Sinistra 0.199 1.000
Linkedin +Europa Azione-Italia Viva -0.213 1.000
Linkedin +Europa Did not vote -0.350 0.985
Linkedin +Europa Forza Italia 0.199 1.000
Linkedin +Europa Fratelli d’Italia -0.696 0.479
Linkedin +Europa Lega -0.543 0.897
Linkedin +Europa Movimento 5 Stelle -0.195 1.000
Linkedin +Europa Other party -0.047 1.000
Linkedin +Europa Partito Democratico -0.406 0.948
Linkedin Alleanza Verdi-Sinistra Azione-Italia Viva -0.413 0.923
Linkedin Alleanza Verdi-Sinistra Did not vote -0.549 0.570
Linkedin Alleanza Verdi-Sinistra Forza Italia 0.000 1.000
Linkedin Alleanza Verdi-Sinistra Fratelli d’Italia -0.895 0.028 *
Linkedin Alleanza Verdi-Sinistra Lega -0.742 0.381
Linkedin Alleanza Verdi-Sinistra Movimento 5 Stelle -0.395 0.913
Linkedin Alleanza Verdi-Sinistra Other party -0.246 0.999
Linkedin Alleanza Verdi-Sinistra Partito Democratico -0.605 0.342
Linkedin Azione-Italia Viva Did not vote -0.136 1.000
Linkedin Azione-Italia Viva Forza Italia 0.413 0.967
Linkedin Azione-Italia Viva Fratelli d’Italia -0.483 0.434
Linkedin Azione-Italia Viva Lega -0.329 0.977
Linkedin Azione-Italia Viva Movimento 5 Stelle 0.018 1.000
Linkedin Azione-Italia Viva Other party 0.167 1.000
Linkedin Azione-Italia Viva Partito Democratico -0.193 0.995
Linkedin Did not vote Forza Italia 0.549 0.772
Linkedin Did not vote Fratelli d’Italia -0.346 0.656
Linkedin Did not vote Lega -0.193 0.999
Linkedin Did not vote Movimento 5 Stelle 0.154 0.999
Linkedin Did not vote Other party 0.303 0.974
Linkedin Did not vote Partito Democratico -0.056 1.000
Linkedin Forza Italia Fratelli d’Italia -0.895 0.134
Linkedin Forza Italia Lega -0.742 0.562
Linkedin Forza Italia Movimento 5 Stelle -0.395 0.965
Linkedin Forza Italia Other party -0.246 1.000
Linkedin Forza Italia Partito Democratico -0.605 0.607
Linkedin Fratelli d’Italia Lega 0.154 1.000
Linkedin Fratelli d’Italia Movimento 5 Stelle 0.501 0.202
Linkedin Fratelli d’Italia Other party 0.649 0.220
Linkedin Fratelli d’Italia Partito Democratico 0.290 0.699
Linkedin Lega Movimento 5 Stelle 0.347 0.948
Linkedin Lega Other party 0.496 0.842
Linkedin Lega Partito Democratico 0.136 1.000
Linkedin Movimento 5 Stelle Other party 0.149 1.000
Linkedin Movimento 5 Stelle Partito Democratico -0.211 0.975
Linkedin Other party Partito Democratico -0.359 0.889
Telegram +Europa Alleanza Verdi-Sinistra 0.287 1.000
Telegram +Europa Azione-Italia Viva -0.318 0.998
Telegram +Europa Did not vote 0.028 1.000
Telegram +Europa Forza Italia 0.653 0.911
Telegram +Europa Fratelli d’Italia 0.176 1.000
Telegram +Europa Lega -0.077 1.000
Telegram +Europa Movimento 5 Stelle 0.083 1.000
Telegram +Europa Other party 0.472 0.966
Telegram +Europa Partito Democratico -0.382 0.978
Telegram Alleanza Verdi-Sinistra Azione-Italia Viva -0.605 0.801
Telegram Alleanza Verdi-Sinistra Did not vote -0.259 0.999
Telegram Alleanza Verdi-Sinistra Forza Italia 0.366 0.998
Telegram Alleanza Verdi-Sinistra Fratelli d’Italia -0.111 1.000
Telegram Alleanza Verdi-Sinistra Lega -0.364 0.996
Telegram Alleanza Verdi-Sinistra Movimento 5 Stelle -0.204 1.000
Telegram Alleanza Verdi-Sinistra Other party 0.185 1.000
Telegram Alleanza Verdi-Sinistra Partito Democratico -0.669 0.493
Telegram Azione-Italia Viva Did not vote 0.346 0.956
Telegram Azione-Italia Viva Forza Italia 0.971 0.300
Telegram Azione-Italia Viva Fratelli d’Italia 0.494 0.749
Telegram Azione-Italia Viva Lega 0.241 1.000
Telegram Azione-Italia Viva Movimento 5 Stelle 0.402 0.903
Telegram Azione-Italia Viva Other party 0.790 0.258
Telegram Azione-Italia Viva Partito Democratico -0.064 1.000
Telegram Did not vote Forza Italia 0.625 0.786
Telegram Did not vote Fratelli d’Italia 0.148 1.000
Telegram Did not vote Lega -0.105 1.000
Telegram Did not vote Movimento 5 Stelle 0.056 1.000
Telegram Did not vote Other party 0.444 0.844
Telegram Did not vote Partito Democratico -0.410 0.565
Telegram Forza Italia Fratelli d’Italia -0.477 0.954
Telegram Forza Italia Lega -0.730 0.801
Telegram Forza Italia Movimento 5 Stelle -0.569 0.869
Telegram Forza Italia Other party -0.181 1.000
Telegram Forza Italia Partito Democratico -1.034 0.114
Telegram Fratelli d’Italia Lega -0.253 0.999
Telegram Fratelli d’Italia Movimento 5 Stelle -0.093 1.000
Telegram Fratelli d’Italia Other party 0.296 0.989
Telegram Fratelli d’Italia Partito Democratico -0.558 0.205
Telegram Lega Movimento 5 Stelle 0.160 1.000
Telegram Lega Other party 0.549 0.883
Telegram Lega Partito Democratico -0.305 0.992
Telegram Movimento 5 Stelle Other party 0.388 0.931
Telegram Movimento 5 Stelle Partito Democratico -0.465 0.416
Telegram Other party Partito Democratico -0.853 0.033 *
TikTok +Europa Alleanza Verdi-Sinistra -0.507 0.986
TikTok +Europa Azione-Italia Viva -1.020 0.351
TikTok +Europa Did not vote -0.556 0.941
TikTok +Europa Forza Italia 0.440 0.998
TikTok +Europa Fratelli d’Italia -0.638 0.870
TikTok +Europa Lega -0.667 0.919
TikTok +Europa Movimento 5 Stelle -0.169 1.000
TikTok +Europa Other party -0.117 1.000
TikTok +Europa Partito Democratico -1.084 0.200
TikTok Alleanza Verdi-Sinistra Azione-Italia Viva -0.514 0.874
TikTok Alleanza Verdi-Sinistra Did not vote -0.049 1.000
TikTok Alleanza Verdi-Sinistra Forza Italia 0.946 0.605
TikTok Alleanza Verdi-Sinistra Fratelli d’Italia -0.131 1.000
TikTok Alleanza Verdi-Sinistra Lega -0.161 1.000
TikTok Alleanza Verdi-Sinistra Movimento 5 Stelle 0.338 0.990
TikTok Alleanza Verdi-Sinistra Other party 0.389 0.990
TikTok Alleanza Verdi-Sinistra Partito Democratico -0.578 0.645
TikTok Azione-Italia Viva Did not vote 0.465 0.694
TikTok Azione-Italia Viva Forza Italia 1.460 0.036 *
TikTok Azione-Italia Viva Fratelli d’Italia 0.383 0.870
TikTok Azione-Italia Viva Lega 0.353 0.988
TikTok Azione-Italia Viva Movimento 5 Stelle 0.852 0.038 *
TikTok Azione-Italia Viva Other party 0.903 0.139
TikTok Azione-Italia Viva Partito Democratico -0.064 1.000
TikTok Did not vote Forza Italia 0.995 0.359
TikTok Did not vote Fratelli d’Italia -0.082 1.000
TikTok Did not vote Lega -0.112 1.000
TikTok Did not vote Movimento 5 Stelle 0.387 0.847
TikTok Did not vote Other party 0.438 0.914
TikTok Did not vote Partito Democratico -0.529 0.197
TikTok Forza Italia Fratelli d’Italia -1.078 0.250
TikTok Forza Italia Lega -1.107 0.379
TikTok Forza Italia Movimento 5 Stelle -0.609 0.912
TikTok Forza Italia Other party -0.557 0.970
TikTok Forza Italia Partito Democratico -1.524 0.014 *
TikTok Fratelli d’Italia Lega -0.029 1.000
TikTok Fratelli d’Italia Movimento 5 Stelle 0.469 0.623
TikTok Fratelli d’Italia Other party 0.520 0.784
TikTok Fratelli d’Italia Partito Democratico -0.446 0.403
TikTok Lega Movimento 5 Stelle 0.498 0.881
TikTok Lega Other party 0.550 0.906
TikTok Lega Partito Democratico -0.417 0.924
TikTok Movimento 5 Stelle Other party 0.051 1.000
TikTok Movimento 5 Stelle Partito Democratico -0.915 0.001 ***
TikTok Other party Partito Democratico -0.967 0.029 *
Twitter_X +Europa Alleanza Verdi-Sinistra 0.351 0.996
Twitter_X +Europa Azione-Italia Viva 0.350 0.994
Twitter_X +Europa Did not vote -0.024 1.000
Twitter_X +Europa Forza Italia 0.657 0.934
Twitter_X +Europa Fratelli d’Italia -0.104 1.000
Twitter_X +Europa Lega -0.187 1.000
Twitter_X +Europa Movimento 5 Stelle 0.237 1.000
Twitter_X +Europa Other party 0.538 0.941
Twitter_X +Europa Partito Democratico -0.278 0.997
Twitter_X Alleanza Verdi-Sinistra Azione-Italia Viva -0.002 1.000
Twitter_X Alleanza Verdi-Sinistra Did not vote -0.375 0.955
Twitter_X Alleanza Verdi-Sinistra Forza Italia 0.305 1.000
Twitter_X Alleanza Verdi-Sinistra Fratelli d’Italia -0.456 0.864
Twitter_X Alleanza Verdi-Sinistra Lega -0.538 0.914
Twitter_X Alleanza Verdi-Sinistra Movimento 5 Stelle -0.115 1.000
Twitter_X Alleanza Verdi-Sinistra Other party 0.186 1.000
Twitter_X Alleanza Verdi-Sinistra Partito Democratico -0.629 0.396
Twitter_X Azione-Italia Viva Did not vote -0.373 0.907
Twitter_X Azione-Italia Viva Forza Italia 0.307 0.999
Twitter_X Azione-Italia Viva Fratelli d’Italia -0.454 0.755
Twitter_X Azione-Italia Viva Lega -0.537 0.873
Twitter_X Azione-Italia Viva Movimento 5 Stelle -0.113 1.000
Twitter_X Azione-Italia Viva Other party 0.188 1.000
Twitter_X Azione-Italia Viva Partito Democratico -0.628 0.195
Twitter_X Did not vote Forza Italia 0.680 0.794
Twitter_X Did not vote Fratelli d’Italia -0.081 1.000
Twitter_X Did not vote Lega -0.164 1.000
Twitter_X Did not vote Movimento 5 Stelle 0.260 0.976
Twitter_X Did not vote Other party 0.561 0.686
Twitter_X Did not vote Partito Democratico -0.254 0.936
Twitter_X Forza Italia Fratelli d’Italia -0.761 0.675
Twitter_X Forza Italia Lega -0.844 0.728
Twitter_X Forza Italia Movimento 5 Stelle -0.420 0.989
Twitter_X Forza Italia Other party -0.119 1.000
Twitter_X Forza Italia Partito Democratico -0.934 0.347
Twitter_X Fratelli d’Italia Lega -0.083 1.000
Twitter_X Fratelli d’Italia Movimento 5 Stelle 0.341 0.879
Twitter_X Fratelli d’Italia Other party 0.642 0.504
Twitter_X Fratelli d’Italia Partito Democratico -0.174 0.995
Twitter_X Lega Movimento 5 Stelle 0.424 0.950
Twitter_X Lega Other party 0.725 0.670
Twitter_X Lega Partito Democratico -0.091 1.000
Twitter_X Movimento 5 Stelle Other party 0.301 0.993
Twitter_X Movimento 5 Stelle Partito Democratico -0.514 0.216
Twitter_X Other party Partito Democratico -0.816 0.120
WhatsApp +Europa Alleanza Verdi-Sinistra -0.138 1.000
WhatsApp +Europa Azione-Italia Viva -0.311 0.977
WhatsApp +Europa Did not vote -0.395 0.850
WhatsApp +Europa Forza Italia -0.068 1.000
WhatsApp +Europa Fratelli d’Italia -0.078 1.000
WhatsApp +Europa Lega -0.103 1.000
WhatsApp +Europa Movimento 5 Stelle -0.108 1.000
WhatsApp +Europa Other party -0.289 0.986
WhatsApp +Europa Partito Democratico -0.137 1.000
WhatsApp Alleanza Verdi-Sinistra Azione-Italia Viva -0.173 0.998
WhatsApp Alleanza Verdi-Sinistra Did not vote -0.257 0.920
WhatsApp Alleanza Verdi-Sinistra Forza Italia 0.070 1.000
WhatsApp Alleanza Verdi-Sinistra Fratelli d’Italia 0.060 1.000
WhatsApp Alleanza Verdi-Sinistra Lega 0.035 1.000
WhatsApp Alleanza Verdi-Sinistra Movimento 5 Stelle 0.031 1.000
WhatsApp Alleanza Verdi-Sinistra Other party -0.151 0.999
WhatsApp Alleanza Verdi-Sinistra Partito Democratico 0.001 1.000
WhatsApp Azione-Italia Viva Did not vote -0.084 1.000
WhatsApp Azione-Italia Viva Forza Italia 0.243 0.993
WhatsApp Azione-Italia Viva Fratelli d’Italia 0.233 0.950
WhatsApp Azione-Italia Viva Lega 0.208 0.996
WhatsApp Azione-Italia Viva Movimento 5 Stelle 0.203 0.980
WhatsApp Azione-Italia Viva Other party 0.022 1.000
WhatsApp Azione-Italia Viva Partito Democratico 0.174 0.991
WhatsApp Did not vote Forza Italia 0.327 0.913
WhatsApp Did not vote Fratelli d’Italia 0.317 0.474
WhatsApp Did not vote Lega 0.292 0.917
WhatsApp Did not vote Movimento 5 Stelle 0.287 0.632
WhatsApp Did not vote Other party 0.106 1.000
WhatsApp Did not vote Partito Democratico 0.258 0.677
WhatsApp Forza Italia Fratelli d’Italia -0.010 1.000
WhatsApp Forza Italia Lega -0.035 1.000
WhatsApp Forza Italia Movimento 5 Stelle -0.040 1.000
WhatsApp Forza Italia Other party -0.221 0.997
WhatsApp Forza Italia Partito Democratico -0.069 1.000
WhatsApp Fratelli d’Italia Lega -0.025 1.000
WhatsApp Fratelli d’Italia Movimento 5 Stelle -0.029 1.000
WhatsApp Fratelli d’Italia Other party -0.211 0.974
WhatsApp Fratelli d’Italia Partito Democratico -0.059 1.000
WhatsApp Lega Movimento 5 Stelle -0.004 1.000
WhatsApp Lega Other party -0.186 0.998
WhatsApp Lega Partito Democratico -0.034 1.000
WhatsApp Movimento 5 Stelle Other party -0.182 0.991
WhatsApp Movimento 5 Stelle Partito Democratico -0.030 1.000
WhatsApp Other party Partito Democratico 0.152 0.997
YouTube +Europa Alleanza Verdi-Sinistra 0.611 0.497
YouTube +Europa Azione-Italia Viva 0.552 0.644
YouTube +Europa Did not vote 0.474 0.696
YouTube +Europa Forza Italia 1.126 0.023 *
YouTube +Europa Fratelli d’Italia 0.608 0.353
YouTube +Europa Lega 0.395 0.969
YouTube +Europa Movimento 5 Stelle 0.711 0.139
YouTube +Europa Other party 0.558 0.688
YouTube +Europa Partito Democratico 0.059 1.000
YouTube Alleanza Verdi-Sinistra Azione-Italia Viva -0.059 1.000
YouTube Alleanza Verdi-Sinistra Did not vote -0.136 1.000
YouTube Alleanza Verdi-Sinistra Forza Italia 0.515 0.768
YouTube Alleanza Verdi-Sinistra Fratelli d’Italia -0.002 1.000
YouTube Alleanza Verdi-Sinistra Lega -0.215 0.999
YouTube Alleanza Verdi-Sinistra Movimento 5 Stelle 0.101 1.000
YouTube Alleanza Verdi-Sinistra Other party -0.053 1.000
YouTube Alleanza Verdi-Sinistra Partito Democratico -0.551 0.207
YouTube Azione-Italia Viva Did not vote -0.078 1.000
YouTube Azione-Italia Viva Forza Italia 0.574 0.646
YouTube Azione-Italia Viva Fratelli d’Italia 0.056 1.000
YouTube Azione-Italia Viva Lega -0.157 1.000
YouTube Azione-Italia Viva Movimento 5 Stelle 0.159 0.999
YouTube Azione-Italia Viva Other party 0.006 1.000
YouTube Azione-Italia Viva Partito Democratico -0.493 0.363
YouTube Did not vote Forza Italia 0.652 0.324
YouTube Did not vote Fratelli d’Italia 0.134 0.999
YouTube Did not vote Lega -0.079 1.000
YouTube Did not vote Movimento 5 Stelle 0.237 0.948
YouTube Did not vote Other party 0.083 1.000
YouTube Did not vote Partito Democratico -0.415 0.278
YouTube Forza Italia Fratelli d’Italia -0.518 0.650
YouTube Forza Italia Lega -0.730 0.484
YouTube Forza Italia Movimento 5 Stelle -0.415 0.852
YouTube Forza Italia Other party -0.568 0.710
YouTube Forza Italia Partito Democratico -1.066 0.003 **
YouTube Fratelli d’Italia Lega -0.213 0.999
YouTube Fratelli d’Italia Movimento 5 Stelle 0.103 1.000
YouTube Fratelli d’Italia Other party -0.051 1.000
YouTube Fratelli d’Italia Partito Democratico -0.549 0.037 *
YouTube Lega Movimento 5 Stelle 0.316 0.976
YouTube Lega Other party 0.162 1.000
YouTube Lega Partito Democratico -0.336 0.956
YouTube Movimento 5 Stelle Other party -0.154 1.000
YouTube Movimento 5 Stelle Partito Democratico -0.652 0.002 **
YouTube Other party Partito Democratico -0.498 0.467
# Grapth per party voted
ggplot(desc_stats_vote,
       aes(x = Vote, y = mean, fill = Vote)) +
  geom_col(position = "dodge", color = "black") +
  geom_errorbar(aes(ymin = mean - se, ymax = mean + se),
                width = 0.2,
                position = position_dodge(0.9)) +
  facet_wrap(~ Platform, scales = "free_y") +
  labs(
    title = "Platform use frequency and party voted in general elections",
    x     = "Party voted",
    y     = "Platform use frequency (±SE)"
  ) +
  scale_fill_viridis_d() +
  theme_minimal() +
  theme(
    legend.position = "none",
    axis.text.x = element_text(angle = 90, hjust = 1)
  )

# 13.3 Platform and age (Age_cat) -------------------

# Descriptives of platforms and age categories
desc_stats_age <- data_PCA3 %>%
  tidyr::pivot_longer(
    cols      = dplyr::all_of(social_vars),
    names_to  = "Platform",
    values_to = "Frequency"
  ) %>%
  dplyr::group_by(Platform, Age_cat) %>%
  dplyr::summarise(
    n    = dplyr::n(),
    mean = mean(Frequency, na.rm = TRUE),
    sd   = sd(Frequency, na.rm = TRUE),
    se   = sd / sqrt(n),
    .groups = "drop"
  )

knitr::kable(
  desc_stats_age,
  digits  = 2,
  caption = "Descriptives for platforms and age categories"
)
Descriptives for platforms and age categories
Platform Age_cat n mean sd se
Facebook 18_24 100 3.92 2.05 0.21
Facebook 25_34 157 4.53 1.79 0.14
Facebook 35_44 189 5.18 1.65 0.12
Facebook 45_54 251 4.93 1.83 0.12
Facebook 55_64 231 4.82 1.91 0.13
Facebook 65_+ 373 4.38 2.18 0.11
Instagram 18_24 100 5.58 1.53 0.15
Instagram 25_34 157 5.23 1.64 0.13
Instagram 35_44 189 5.02 1.81 0.13
Instagram 45_54 251 4.19 2.13 0.13
Instagram 55_64 231 3.74 2.06 0.14
Instagram 65_+ 373 2.71 2.07 0.11
Linkedin 18_24 100 2.59 1.97 0.20
Linkedin 25_34 157 3.03 1.84 0.15
Linkedin 35_44 189 3.08 1.93 0.14
Linkedin 45_54 251 2.37 1.60 0.10
Linkedin 55_64 231 2.12 1.51 0.10
Linkedin 65_+ 373 1.73 1.40 0.07
Telegram 18_24 100 3.83 2.06 0.21
Telegram 25_34 157 3.71 2.00 0.16
Telegram 35_44 189 3.67 2.11 0.15
Telegram 45_54 251 3.12 2.12 0.13
Telegram 55_64 231 2.75 1.93 0.13
Telegram 65_+ 373 1.95 1.71 0.09
TikTok 18_24 100 4.23 2.34 0.23
TikTok 25_34 157 3.12 2.24 0.18
TikTok 35_44 189 2.66 2.08 0.15
TikTok 45_54 251 2.51 2.06 0.13
TikTok 55_64 231 2.11 1.78 0.12
TikTok 65_+ 373 1.91 1.73 0.09
Twitter_X 18_24 100 3.18 2.14 0.21
Twitter_X 25_34 157 2.84 2.13 0.17
Twitter_X 35_44 189 2.71 2.09 0.15
Twitter_X 45_54 251 2.27 1.81 0.11
Twitter_X 55_64 231 2.17 1.75 0.12
Twitter_X 65_+ 373 2.01 1.80 0.09
WhatsApp 18_24 100 6.07 0.98 0.10
WhatsApp 25_34 157 5.91 1.08 0.09
WhatsApp 35_44 189 6.05 1.15 0.08
WhatsApp 45_54 251 6.01 0.99 0.06
WhatsApp 55_64 231 5.87 1.08 0.07
WhatsApp 65_+ 373 5.45 1.65 0.09
YouTube 18_24 100 4.97 1.53 0.15
YouTube 25_34 157 4.50 1.52 0.12
YouTube 35_44 189 4.58 1.65 0.12
YouTube 45_54 251 4.21 1.57 0.10
YouTube 55_64 231 3.95 1.60 0.11
YouTube 65_+ 373 3.57 1.76 0.09
# Welch ANOVA + eta squared per età
anova_results_age <- data_PCA3 %>%
  tidyr::pivot_longer(
    cols      = dplyr::all_of(social_vars),
    names_to  = "Platform",
    values_to = "Frequency"
  ) %>%
  dplyr::group_by(Platform) %>%
  dplyr::summarise(
    Welch_p = oneway.test(Frequency ~ Age_cat,
                          data = dplyr::cur_data(),
                          var.equal = FALSE)$p.value,
    eta_sq  = {
      eta_res <- rstatix::eta_squared(aov(Frequency ~ Age_cat,
                                          data = dplyr::cur_data()))
      if (is.data.frame(eta_res)) eta_res$Eta2[1] else as.numeric(eta_res[1])
    },
    .groups = "drop"
  )

knitr::kable(
  anova_results_age,
  digits  = 3,
  caption = "Welch ANOVA con eta-squared (per age class)"
)
Welch ANOVA con eta-squared (per age class)
Platform Welch_p eta_sq
Facebook 0 0.032
Instagram 0 0.210
Linkedin 0 0.086
Telegram 0 0.115
TikTok 0 0.097
Twitter_X 0 0.037
WhatsApp 0 0.037
YouTube 0 0.068
# Games–Howell post-hoc per age
gh_results_age <- data_PCA3 %>%
  tidyr::pivot_longer(
    cols      = dplyr::all_of(social_vars),
    names_to  = "Platform",
    values_to = "Frequency"
  ) %>%
  dplyr::group_by(Platform) %>%
  rstatix::games_howell_test(Frequency ~ Age_cat) %>%
  dplyr::mutate(
    p_sig = dplyr::case_when(
      p.adj < .001 ~ "***",
      p.adj < .01  ~ "**",
      p.adj < .05  ~ "*",
      TRUE        ~ ""
    )
  ) %>%
  dplyr::select(
    Platform, group1, group2,
    mean_difference = estimate, p.adj, p_sig
  )

knitr::kable(
  gh_results_age,
  digits  = 3,
  caption = "Comparison post-hoc Games–Howell (for age class)"
)
Comparison post-hoc Games–Howell (for age class)
Platform group1 group2 mean_difference p.adj p_sig
Facebook 18_24 25_34 0.614 0.151
Facebook 18_24 35_44 1.259 0.000 ***
Facebook 18_24 45_54 1.013 0.000 ***
Facebook 18_24 55_64 0.900 0.004 **
Facebook 18_24 65_+ 0.465 0.367
Facebook 25_34 35_44 0.645 0.009 **
Facebook 25_34 45_54 0.400 0.256
Facebook 25_34 55_64 0.286 0.665
Facebook 25_34 65_+ -0.149 0.965
Facebook 35_44 45_54 -0.246 0.685
Facebook 35_44 55_64 -0.359 0.310
Facebook 35_44 65_+ -0.794 0.000 ***
Facebook 45_54 55_64 -0.114 0.986
Facebook 45_54 65_+ -0.549 0.010 *
Facebook 55_64 65_+ -0.435 0.106
Instagram 18_24 25_34 -0.351 0.507
Instagram 18_24 35_44 -0.558 0.069
Instagram 18_24 45_54 -1.386 0.000 ***
Instagram 18_24 55_64 -1.836 0.000 ***
Instagram 18_24 65_+ -2.866 0.000 ***
Instagram 25_34 35_44 -0.208 0.876
Instagram 25_34 45_54 -1.035 0.000 ***
Instagram 25_34 55_64 -1.485 0.000 ***
Instagram 25_34 65_+ -2.515 0.000 ***
Instagram 35_44 45_54 -0.827 0.000 ***
Instagram 35_44 55_64 -1.277 0.000 ***
Instagram 35_44 65_+ -2.308 0.000 ***
Instagram 45_54 55_64 -0.450 0.181
Instagram 45_54 65_+ -1.480 0.000 ***
Instagram 55_64 65_+ -1.031 0.000 ***
Linkedin 18_24 25_34 0.440 0.480
Linkedin 18_24 35_44 0.494 0.340
Linkedin 18_24 45_54 -0.220 0.922
Linkedin 18_24 55_64 -0.468 0.291
Linkedin 18_24 65_+ -0.858 0.001 **
Linkedin 25_34 35_44 0.054 1.000
Linkedin 25_34 45_54 -0.660 0.004 **
Linkedin 25_34 55_64 -0.908 0.000 ***
Linkedin 25_34 65_+ -1.298 0.000 ***
Linkedin 35_44 45_54 -0.714 0.001 **
Linkedin 35_44 55_64 -0.962 0.000 ***
Linkedin 35_44 65_+ -1.352 0.000 ***
Linkedin 45_54 55_64 -0.249 0.519
Linkedin 45_54 65_+ -0.639 0.000 ***
Linkedin 55_64 65_+ -0.390 0.027 *
Telegram 18_24 25_34 -0.123 0.997
Telegram 18_24 35_44 -0.160 0.990
Telegram 18_24 45_54 -0.707 0.053
Telegram 18_24 55_64 -1.080 0.000 ***
Telegram 18_24 65_+ -1.875 0.000 ***
Telegram 25_34 35_44 -0.037 1.000
Telegram 25_34 45_54 -0.584 0.064
Telegram 25_34 55_64 -0.957 0.000 ***
Telegram 25_34 65_+ -1.752 0.000 ***
Telegram 35_44 45_54 -0.548 0.093
Telegram 35_44 55_64 -0.921 0.000 ***
Telegram 35_44 65_+ -1.716 0.000 ***
Telegram 45_54 55_64 -0.373 0.349
Telegram 45_54 65_+ -1.168 0.000 ***
Telegram 55_64 65_+ -0.795 0.000 ***
TikTok 18_24 25_34 -1.110 0.003 **
TikTok 18_24 35_44 -1.573 0.000 ***
TikTok 18_24 45_54 -1.718 0.000 ***
TikTok 18_24 55_64 -2.125 0.000 ***
TikTok 18_24 65_+ -2.324 0.000 ***
TikTok 25_34 35_44 -0.463 0.373
TikTok 25_34 45_54 -0.608 0.074
TikTok 25_34 55_64 -1.015 0.000 ***
TikTok 25_34 65_+ -1.215 0.000 ***
TikTok 35_44 45_54 -0.145 0.981
TikTok 35_44 55_64 -0.552 0.057
TikTok 35_44 65_+ -0.751 0.001 ***
TikTok 45_54 55_64 -0.407 0.204
TikTok 45_54 65_+ -0.607 0.003 **
TikTok 55_64 65_+ -0.200 0.773
Twitter_X 18_24 25_34 -0.342 0.819
Twitter_X 18_24 35_44 -0.474 0.482
Twitter_X 18_24 45_54 -0.909 0.004 **
Twitter_X 18_24 55_64 -1.015 0.001 ***
Twitter_X 18_24 65_+ -1.169 0.000 ***
Twitter_X 25_34 35_44 -0.133 0.993
Twitter_X 25_34 45_54 -0.568 0.075
Twitter_X 25_34 55_64 -0.674 0.018 *
Twitter_X 25_34 65_+ -0.828 0.001 ***
Twitter_X 35_44 45_54 -0.435 0.231
Twitter_X 35_44 55_64 -0.541 0.066
Twitter_X 35_44 65_+ -0.695 0.003 **
Twitter_X 45_54 55_64 -0.106 0.988
Twitter_X 45_54 65_+ -0.260 0.529
Twitter_X 55_64 65_+ -0.154 0.915
WhatsApp 18_24 25_34 -0.159 0.825
WhatsApp 18_24 35_44 -0.021 1.000
WhatsApp 18_24 45_54 -0.058 0.996
WhatsApp 18_24 55_64 -0.205 0.536
WhatsApp 18_24 65_+ -0.617 0.000 ***
WhatsApp 25_34 35_44 0.138 0.863
WhatsApp 25_34 45_54 0.101 0.932
WhatsApp 25_34 55_64 -0.046 0.999
WhatsApp 25_34 65_+ -0.458 0.002 **
WhatsApp 35_44 45_54 -0.037 0.999
WhatsApp 35_44 55_64 -0.184 0.559
WhatsApp 35_44 65_+ -0.596 0.000 ***
WhatsApp 45_54 55_64 -0.147 0.630
WhatsApp 45_54 65_+ -0.559 0.000 ***
WhatsApp 55_64 65_+ -0.413 0.003 **
YouTube 18_24 25_34 -0.470 0.160
YouTube 18_24 35_44 -0.393 0.344
YouTube 18_24 45_54 -0.757 0.001 ***
YouTube 18_24 55_64 -1.018 0.000 ***
YouTube 18_24 65_+ -1.398 0.000 ***
YouTube 25_34 35_44 0.077 0.998
YouTube 25_34 45_54 -0.287 0.449
YouTube 25_34 55_64 -0.548 0.010 *
YouTube 25_34 65_+ -0.928 0.000 ***
YouTube 35_44 45_54 -0.364 0.194
YouTube 35_44 55_64 -0.625 0.002 **
YouTube 35_44 65_+ -1.005 0.000 ***
YouTube 45_54 55_64 -0.260 0.470
YouTube 45_54 65_+ -0.641 0.000 ***
YouTube 55_64 65_+ -0.380 0.074
# Graph for age
ggplot(desc_stats_age,
       aes(x = Age_cat, y = mean, fill = Age_cat)) +
  geom_col(position = "dodge", color = "grey30") +
  geom_errorbar(aes(ymin = mean - se, ymax = mean + se),
                width = 0.2,
                position = position_dodge(0.9)) +
  facet_wrap(~ Platform, scales = "free_y") +
  labs(
    title = "Platform use frequence and age class",
    x     = "Age classes",
    y     = "Platform use frequence (±SE)"
  ) +
  scale_fill_viridis_d() +
  theme_minimal() +
  theme(
    legend.position = "none",
    axis.text.x = element_text(angle = 90, hjust = 1)
  )

OLS regression model (Platform use as DV)

# 14. OLS

library(broom)
Warning: il pacchetto 'broom' è stato creato con R versione 4.4.2
library(car)
Warning: il pacchetto 'car' è stato creato con R versione 4.4.3
Caricamento del pacchetto richiesto: carData
Warning: il pacchetto 'carData' è stato creato con R versione 4.4.3

Caricamento pacchetto: 'car'
Il seguente oggetto è mascherato da 'package:psych':

    logit
Il seguente oggetto è mascherato da 'package:dplyr':

    recode
library(purrr)
Warning: il pacchetto 'purrr' è stato creato con R versione 4.4.2

Caricamento pacchetto: 'purrr'
Il seguente oggetto è mascherato da 'package:car':

    some
Il seguente oggetto è mascherato da 'package:scales':

    discard
library(stringr)

# Dependent variables (platform use)
social_vars <- c("YouTube","WhatsApp","Twitter_X","Instagram",
                 "TikTok","Facebook","Linkedin","Telegram")

# Predictors (factors + latent factors of participation)
predictors <- c("Age_cat", "Vote", "Sex", "Left_Right",
                "Pol_int", "Info_Online", "Partisan_mobil")

# OLS per each platform
ols_results <- purrr::map_df(social_vars, function(var) {
  
  fml <- as.formula(
    paste(var, "~", paste(predictors, collapse = " + "))
  )
  
  model <- lm(fml, data = data_PCA3)
  
  coef_tbl <- broom::tidy(model, conf.int = TRUE) %>%
    dplyr::mutate(
      Dependent = var,
      Adj_R2    = summary(model)$adj.r.squared,
      F_stat    = broom::glance(model)$statistic,
      p_model   = broom::glance(model)$p.value
    )
  
  # VIF and robust merge
  vif_vals <- tryCatch(car::vif(model), error = function(e) NULL)
  
  if (!is.null(vif_vals)) {
    
    if (is.matrix(vif_vals)) {
      vif_df <- tibble(
        predictor_key = rownames(vif_vals),
        VIF           = vif_vals[, 1]
      )
    } else {
      vif_df <- tibble(
        predictor_key = names(vif_vals),
        VIF           = as.numeric(vif_vals)
      )
    }
    
    predictor_pattern <- paste(predictors, collapse = "|")
    
    coef_tbl <- coef_tbl %>%
      dplyr::mutate(
        predictor_key = stringr::str_extract(term, predictor_pattern)
      ) %>%
      dplyr::left_join(vif_df, by = "predictor_key") %>%
      dplyr::select(-predictor_key)
    
  } else {
    coef_tbl <- coef_tbl %>% dplyr::mutate(VIF = NA_real_)
  }
  
  coef_tbl
})

# Model fit
fit_summary <- ols_results %>%
  dplyr::group_by(Dependent) %>%
  dplyr::summarise(
    Adj_R2  = unique(Adj_R2),
    F_stat  = unique(F_stat),
    p_model = unique(p_model),
    .groups = "drop"
  )

knitr::kable(
  fit_summary,
  digits  = 3,
  caption = "Statistiche di fit del modello OLS per ciascuna piattaforma"
)
Statistiche di fit del modello OLS per ciascuna piattaforma
Dependent Adj_R2 F_stat p_model
Facebook 0.111 5.697 0
Instagram 0.276 15.217 0
Linkedin 0.168 8.360 0
Telegram 0.177 8.815 0
TikTok 0.158 7.797 0
Twitter_X 0.141 6.953 0
WhatsApp 0.063 3.540 0
YouTube 0.135 6.866 0
# Coefficients table
coef_table <- ols_results %>%
  dplyr::filter(term != "(Intercept)") %>%
  dplyr::mutate(
    Significant = ifelse(p.value < 0.05, "Yes", "No")
  ) %>%
  dplyr::select(
    Dependent, term, estimate, std.error,
    conf.low, conf.high, p.value, VIF, Significant
  )

knitr::kable(
  coef_table,
  digits  = 3,
  caption = "OLS coefficients (95% CI, VIF, significance)"
)
OLS coefficients (95% CI, VIF, significance)
Dependent term estimate std.error conf.low conf.high p.value VIF Significant
YouTube Age_cat25_34 -0.357 0.249 -0.847 0.132 0.152 1.215 No
YouTube Age_cat35_44 -0.080 0.239 -0.549 0.390 0.739 1.215 No
YouTube Age_cat45_54 -0.788 0.229 -1.238 -0.338 0.001 1.215 Yes
YouTube Age_cat55_64 -0.890 0.227 -1.336 -0.444 0.000 1.215 Yes
YouTube Age_cat65_+ -1.354 0.216 -1.779 -0.929 0.000 1.215 Yes
YouTube VoteAlleanza Verdi-Sinistra 0.711 0.349 0.027 1.394 0.042 3.310 Yes
YouTube VoteAzione-Italia Viva 0.738 0.331 0.088 1.388 0.026 3.310 Yes
YouTube VoteDid not vote 0.814 0.312 0.201 1.427 0.009 3.310 Yes
YouTube VoteForza Italia 1.266 0.392 0.497 2.035 0.001 3.310 Yes
YouTube VoteFratelli d’Italia 0.862 0.335 0.205 1.518 0.010 3.310 Yes
YouTube VoteLega 1.015 0.379 0.271 1.759 0.008 3.310 Yes
YouTube VoteMovimento 5 Stelle 0.825 0.305 0.226 1.424 0.007 3.310 Yes
YouTube VoteOther party 0.840 0.340 0.172 1.507 0.014 3.310 Yes
YouTube VotePartito Democratico 0.461 0.292 -0.111 1.033 0.114 3.310 No
YouTube SexFemale -0.124 0.105 -0.330 0.083 0.240 1.148 No
YouTube SexNon-binary 0.732 0.925 -1.084 2.548 0.429 1.148 No
YouTube Left_RightLeft 0.095 0.179 -0.256 0.446 0.595 3.052 No
YouTube Left_RightCenter 0.280 0.182 -0.078 0.637 0.125 3.052 No
YouTube Left_RightRight -0.033 0.230 -0.484 0.418 0.886 3.052 No
YouTube Left_RightExt_right 0.369 0.258 -0.137 0.874 0.153 3.052 No
YouTube Left_RightNo_position 0.390 0.212 -0.027 0.806 0.066 3.052 No
YouTube Pol_intSomewhat interested 0.419 0.137 0.151 0.688 0.002 1.661 Yes
YouTube Pol_intNot very interested 0.338 0.173 -0.002 0.678 0.051 1.661 No
YouTube Pol_intNot at all interested 0.172 0.259 -0.338 0.681 0.508 1.661 No
YouTube Info_Online 0.100 0.071 -0.040 0.240 0.161 1.679 No
YouTube Partisan_mobil 0.302 0.076 0.154 0.451 0.000 1.917 Yes
WhatsApp Age_cat25_34 -0.056 0.195 -0.440 0.327 0.774 1.219 No
WhatsApp Age_cat35_44 -0.136 0.187 -0.504 0.231 0.467 1.219 No
WhatsApp Age_cat45_54 -0.124 0.180 -0.477 0.229 0.492 1.219 No
WhatsApp Age_cat55_64 -0.280 0.179 -0.631 0.070 0.117 1.219 No
WhatsApp Age_cat65_+ -0.692 0.170 -1.026 -0.359 0.000 1.219 Yes
WhatsApp VoteAlleanza Verdi-Sinistra 0.038 0.274 -0.499 0.576 0.888 3.319 No
WhatsApp VoteAzione-Italia Viva -0.119 0.260 -0.629 0.391 0.648 3.319 No
WhatsApp VoteDid not vote -0.040 0.245 -0.521 0.441 0.869 3.319 No
WhatsApp VoteForza Italia 0.100 0.308 -0.504 0.704 0.744 3.319 No
WhatsApp VoteFratelli d’Italia 0.092 0.263 -0.424 0.607 0.727 3.319 No
WhatsApp VoteLega 0.162 0.296 -0.420 0.743 0.585 3.319 No
WhatsApp VoteMovimento 5 Stelle 0.179 0.240 -0.292 0.650 0.456 3.319 No
WhatsApp VoteOther party 0.049 0.266 -0.474 0.571 0.856 3.319 No
WhatsApp VotePartito Democratico 0.088 0.229 -0.361 0.538 0.700 3.319 No
WhatsApp SexFemale 0.220 0.082 0.059 0.382 0.008 1.146 Yes
WhatsApp SexNon-binary 0.611 0.727 -0.815 2.038 0.401 1.146 No
WhatsApp Left_RightLeft 0.098 0.140 -0.177 0.374 0.484 3.050 No
WhatsApp Left_RightCenter 0.099 0.143 -0.182 0.379 0.490 3.050 No
WhatsApp Left_RightRight 0.034 0.180 -0.319 0.388 0.849 3.050 No
WhatsApp Left_RightExt_right 0.172 0.201 -0.223 0.568 0.392 3.050 No
WhatsApp Left_RightNo_position -0.245 0.167 -0.571 0.082 0.142 3.050 No
WhatsApp Pol_intSomewhat interested 0.163 0.107 -0.047 0.372 0.128 1.642 No
WhatsApp Pol_intNot very interested 0.252 0.135 -0.014 0.517 0.063 1.642 No
WhatsApp Pol_intNot at all interested 0.114 0.204 -0.287 0.514 0.578 1.642 No
WhatsApp Info_Online -0.069 0.055 -0.178 0.040 0.212 1.670 No
WhatsApp Partisan_mobil 0.239 0.059 0.123 0.355 0.000 1.914 Yes
Twitter_X Age_cat25_34 -0.239 0.284 -0.796 0.317 0.399 1.225 No
Twitter_X Age_cat35_44 -0.284 0.272 -0.817 0.249 0.296 1.225 No
Twitter_X Age_cat45_54 -0.701 0.262 -1.215 -0.188 0.007 1.225 Yes
Twitter_X Age_cat55_64 -0.746 0.260 -1.255 -0.236 0.004 1.225 Yes
Twitter_X Age_cat65_+ -0.843 0.247 -1.328 -0.358 0.001 1.225 Yes
Twitter_X VoteAlleanza Verdi-Sinistra 0.207 0.401 -0.580 0.995 0.606 3.260 No
Twitter_X VoteAzione-Italia Viva 0.209 0.377 -0.532 0.949 0.580 3.260 No
Twitter_X VoteDid not vote 0.334 0.359 -0.370 1.038 0.352 3.260 No
Twitter_X VoteForza Italia 0.141 0.457 -0.755 1.037 0.757 3.260 No
Twitter_X VoteFratelli d’Italia -0.165 0.384 -0.919 0.589 0.668 3.260 No
Twitter_X VoteLega -0.030 0.437 -0.888 0.828 0.945 3.260 No
Twitter_X VoteMovimento 5 Stelle 0.058 0.350 -0.630 0.745 0.869 3.260 No
Twitter_X VoteOther party 0.482 0.388 -0.281 1.244 0.215 3.260 No
Twitter_X VotePartito Democratico 0.004 0.333 -0.651 0.658 0.991 3.260 No
Twitter_X SexFemale -0.082 0.121 -0.319 0.155 0.495 1.146 No
Twitter_X SexNon-binary 1.772 1.044 -0.277 3.821 0.090 1.146 No
Twitter_X Left_RightLeft 0.241 0.204 -0.159 0.641 0.237 3.026 No
Twitter_X Left_RightCenter 0.628 0.207 0.221 1.035 0.003 3.026 Yes
Twitter_X Left_RightRight 0.646 0.263 0.130 1.162 0.014 3.026 Yes
Twitter_X Left_RightExt_right 0.849 0.296 0.268 1.430 0.004 3.026 Yes
Twitter_X Left_RightNo_position 0.368 0.246 -0.115 0.851 0.135 3.026 No
Twitter_X Pol_intSomewhat interested 0.095 0.156 -0.210 0.401 0.541 1.648 No
Twitter_X Pol_intNot very interested -0.174 0.200 -0.567 0.218 0.383 1.648 No
Twitter_X Pol_intNot at all interested -0.442 0.300 -1.032 0.148 0.142 1.648 No
Twitter_X Info_Online 0.201 0.081 0.042 0.359 0.013 1.679 Yes
Twitter_X Partisan_mobil 0.487 0.086 0.317 0.656 0.000 1.911 Yes
Instagram Age_cat25_34 -0.347 0.301 -0.938 0.244 0.250 1.221 No
Instagram Age_cat35_44 -0.514 0.289 -1.082 0.054 0.076 1.221 No
Instagram Age_cat45_54 -1.292 0.278 -1.838 -0.747 0.000 1.221 Yes
Instagram Age_cat55_64 -1.780 0.276 -2.322 -1.239 0.000 1.221 Yes
Instagram Age_cat65_+ -2.911 0.262 -3.426 -2.396 0.000 1.221 Yes
Instagram VoteAlleanza Verdi-Sinistra 0.768 0.424 -0.064 1.599 0.070 3.294 No
Instagram VoteAzione-Italia Viva 0.767 0.400 -0.019 1.553 0.056 3.294 No
Instagram VoteDid not vote 0.560 0.378 -0.183 1.302 0.139 3.294 No
Instagram VoteForza Italia 1.058 0.477 0.122 1.994 0.027 3.294 Yes
Instagram VoteFratelli d’Italia 0.361 0.405 -0.434 1.157 0.373 3.294 No
Instagram VoteLega 0.692 0.460 -0.211 1.595 0.133 3.294 No
Instagram VoteMovimento 5 Stelle 0.638 0.370 -0.088 1.364 0.085 3.294 No
Instagram VoteOther party 0.112 0.414 -0.700 0.924 0.787 3.294 No
Instagram VotePartito Democratico 0.485 0.353 -0.208 1.178 0.170 3.294 No
Instagram SexFemale 0.884 0.128 0.633 1.134 0.000 1.145 Yes
Instagram SexNon-binary -0.693 1.121 -2.892 1.506 0.536 1.145 No
Instagram Left_RightLeft 0.097 0.218 -0.330 0.525 0.655 3.024 No
Instagram Left_RightCenter 0.385 0.222 -0.051 0.821 0.084 3.024 No
Instagram Left_RightRight 0.338 0.280 -0.212 0.887 0.228 3.024 No
Instagram Left_RightExt_right 0.561 0.313 -0.054 1.176 0.074 3.024 No
Instagram Left_RightNo_position 0.070 0.261 -0.442 0.582 0.788 3.024 No
Instagram Pol_intSomewhat interested 0.238 0.165 -0.086 0.563 0.150 1.651 No
Instagram Pol_intNot very interested 0.275 0.210 -0.137 0.686 0.191 1.651 No
Instagram Pol_intNot at all interested 0.111 0.316 -0.508 0.731 0.724 1.651 No
Instagram Info_Online 0.163 0.086 -0.005 0.331 0.057 1.670 No
Instagram Partisan_mobil 0.326 0.092 0.146 0.507 0.000 1.919 Yes
TikTok Age_cat25_34 -1.137 0.296 -1.718 -0.556 0.000 1.230 Yes
TikTok Age_cat35_44 -1.499 0.284 -2.057 -0.941 0.000 1.230 Yes
TikTok Age_cat45_54 -1.601 0.274 -2.138 -1.063 0.000 1.230 Yes
TikTok Age_cat55_64 -2.000 0.272 -2.533 -1.467 0.000 1.230 Yes
TikTok Age_cat65_+ -2.136 0.258 -2.643 -1.629 0.000 1.230 Yes
TikTok VoteAlleanza Verdi-Sinistra -0.505 0.418 -1.326 0.316 0.227 3.303 No
TikTok VoteAzione-Italia Viva -0.693 0.395 -1.468 0.083 0.080 3.303 No
TikTok VoteDid not vote -0.327 0.376 -1.065 0.410 0.384 3.303 No
TikTok VoteForza Italia -0.056 0.472 -0.982 0.870 0.906 3.303 No
TikTok VoteFratelli d’Italia -0.761 0.401 -1.549 0.026 0.058 3.303 No
TikTok VoteLega -0.481 0.453 -1.370 0.408 0.289 3.303 No
TikTok VoteMovimento 5 Stelle -0.034 0.367 -0.754 0.687 0.927 3.303 No
TikTok VoteOther party 0.044 0.411 -0.763 0.851 0.915 3.303 No
TikTok VotePartito Democratico -0.494 0.349 -1.179 0.191 0.157 3.303 No
TikTok SexFemale 0.374 0.126 0.126 0.622 0.003 1.150 Yes
TikTok SexNon-binary 0.248 1.093 -1.897 2.394 0.820 1.150 No
TikTok Left_RightLeft -0.078 0.214 -0.498 0.342 0.714 3.033 No
TikTok Left_RightCenter 0.347 0.217 -0.079 0.773 0.110 3.033 No
TikTok Left_RightRight 0.694 0.274 0.157 1.231 0.011 3.033 Yes
TikTok Left_RightExt_right 1.202 0.306 0.601 1.804 0.000 3.033 Yes
TikTok Left_RightNo_position 0.392 0.256 -0.111 0.894 0.127 3.033 No
TikTok Pol_intSomewhat interested 0.488 0.163 0.168 0.808 0.003 1.646 Yes
TikTok Pol_intNot very interested 0.437 0.208 0.029 0.845 0.036 1.646 Yes
TikTok Pol_intNot at all interested -0.055 0.313 -0.668 0.558 0.860 1.646 No
TikTok Info_Online 0.356 0.084 0.190 0.521 0.000 1.672 Yes
TikTok Partisan_mobil 0.096 0.090 -0.082 0.273 0.290 1.915 No
Facebook Age_cat25_34 0.631 0.299 0.046 1.217 0.035 1.215 Yes
Facebook Age_cat35_44 1.451 0.286 0.890 2.013 0.000 1.215 Yes
Facebook Age_cat45_54 1.163 0.274 0.625 1.702 0.000 1.215 Yes
Facebook Age_cat55_64 1.078 0.272 0.544 1.612 0.000 1.215 Yes
Facebook Age_cat65_+ 0.571 0.259 0.062 1.080 0.028 1.215 Yes
Facebook VoteAlleanza Verdi-Sinistra 0.716 0.416 -0.100 1.532 0.085 3.331 No
Facebook VoteAzione-Italia Viva 0.428 0.394 -0.346 1.202 0.278 3.331 No
Facebook VoteDid not vote 0.682 0.373 -0.049 1.413 0.068 3.331 No
Facebook VoteForza Italia 1.072 0.468 0.155 1.990 0.022 3.331 Yes
Facebook VoteFratelli d’Italia 0.436 0.399 -0.347 1.219 0.275 3.331 No
Facebook VoteLega 0.994 0.451 0.108 1.880 0.028 3.331 Yes
Facebook VoteMovimento 5 Stelle 1.136 0.365 0.419 1.852 0.002 3.331 Yes
Facebook VoteOther party 0.239 0.405 -0.557 1.034 0.556 3.331 No
Facebook VotePartito Democratico 0.920 0.348 0.237 1.602 0.008 3.331 Yes
Facebook SexFemale 0.627 0.125 0.381 0.873 0.000 1.147 Yes
Facebook SexNon-binary 0.930 1.104 -1.237 3.097 0.400 1.147 No
Facebook Left_RightLeft -0.017 0.214 -0.436 0.402 0.935 3.055 No
Facebook Left_RightCenter 0.261 0.217 -0.166 0.688 0.231 3.055 No
Facebook Left_RightRight 0.499 0.274 -0.039 1.037 0.069 3.055 No
Facebook Left_RightExt_right 0.823 0.307 0.220 1.426 0.007 3.055 Yes
Facebook Left_RightNo_position 0.055 0.254 -0.443 0.553 0.828 3.055 No
Facebook Pol_intSomewhat interested 0.100 0.162 -0.219 0.418 0.538 1.652 No
Facebook Pol_intNot very interested 0.426 0.206 0.022 0.831 0.039 1.652 Yes
Facebook Pol_intNot at all interested 0.242 0.309 -0.365 0.849 0.434 1.652 No
Facebook Info_Online -0.001 0.085 -0.168 0.167 0.993 1.669 No
Facebook Partisan_mobil 0.499 0.090 0.322 0.676 0.000 1.908 Yes
Linkedin Age_cat25_34 0.581 0.237 0.116 1.046 0.014 1.227 Yes
Linkedin Age_cat35_44 0.820 0.227 0.374 1.266 0.000 1.227 Yes
Linkedin Age_cat45_54 0.077 0.218 -0.351 0.505 0.724 1.227 No
Linkedin Age_cat55_64 -0.031 0.217 -0.457 0.395 0.886 1.227 No
Linkedin Age_cat65_+ -0.456 0.206 -0.861 -0.051 0.027 1.227 Yes
Linkedin VoteAlleanza Verdi-Sinistra 0.108 0.337 -0.553 0.769 0.750 3.383 No
Linkedin VoteAzione-Italia Viva -0.103 0.318 -0.726 0.521 0.747 3.383 No
Linkedin VoteDid not vote -0.193 0.301 -0.783 0.398 0.522 3.383 No
Linkedin VoteForza Italia -0.309 0.378 -1.050 0.432 0.413 3.383 No
Linkedin VoteFratelli d’Italia -0.826 0.324 -1.462 -0.189 0.011 3.383 Yes
Linkedin VoteLega -0.600 0.369 -1.324 0.124 0.104 3.383 No
Linkedin VoteMovimento 5 Stelle -0.262 0.295 -0.840 0.317 0.375 3.383 No
Linkedin VoteOther party -0.094 0.329 -0.738 0.551 0.776 3.383 No
Linkedin VotePartito Democratico -0.014 0.281 -0.565 0.537 0.960 3.383 No
Linkedin SexFemale -0.084 0.101 -0.283 0.115 0.407 1.145 No
Linkedin SexNon-binary 0.000 0.878 -1.723 1.723 1.000 1.145 No
Linkedin Left_RightLeft 0.103 0.171 -0.234 0.439 0.549 3.083 No
Linkedin Left_RightCenter 0.712 0.174 0.370 1.054 0.000 3.083 Yes
Linkedin Left_RightRight 0.890 0.221 0.456 1.324 0.000 3.083 Yes
Linkedin Left_RightExt_right 1.004 0.248 0.518 1.491 0.000 3.083 Yes
Linkedin Left_RightNo_position 0.552 0.206 0.147 0.957 0.008 3.083 Yes
Linkedin Pol_intSomewhat interested 0.143 0.131 -0.115 0.400 0.277 1.645 No
Linkedin Pol_intNot very interested -0.062 0.167 -0.391 0.266 0.710 1.645 No
Linkedin Pol_intNot at all interested -0.406 0.252 -0.901 0.089 0.108 1.645 No
Linkedin Info_Online 0.427 0.068 0.294 0.561 0.000 1.683 Yes
Linkedin Partisan_mobil 0.024 0.072 -0.118 0.166 0.742 1.920 No
Telegram Age_cat25_34 -0.070 0.295 -0.648 0.509 0.814 1.239 No
Telegram Age_cat35_44 0.033 0.283 -0.522 0.588 0.906 1.239 No
Telegram Age_cat45_54 -0.555 0.273 -1.090 -0.020 0.042 1.239 Yes
Telegram Age_cat55_64 -0.789 0.270 -1.319 -0.260 0.004 1.239 Yes
Telegram Age_cat65_+ -1.557 0.258 -2.064 -1.050 0.000 1.239 Yes
Telegram VoteAlleanza Verdi-Sinistra 0.186 0.416 -0.631 1.002 0.655 3.365 No
Telegram VoteAzione-Italia Viva -0.261 0.394 -1.035 0.512 0.507 3.365 No
Telegram VoteDid not vote 0.277 0.374 -0.457 1.011 0.459 3.365 No
Telegram VoteForza Italia 0.237 0.472 -0.690 1.164 0.616 3.365 No
Telegram VoteFratelli d’Italia 0.158 0.401 -0.630 0.946 0.695 3.365 No
Telegram VoteLega 0.186 0.456 -0.709 1.080 0.684 3.365 No
Telegram VoteMovimento 5 Stelle 0.104 0.365 -0.612 0.820 0.775 3.365 No
Telegram VoteOther party 0.632 0.406 -0.165 1.429 0.120 3.365 No
Telegram VotePartito Democratico 0.112 0.348 -0.570 0.794 0.747 3.365 No
Telegram SexFemale -0.253 0.126 -0.501 -0.006 0.045 1.150 Yes
Telegram SexNon-binary -0.240 1.088 -2.375 1.896 0.826 1.150 No
Telegram Left_RightLeft 0.643 0.213 0.225 1.061 0.003 3.067 Yes
Telegram Left_RightCenter 0.832 0.217 0.407 1.258 0.000 3.067 Yes
Telegram Left_RightRight 1.034 0.275 0.493 1.574 0.000 3.067 Yes
Telegram Left_RightExt_right 1.276 0.309 0.669 1.883 0.000 3.067 Yes
Telegram Left_RightNo_position 0.863 0.254 0.365 1.361 0.001 3.067 Yes
Telegram Pol_intSomewhat interested 0.220 0.163 -0.100 0.539 0.177 1.658 No
Telegram Pol_intNot very interested 0.147 0.207 -0.260 0.554 0.478 1.658 No
Telegram Pol_intNot at all interested -0.106 0.312 -0.717 0.506 0.734 1.658 No
Telegram Info_Online 0.410 0.084 0.245 0.575 0.000 1.686 Yes
Telegram Partisan_mobil 0.201 0.090 0.024 0.378 0.026 1.937 Yes
# Coefficient plot
coef_table %>%
  dplyr::mutate(
    term = stringr::str_replace_all(
      term,
      c(
        "Age_cat" = "Age: ",
        "Vote"    = "Vote: ",
        "Sex"     = "Sex: ",
        "Left_Right" = "L–R: ",
        "Pol_int"    = "Pol. interest: ",
        "\\[T\\."    = "",
        "\\]"        = ""
      )
    )
  ) %>%
  ggplot(aes(
    y     = reorder(term, estimate),
    x     = estimate,
    color = Significant,
    shape = Significant
  )) +
  geom_point(position = position_dodge(width = 0.5), size = 1) +
  geom_errorbar(aes(xmin = conf.low, xmax = conf.high),
                height   = 0.2,
                position = position_dodge(width = 0.5),
                orientation = "y") +
  geom_vline(xintercept = 0, linetype = "dashed", color = "gray50") +
  facet_wrap(~ Dependent, scales = "free_y", ncol = 2) +
  scale_color_manual(values = c("No" = "gray50", "Yes" = "#E69F00")) +
  scale_shape_manual(values = c("No" = 16, "Yes" = 17)) +
  theme_bw(base_size = 6) +
  theme(
    legend.position       = "bottom",
    panel.grid.minor      = element_blank(),
    panel.grid.major.y    = element_blank(),
    strip.background      = element_rect(fill = "gray90"),
    axis.text.y           = element_text(size = 4)
  ) +
  labs(
    title    = "OLS coefficients per platform",
    subtitle = "Statistically significant coefficients (p < .05)",
    y        = "Predictors",
    x        = "Coefficient extimation (±95% CI)",
    color    = "Significant:",
    shape    = "Significant:"
  )
`height` was translated to `width`.