digipol 1 – Italy replication

Published

November 24, 2025

1 Define data MP_DATASET

Code
# 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)

2 Define the USES_DATASET

Code
# 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))

# Summary table by purpose (overall across all platforms)
summary_table_purpose <- data_platform_use %>%
  dplyr::count(Purpose, Response) %>%
  dplyr::group_by(Purpose) %>%
  dplyr::mutate(
    Percentage = n / sum(n) * 100,
    Purpose = factor(Purpose, levels = purpose_labels)
  ) %>%
  dplyr::ungroup() %>%
  dplyr::arrange(Purpose, desc(Response))

# Visualizza la tabella
summary_table_purpose
Code
# 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)
  )

Italy. Social media use is generally moderate, with platforms mostly serving relational purposes (friends/family). Political engagement is concentrated almost entirely on TwitterX and—more marginally—Telegram. WhatsApp and Instagram remain predominantly social, while YouTube shows a notable share of “other” uses.

*Compared with Spain, Italy displays lower overall usage levels and a less intense sociality across all major platforms. Spain shows broader and more versatile engagement—especially on Instagram, WhatsApp and YouTube—while Italy stands out mainly for the comparatively stronger political use of TwitterX.

3 Set platform per purpose

Code
# 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")
  )

Code
# 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
Code
### 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
Code
# 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

The overlap between political information and support for political causes is strongly asymmetric: those who do not seek political information on social media almost never support causes (only 3.4%). In contrast, among those who use social media for political information, about four out of five also engage in supporting causes. The politically active online public therefore appears concentrated and consistent in its practices, while the non-political users remain largely impermeable polarization between purely non-political uses and a smaller but highly engaged cluster.

4 Descriptive plots: platform use and purposes

Code
# 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)))

Code
## 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)))

Code
## 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)))

Code
# 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)))

The Italian pattern shows a strongly asymmetric ecosystem: WhatsApp, Facebook, Instagram and YouTube concentrate the bulk of high-frequency users, while platforms linked to news or public debate (Twitter/X, LinkedIn) remain marginal and used mostly sporadically. The contrast between “never users” and “daily users” is especially visible on WhatsApp and Facebook, indicating polarized usage habits. Younger-oriented platforms like TikTok show moderate engagement but still far from the levels of Instagram. Telegram displays an intermediate profile, with a large share of occasional users but fewer daily ones. Overall, the Italian landscape is dominated by interpersonal and entertainment-driven platforms rather than explicitly political ones.

*Compared with Spain, Italian users rely more heavily on WhatsApp and Facebook for daily communication and information exchange. Spain generally shows higher engagement on Instagram and TikTok, reflecting a more youth-skewed and mobile-centric pattern. Twitter/X tends to be more integrated into political conversation in Spain than in Italy, where it remains niche. Overall, Spain exhibits a more diversified platform ecology, while Italy shows stronger dependence on a few dominant channels.

4.1 Sociopolitical variables and platform use

Code
## 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 = "darkorange") +
  theme_minimal() +
  labs(
    title = "Use of Social Media to Inform Oneself Politically (Any Platform)",
    x = NULL,
    y = "Count"
  )

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

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

Code
# 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"
  )

4.2 Sociopolitical variables descriptives

Code
## 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))

Code
# 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))

Code
# 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))

Code
# 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))

Code
# 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))

Code
# 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))

As concerns, Left–Right self-location, the Italian distribution appears weakly structured: middle categories do not dominate, while small, irregular peaks appear across the entire scale. Two elements stand out: (1) a sizeable group placing itself at the far right; (2) a very large “no answer” category, indicating ideological distance, uncertainty, or low cognitive anchoring. Overall, the pattern suggests that a significant share of respondents does not internalize the left–right dimension strongly, while those who do tend to adopt clearer, sometimes polarized positions. Political interest shows a much more coherent profile: the majority falls in the middle (“somewhat interested”), while the extremes—very interested or not interested at all—remain minorities. This points to a “moderately engaged” public: not apathetic, yet not strongly mobilized either. The notable minority reporting no interest at all indicates a segment disconnected from political life. Exposure to viewpoints one disagrees with is concentrated in the middle categories (“sometimes”, “often”), while the extremes—constant exposure or total absence—are limited. This suggests that the online information environment is not fully siloed: many Italians encounter disagreement, though in an intermittent rather than systematic way. Algorithms filter content, but do not completely seal individuals off from cross-cutting perspectives. The Italian data portray an electorate that is ideologically fragmented and only partially anchored to the left–right dimension: the distribution is uneven, with irregular concentrations along the scale and a remarkably high share of respondents who avoid placing themselves altogether.

*The Spanish pattern, in contrast, is noticeably more orderly and symmetrical, suggesting that ideological self-location functions as a clearer cognitive compass. Political interest reinforces this difference: in Italy, most respondents converge in the middle categories, forming a bloc of moderate but not particularly intense engagement; Spain instead shows stronger tails, with more individuals who follow politics very closely and, simultaneously, more who reject it entirely. This produces a more polarized landscape of attentiveness. Finally, exposure to disagreeing views online is more frequent and more evenly spread in Spain, whereas Italians tend to encounter cross-cutting information in a more sporadic and less systematic manner. Taken together, these contrasts depict Spain as a context where political orientations and engagement practices are more crystallized, while Italy appears marked by ideological looseness, moderate interest, and a comparatively softer circulation of dissonant content.

5 PCA preparation

Code
# 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 
Code
# 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
Code
# 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
Code
caret::findCorrelation(cor_matrix, cutoff = 0.9)
integer(0)

6 PCA Estimation & visualization

Code
# 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
)

# 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 |
Code
# 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
Code
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
Code
# 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
)

p

The PCA reveals a very clear structure in social-media usage patterns. Dimension 1 (39%) separates high-intensity, mainstream social platforms—WhatsApp, Facebook, Instagram—which cluster together and strongly shape this axis. This component can be read as a general intensity of social-media use. Dimension 2 (15%) contrasts visual/entertainment platforms (YouTube, TikTok) with more informational or professional platforms (Twitter/X, LinkedIn, Telegram). This dimension captures a shift from entertainment-oriented to information-oriented usage. The contribution levels show that WhatsApp, Facebook, and Instagram dominate the first dimension, while YouTube and TikTok drive the second. PCA suggests two robust patterns: (a) General social-media intensity (Dim1); (b) Entertainment-visual vs. informational-professional orientation (Dim2). The configuration aligns well with typical distinctions found in the literature.

*The Italian and Spanish PCA maps share the same basic structure: Dim1 captures general social-media intensity, while Dim2 separates entertainment-oriented platforms (YouTube, TikTok) from informational/professional ones (Twitter/X, LinkedIn). The difference lies in the degree of separation. In Italy, Facebook, WhatsApp and Instagram cluster tightly, showing a more homogeneous mainstream use. In Spain, this cluster is more dispersed and the contrast along Dim2 is sharper, especially for Twitter/X and LinkedIn, which are more clearly positioned as informational tools. YouTube is more central in the Italian plot, indicating more overlap with generalist use, whereas in Spain its entertainment orientation is more distinct. In short: Italy shows a more blended pattern; Spain shows clearer segmentation of platform types.

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

Code
# 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
  )

Code
# 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
  )

Code
# 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
  )

Code
# 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
  )

Code
# 7.6 Biplot with gender centroids
p + 
  geom_point(
    data = Sex_coords %>% dplyr::filter(Category != "Non-binary"),
    aes(x = Dim.1, y = Dim.2),
    color = "darkblue", size = 3, shape = 20
  ) +
  ggrepel::geom_text_repel(
    data = Sex_coords %>% dplyr::filter(Category != "Non-binary"),
    aes(x = Dim.1, y = Dim.2, label = Category),
    color = "darkblue",
    size  = 3.5
  )

Code
# 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
  )

Code
# 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
  )

Code
# 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
  )

Across all PCA plots, the structure of social-media use in the Italian data is remarkably stable: the first dimension consistently captures a gradient of general intensity, defined by the tight cluster formed by WhatsApp, Facebook and Instagram, while the second dimension distinguishes visual/entertainment platforms such as YouTube and TikTok from informational or professional tools like Twitter/X, LinkedIn and Telegram. When the political and socio-demographic variables are projected into this space, they do not reshape the underlying structure but position themselves relative to these two axes. Voting categories and left–right self-placement remain very close to the centre of the map, indicating that neither variable is strongly associated with specific platform clusters. Political interest, instead, shows a clearer pattern: higher-interest respondents lie nearer to the informational/professional platforms, whereas low-interest groups appear toward the lower-intensity side of Dim1. Gender categories display minimal separation and stay largely central, which suggests limited differentiation in platform use. The same modest but coherent tendency appears with exposure to political disagreement: respondents who report more frequent exposure position somewhat closer to the informational side of Dim2, while those who report rare or no exposure remain centrally located. Taken together, these results show that the Italian PCA distinguishes platform types in a consistent and interpretable way, while most political and demographic factors exert only weak differentiation, with political interest—and to a lesser extent exposure to disagreement—showing the most structured alignment with the informational dimension.

*Across both countries, the overall structure of the PCA is highly similar. In Italy and Spain alike, Dim1 reflects a gradient of general social-media intensity, with WhatsApp, Facebook and Instagram forming a compact cluster with the strongest contributions. Likewise, Dim2 separates YouTube and TikTok—positioned toward the visual/entertainment side—from Twitter/X, LinkedIn and Telegram, which align with the informational/professional pole. This shared structure suggests that, in both contexts, platform types organise usage patterns in a remarkably consistent way. The main differences emerge when the supplementary variables are projected. In Italy, most political and demographic categories remain close to the origin, indicating weak differentiation across all variables except political interest, which shows the clearest alignment with the informational dimension. In Spain, by contrast, some variables display slightly more pronounced positioning, especially on Dim2. Left–right ideology, interest, exposure to disagreement, and information-checking behaviours tend to stretch further toward the informational or low-intensity sides than in the Italian maps. This indicates that in Spain, political engagement variables are somewhat more structured in relation to platform types. A second difference concerns the dispersion of categories. Italian categories are generally more compact and central, while Spanish categories show greater spread, especially for political interest and the information-seeking dimensions (inf_check, inf_confirm). In Spain, high-engagement levels cluster more distinctly near Twitter/X and LinkedIn, and low-engagement categories more clearly toward low-intensity areas. The gradients are therefore clearer and more directional in the Spanish results. Despite these differences in the strength of associations, the core geometry remains the same in both countries: (a) intensive/mainstream use on Dim1; (b) entertainment vs. informational orientation on Dim2; (c) political variables projecting onto this space without altering its structure. Italy and Spain share the same fundamental platform structure, but Spain shows slightly stronger alignment between political engagement variables and the informational–entertainment axis, while Italy displays a more central and compact distribution of categories with fewer marked distinctions.

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

Code
# 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 (remove the #)
# str(data_PCA2)  

# 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
)

# 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
)

In the Italian data, platform use is organised around a compact mainstream cluster—WhatsApp, Facebook and Instagram—that structures the first dimension, while informational and political purposes remain relatively central, producing a less sharply differentiated configuration across platform types. In both countries the structure is almost identical: Dim1 reflects a gradient of general social-media intensity, driven by WhatsApp, Facebook and Instagram, while Dim2 separates visual/entertainment platforms (YouTube, TikTok) from informational/professional platforms (Twitter/X, LinkedIn, Telegram). This shared geometry indicates that users in Italy and Spain organise their platform use along the same two underlying dimensions. In both countries, informational and political purposes (information socially; supporting social or political causes; political information) cluster near Twitter/X, LinkedIn, Telegram, aligning with the informational pole of Dim2. Meanwhile, more general or social purposes fall closer to the centre or slightly toward the mainstream cluster, indicating that they overlap with general, high-intensity use but do not distinguish platform types as sharply. The main difference lies in the strength of alignment. In the Spanish data, political and informational purposes appear more clearly pulled toward Twitter/X and LinkedIn, producing a slightly stronger separation along Dim2. In the Italian map, the same purposes are present but show a more compact and central position, suggesting weaker differentiation across platform types. The two countries share the same structure, but Spain displays sharper contrasts between entertainment-oriented and informational/political use, whereas Italy shows a more blended configuration with less pronounced distinctions.

9 Factor Analysis of online and offline political participation

Code
# 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
  )

# 1) Number of NA per variable 
cat("Number of missing values per variable:\n")
Number of missing values per variable:
Code
print(colSums(is.na(dplyr::select(data_FACTOR, -id))))
       pol_inf_on          liked_on         shared_on         posted_on 
               23                23                35                21 
       discuss_on        comment_on        profile_on      vol_party_on 
               27                27                31                35 
   donat_party_on      donat_NGO_on     vol_social_on        contact_on 
               24                39                30                23 
      petition_on      pol_meet_off        strike_off       demonst_off 
               16                22                23                20 
  org_demonst_off       discuss_off     vol_party_off   donat_party_off 
               25                21                22                27 
    donat_NGO_off       contact_off read_campaign_off      petition_off 
               30                17                25                26 
      boycott_off        button_off 
               34                23 
Code
# 2) List of participation variables
part_vars <- setdiff(names(data_FACTOR), "id")

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

# 4) Optional corrplot
if (requireNamespace("corrplot", quietly = TRUE)) {
  corrplot::corrplot(
    cor_matrix_part,
    method = "color",
    type   = "upper",
    tl.cex = 0.7,
    tl.col = "black",
    title  = "Correlation matrix Online/Offline participation items (Italy)",
    mar    = c(0, 0, 2, 0)
  )
} else {
  cat("Package 'corrplot' not installed. Skipping correlation plot.\n")
}

Code
# 5) Multicollinearity check (cutoff 0.9)
if (requireNamespace("caret", quietly = TRUE)) {
  high_corr <- caret::findCorrelation(cor_matrix_part, cutoff = 0.9)
  if (length(high_corr) > 0) {
    cat("Variables with high correlation (> 0.9):\n")
    print(part_vars[high_corr])
  } else {
    cat("No variables show excessive multicollinearity.\n")
  }
} else {
  cat("Package 'caret' not installed. Skipping multicollinearity check.\n")
}
No variables show excessive multicollinearity.
Code
# 6) KMO e Bartlett 
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 
Code
psych::cortest.bartlett(
  cor_matrix_part,
  n = nrow(data_FACTOR)
)
$chisq
[1] 10451.93

$p.value
[1] 0

$df
[1] 325
Code
# 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 
Code
# 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
Code
# 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
Code
efa_result$TLI
[1] 0.917059
Code
efa_result$RMSEA
     RMSEA      lower      upper confidence 
0.04523795 0.04174861 0.04882587 0.90000000 
Code
# Optional: diagram
psych::fa.diagram(
  efa_result,
  main   = "Exploratory Factor Analysis – Political Participation",
  simple = FALSE
)

Code
# 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"
  )

Code
# 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)

The Italian diagnostics suggest that the items are well suited for factor analysis. The table of missing values shows that non-response is present but limited and reasonably balanced across items, with no variable dominated by NAs, and the row filter (>50% missing) has removed the most problematic cases. The correlation matrix displays a dense pattern of positive, medium-sized associations among most online and offline participation items, which is exactly what you expect if they share a set of common latent dimensions; at the same time, the correlations never become extremely high, and the multicollinearity check confirms that no pair exceeds the 0.9 threshold. The KMO output indicates adequate overall sampling adequacy and acceptable MSA values for individual items, while Bartlett’s test rejects the null of an identity matrix, meaning that the correlation structure is far from random. Taken together, these diagnostics support the decision to proceed with an exploratory factor analysis on the Italian online/offline participation items.

The Italian factor-analysis results show a clear and coherent structure, supported by diagnostics and by the factor loadings. The parallel analysis indicates that four factors should be retained, with a steep drop after the first component and simulated data crossing the empirical line around the fourth dimension. This already suggests that political participation in the Italian data is multidimensional, not reducible to a single online/offline divide. The loading matrix confirms this interpretation. A first factor groups the classic forms of low-threshold online engagement such as liking, sharing, commenting or posting; these items load together with profile/status changes and online petitions. A second factor gathers contact- and donation-oriented behaviours, both online and offline, suggesting a shared “resource-intensive” component. A third dimension captures collective or public-facing offline actions, such as offline volunteering, attending meetings, demonstrating or organising demonstrations. Finally, a fourth factor isolates information-seeking behaviours, distinguishing the more passive forms of attention to politics from active mobilisation. The loading plot visualises these patterns well: online expressive actions cluster tightly in one corner, collective offline modes are separate, and donation/contact behaviours stand apart from both. The factors are not redundant: cross-loadings remain generally low, indicating that each dimension taps a distinct component of political engagement. The Italian data suggest a four-pillar model of political participation: expressive online actions, resource-based engagement, collective offline mobilisation, and information-driven involvement. The structure is internally consistent and aligns with theoretical expectations about contemporary hybrid forms of participation.

*Although both countries rely on the same set of online and offline participation items, the factor structures show notable differences in dimensionality and coherence. In the Italian case, the parallel analysis and loading patterns converge on a more compact structure, with four clearly interpretable dimensions: expressive online engagement, collective offline action, resource-based behaviours, and information-seeking activities. The factors are well-defined, cross-loadings are limited, and items cluster tightly, indicating that Italian respondents’ participation behaviours form broader and more cohesive domains. By contrast, the Spanish factor structure is more articulated and internally differentiated. Even though the final decision retains five factors, the parallel analysis signals a more complex latent space. The five-factor solution reflects this fragmentation:
– a factor centred on online political communication with an offline spillover,
– a hybrid partisan-mobilization dimension combining online and offline volunteering and contacting,
– a non-partisan social engagement factor based on NGO donations,
– a factor capturing traditional unconventional offline action (strike, demonstration), and
– an offline information and discussion dimension.

This richer and more segmented configuration suggests that in Spain, political participation behaviours are more specialised, with finer-grained distinctions between modes of engagement. Italy shows fewer, broader, and more cohesive participation dimensions. Spain displays a more fragmented, hybrid, and differentiated structure, where several items separate into specialised subdomains.

10 New PCA with factors as supplementary numerical variables

Code
# 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"  
Code
# 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
)

# 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 |
Code
# 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
Code
# 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
Code
# 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
)

The PCA confirms the underlying structure already observed in the participation and platform analyses: Dim1 (≈ 39%) remains a broad intensity / mainstream use axis, dominated by WhatsApp, Facebook and Instagram, while Dim2 (≈15%) continues to reflect the contrast between entertainment-oriented platforms (TikTok, YouTube) and informational/professional platforms (Twitter/X, LinkedIn, Telegram).

What is new in this model is the projection of the five participation factors—treated as supplementary numerical variables. Their loadings show a coherent alignment with the two PCA axes.

1. Online expressive participation aligns with the visual/entertainment pole: The factor capturing online posting, liking, commenting and profile-based actions is positioned near TikTok and YouTube, indicating that expressive online participation maps onto the audiovisual side of the platform ecosystem. This suggests that individuals who engage in expressive online political acts tend to use visually oriented platforms more intensively.

2. Civic engagement / NGO-related participation sits closer to the informational platforms: The factor representing donations and volunteering for NGOs leans toward LinkedIn and Telegram, aligning with the informational/professional side of Dim2. This indicates that non-partisan civic engagement is more closely associated with structured, informational forms of digital use rather than with high-intensity mainstream platforms.

3. Protest and offline mobilisation align with lower-intensity and non-mainstream use: The factor capturing offline protest (e.g., strikes, demonstrations) is placed closer to the low-intensity region of Dim1, and only modestly associated with any specific platform. This shows that offline mobilisation is weakly linked to digital platform ecosystems, reinforcing the idea that traditional collective action remains partly decoupled from everyday online behaviour.

4. Partisan mobilisation sits between informational and mainstream platform use: The hybrid partisan-mobilisation factor (contacting officials, volunteering for parties) projects nearer to Twitter/X and Telegram, signalling a profile marked by information-driven and politically oriented platform use, but still connected to broader digital engagement.

5. Offline information and discussion aligns with moderate, central digital use: This factor sits near the centre of the map, indicating that face-to-face discussion and reading political materials do not strongly differentiate platform use, and that they characterise individuals with balanced, non-extreme digital behaviours.

The Italian PCA shows that the five participation factors align smoothly with the existing digital-use structure, without reshaping it. Participation modes distribute along the two core axes: (a) Dim1: intensity of digital engagement (WhatsApp–Facebook–Instagram); (b) Dim2: information-oriented vs. entertainment-oriented platform use. Online expressive acts gravitate toward the entertainment pole; partisan mobilisation and civic engagement toward the informational pole; traditional offline protest remains relatively detached. The result is a coherent and interpretable mapping, confirming that in Italy, digital participation styles integrate into platform use in an orderly and predictable way.

The Italian and Spanish results point to two configurations that share a common foundation but diverge in their internal organisation. In both countries, the PCA confirms that patterns of social-media use are structured along two familiar axes: a first component capturing the overall intensity of digital engagement—dominated by WhatsApp, Facebook and Instagram—and a second one separating entertainment-oriented platforms such as YouTube and TikTok from informational or professional ones like Twitter/X, LinkedIn and Telegram. This broad geometry is remarkably stable across the two contexts, suggesting that citizens in Italy and Spain navigate the digital ecosystem through similar repertoires of everyday platform use. What changes, however, is how political participation relates to this digital structure. In Italy, the exploratory factor analysis yields a compact and coherent latent space. Participation behaviours cluster into a few broad dimensions—expressive online actions, collective offline mobilisation, resource-based involvement, and information-oriented engagement. These clusters are internally cohesive and exhibit limited cross-loading, resulting in a relatively integrated picture of how Italians engage politically. When these factors are projected back onto the PCA, only the information-seeking factor aligns clearly with the first digital-use component. This indicates that frequent social-media users tend to be more exposed to political information online, but their intensity of digital engagement does not strongly shape their propensity to mobilise, volunteer, donate, or participate in protest activities. The Spanish case is more articulated. Although the final EFA solution retains five factors, the parallel analysis reveals a more complex underlying structure. The factors themselves are more differentiated and specialised: online political communication forms a distinct dimension with spillover into offline discussion, partisan mobilisation blends online and offline channels, civic engagement emerges as a separate cluster, and traditional protest retains its own space. Compared to Italy, these dimensions are narrower and more specific, which creates a more fragmented but also more finely resolved map of political behaviour. When the Spanish factors are aligned with the PCA, the pattern resembles the Italian one, in that the link between general digital use and political action remains modest; yet some dimensions—notably partisan mobilisation—show a slightly stronger affinity with the informational pole of the digital landscape. This suggests that in Spain, certain types of engagement are more embedded within politically oriented information flows. Analyses depict different modes of integration between digital repertoires and participation behaviours. Italy displays a more cohesive and aggregated structure, where forms of participation cluster into a few broad families and relate only weakly to patterns of platform use. Spain, by contrast, reveals a more differentiated and hybridised landscape, where political engagement is broken into smaller components and shows a somewhat closer alignment with specific aspects of digital information use. The comparison ultimately highlights that while the structure of digital media use is broadly similar across the two countries, the organisation of political participation—and its degree of connection to the digital sphere—varies in systematic and theoretically meaningful ways.

10.1 Canonical Correlation Analysis

Code
# 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.")

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)
)

Code
# 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
Code
dim(Y_efa)
[1] 995   5
Code
# 11.3.1 CCA execution
cca_result <- CCA::cc(X_pca, Y_efa)

# CCA
cca_result$cor
[1] 0.39421385 0.13937680 0.05488145
Code
# 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
Code
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
Code
# 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
Code
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
Code
# 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'

Code
# 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()

The canonical correlation analysis shows that, in the Italian case, social media use and political participation occupy related but only partially overlapping domains. The first canonical function (0.33) captures a modest but meaningful link between the general intensity of social-media use and the factor measuring online political information-seeking. This indicates that individuals who use multiple platforms more frequently tend to be more exposed to political content online. Beyond this informational dimension, however, the overlap vanishes: the relationships with protest, civic engagement and partisan mobilisation are negligible, suggesting that everyday digital activity does not translate into broader political action.

The Spanish pattern reinforces this interpretation by contrast. Here, canonical correlations are extremely weak from the outset (≈0.07, 0.04, 0.03), implying that digital use and political participation are almost entirely disconnected. Even frequent users do not exhibit systematically higher engagement—neither informational nor participatory. This is noteworthy because the Spanish participation structure is more fragmented and internally differentiated, yet this finer granularity does not produce stronger alignment with digital repertoires. The two behavioural spheres remain parallel but effectively independent.

Taken together, the comparison highlights a subtle but important divergence: Italy shows a slightly more integrated ecology, where the informational dimension of online participation reflects—albeit weakly—the broader patterns of platform use. In Spain, political action appears shaped by dynamics that operate independently of everyday digital behaviour. The informational function of social media plays a more visible role in structuring engagement in Italy, while in Spain the link between digital exposure and participation remains almost entirely absent.

10.2 Hierarchical clustering on PCA results

Code
# 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 ...
Code
# 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
Code
print(hcpc_res$desc.var$quali)
NULL
Code
# Cluster map on PCA
plot(hcpc_res, choice = "map")

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

Code
# 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 =====
Code
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>, …

The hierarchical clustering applied to the Italian PCA results identifies three clearly structured groups of social-media users, each reflecting a coherent digital repertoire. (a) The first cluster gathers low-intensity users, positioned on the negative side of the first PCA dimension, who engage minimally with almost all platforms—especially Instagram, TikTok and Twitter/X. This is the most digitally marginal segment, characterised by sparse and selective use; (b) The second cluster represents a hybrid profile centred on entertainment and interpersonal communication. These users show moderate engagement with YouTube, Facebook, WhatsApp and TikTok, while remaining much less active on informational or professional platforms such as Twitter/X, LinkedIn and Telegram. Their digital behaviour is generalist but not intensive, oriented mainly toward leisure and everyday social interactions; (c) The third cluster consists of high-intensity, multi-platform users. They score clearly above average across all platforms, and particularly on Twitter/X, LinkedIn and Telegram, suggesting a repertoire that combines entertainment, social interaction and strong informational exposure. This is the most digitally active and information-rich group, the one most embedded in cross-platform flows and likely to encounter political content more frequently. The Italian clustering reveals a digital environment organised along a relatively linear structure: from minimal to heavy use, and from entertainment-oriented to information-oriented behaviour. The three clusters are broad, internally coherent and easy to interpret, indicating that Italian users tend to group into stable, well-defined behavioural blocks.

Compared with Spain, this structure appears more compact. The Spanish clustering produces four groups with more specialised and fragmented profiles, including a highly informational cluster, a strong WhatsApp/Facebook cluster, and a heterogeneous mixed cluster that has no direct counterpart in Italy. In other words, while Italy displays a simpler and more integrated segmentation of digital repertoires, Spain shows a more diverse and finely differentiated ecosystem. This echoes the broader pattern observed across PCA, EFA and CCA: Italian digital and participatory behaviours tend to cluster into larger, more coherent families, whereas Spanish patterns are more dispersed and internally varied, suggesting a digital landscape where distinct niches emerge more sharply.

10.3 Anova per each variable

Code
# Numeric summary by cluster 
num_summary <- data_clustered %>%
  dplyr::group_by(clust) %>%
  dplyr::summarise(
    dplyr::across(
      dplyr::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>, …
Code
# 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) ---
Code
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 

The ANOVA results show that platform-specific behavioural differences are the strongest source of variation across the PCA-derived clusters. Twitter, Facebook, LinkedIn, TikTok, WhatsApp and Instagram all display highly significant cross-cluster heterogeneity, confirming that clusters primarily reflect distinct digital repertoires. These differences correspond closely to the HCPC internal descriptions: a highly active, multi-platform cluster; a mainstream social-media cluster centred on WhatsApp and Instagram; a low-use cluster; and a younger, TikTok-oriented group. Political and informational variables also contribute to differentiation, though more moderately. Online political information-seeking, social and political causes, and civic engagement show significant but smaller effects, suggesting that political orientations and behaviours partially—but not fully—align with these digital lifestyles. In contrast, protest participation does not discriminate the clusters, indicating that contentious engagement is independent from digital usage patterns. Digital practices are the main dividing line, with political disposition playing a secondary, more diffuse role. This produces a landscape where informational engagement overlaps with some clusters, while ideological and participatory differences remain only partially structured by digital repertoires.

The Spanish case displays a fundamentally different configuration. There too, digital behaviours contribute to cluster separation, but they do not dominate the structure to the same extent. Spanish clusters contain clearer and sharper differences in political interest, exposure to disagreement, checking/confirmation habits, and ideological orientation. Several categorical variables—including left–right self-placement, interest in politics, and fact-checking frequency—show highly significant discriminating power. This indicates that in Spain, clusters encode politicised behavioural ecologies, where digital use combines with political predispositions to define more coherent groups. Political identity and informational orientations are more tightly integrated into the clustering structure.

Comparing the two contexts, Italy shows a more behaviourally modular system: online platform repertoires drive the clustering, and political engagement overlays these repertoires only selectively. Spain, instead, exhibits a more politically saturated clustering structure, where political interest, ideology, and information-verification practices play a central role in defining group boundaries. In other words, Italian clusters are primarily digital-repertoire clusters with partial political colouring, whereas Spanish clusters are political-information clusters in which digital practices are embedded. This contrast underscores how differently digital and political behaviours interlock across the two national contexts: loosely and behaviourally in Italy, tightly and cognitively in Spain.

10.4 Summarize of categorical variables per cluster

Code
# 12.6 Categorical variables by cluster (tabella + chi-quadrato) -------

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

===== Categorical Variables by Cluster =====
Code
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
Code
# 12.7 Visualizations: boxplot per le 3 variabili più significative ----

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)
}

Code
# 12.8 Visualizations: stacked bar plots per le variabili categoriche ---

for (v in cat_vars) {
  p <- ggplot(data_clustered, aes(x = clust, fill = .data[[v]])) +
    geom_bar(position = "fill") +
    scale_y_continuous(labels = scales::percent) +
    labs(
      title = paste(v, "distribution across clusters"),
      x = "Cluster", y = "Percentage"
    ) +
    theme_minimal() +
    scale_fill_brewer(palette = "Set2")
  
  print(p)
}

Code
# 12.9 HCPC Internal Descriptions --------------------------------------

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

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

--- Quantitative Variables ---
Code
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
Code
cat("\n--- Qualitative Variables ---\n")

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

The Italian HCPC yields four clusters that are clearly differentiated along two main axes: general platform intensity (Facebook/Instagram/TikTok/Twitter/LinkedIn/YouTube/WhatsApp) and political engagement (info-seeking, civic support, political support). The ANOVA confirms that almost all digital-use variables significantly discriminate clusters, with Protest_Action as the only marginal case—unsurprising given its low prevalence and weak correlation with digital repertoires:

(a) Cluster 1 aggregates low-intensity users, with uniformly low means across platforms and systematically lower scores on political interest, cross-cutting information behaviours (disagree/check/confirm), and all participation variables. This is the “minimal digital engagement” segment.
(b) Cluster 2 represents moderate users who show relatively higher engagement in informational and civic dimensions, but without strong involvement in expressive or political actions. Here, the pattern suggests a functional rather than activist use of digital media.
(c) Cluster 3 shifts further toward activism: moderate-to-high use of Facebook, Instagram and WhatsApp, accompanied by substantially higher values for political and civic support. This group reflects a hybrid profile: socially embedded platforms combined with selective political uses.
(d) Cluster 4 clearly stands out as the high-intensity digital cluster, with dominant means for every major platform and peak values for political information, social support and political support. The categorical variables reinforce this profile: younger age groups, stronger political interest, and higher frequency of cross-cutting information behaviours cluster here. The structure mirrors an “always-on” digital lifestyle that translates into broader political attentiveness.

What is notable is the alignment between social-media intensity, political interest, and political information behaviours, which increases monotonically across clusters. Italian clusters behave almost like gradations of the same underlying dimension: heavier digital engagement is systematically associated with higher political attentiveness, stronger informational openness (read disagreeing news, check alternative sources, seek confirmation), and broader forms of participation. This confirms the coherence of the Italian digital–political ecology emerging from the earlier PCA and CCA: the digital sphere and the political sphere are not identical but are partially integrated, especially through informational pathways.

When juxtaposed with the Spanish clustering results, the contrast becomes clearer. Both countries identify clusters that reflect gradations of digital intensity, but only in Italy do these clusters map onto political interest and political informational behaviours in a consistent, ordered fashion. In Spain, digital clusters discriminate platform use very sharply but show weaker and more uneven associations with political interest, cross-cutting exposure, and confirmatory/checking behaviours. Spanish clusters are more sociotechnical than political: they classify different platform ecologies, but these do not translate into systematic differences in political engagement. A second divergence concerns cohesion vs fragmentation: (a) Italy shows a compact, hierarchical structure: digital use, informational behaviours and participation scale together; (b) Spain exhibits a more fragmented pattern: clusters are internally differentiated by platform repertoires (e.g., WhatsApp vs. TikTok vs. Twitter users), but political variables vary less cleanly across clusters.

Finally, both countries show that political participation is never primarily driven by platform use alone, but Italy reveals a clearer informational channel linking general social-media intensity to political interest and participation. In Spain, this channel is much weaker: political action appears to be driven by factors more independent of digital habits.

11 Anova Analysis

11.1 Anova platform use (DV) per sociopolitical variables

Code
# 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::filter(!is.na(Left_Right)) %>%
  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
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
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
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
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
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
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
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
Code
# 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"
  )

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
Code
# 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
Code
# Grafico: avg 
ggplot(desc_stats %>% dplyr::filter(!is.na(Left_Right)),
       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)
  )

Code
# 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::filter(!is.na(Vote)) %>%
  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"
  ) %>%
  dplyr::mutate(
    Vote = forcats::fct_relevel(Vote, "Other party", "Did not vote", after = Inf)
  ) %>%
  dplyr::arrange(Platform, Vote)

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 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 Partito Democratico 284 4.72 1.92 0.11
Facebook Other party 77 4.38 2.16 0.25
Facebook Did not vote 173 4.37 1.94 0.15
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 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 Partito Democratico 284 3.79 2.27 0.13
Instagram Other party 77 3.76 2.19 0.25
Instagram Did not vote 173 3.87 2.15 0.16
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 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 Partito Democratico 284 2.25 1.67 0.10
Linkedin Other party 77 2.61 1.84 0.21
Linkedin Did not vote 173 2.31 1.71 0.13
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 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 Partito Democratico 284 2.57 1.95 0.12
Telegram Other party 77 3.42 1.93 0.22
Telegram Did not vote 173 2.98 2.06 0.16
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 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 Partito Democratico 284 2.05 1.88 0.11
TikTok Other party 77 3.01 2.17 0.25
TikTok Did not vote 173 2.58 2.05 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 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 Partito Democratico 284 2.12 1.82 0.11
Twitter_X Other party 77 2.93 2.23 0.25
Twitter_X Did not vote 173 2.37 1.89 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 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 Partito Democratico 284 5.86 1.19 0.07
WhatsApp Other party 77 5.71 1.36 0.16
WhatsApp Did not vote 173 5.60 1.51 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 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 Partito Democratico 284 3.75 1.69 0.10
YouTube Other party 77 4.25 1.77 0.20
YouTube Did not vote 173 4.17 1.72 0.13
Code
# 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
Code
# 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
Code
# Reordering categories
desc_stats_vote <- desc_stats_vote %>% 
  dplyr::mutate(
    Vote = forcats::fct_relevel(Vote, "Other party", "Did not vote", after = Inf)
  )

# Grapth per party voted
ggplot(desc_stats_vote %>% dplyr::filter(!is.na(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 = 0.5, vjust = 1)
  )

Code
# 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
Code
# 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
Code
# 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
Code
# 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)
  )

In the Italian case, the descriptive patterns show that social-media use is only weakly connected to political identities. Across the left–right spectrum, platform frequencies remain remarkably stable: Facebook, Instagram, WhatsApp, and YouTube display almost flat distributions, while even the more politically connoted platforms—Twitter/X, Telegram, TikTok—show only minimal ideological fluctuations. Partisan differences are similarly limited. Voters of the main parties (Fratelli d’Italia, PD, Lega, M5S, Forza Italia) exhibit nearly indistinguishable levels of engagement across all platforms, and even the smaller parties do not produce meaningful deviations. The only domain where a clear structure emerges is age: younger Italians consistently appear as the most intensive users of Instagram, TikTok, Telegram, and YouTube, while older cohorts dominate Facebook usage. These age-related gradients are strong, linear, and far more pronounced than any political differentiation. Overall, the Italian digital ecosystem appears socially and politically homogeneous, with demographic life-cycle effects far outweighing ideological or partisan ones.

When compared to Spain, this homogeneity becomes even more evident. The Spanish data similarly confirm the primacy of age as a driver of platform use, but Spain shows slightly more structured political nuances. Ideological groups in Spain display small but coherent gradients—left-leaning users are somewhat more active on Instagram and Twitter, whereas right-leaning groups lean modestly toward LinkedIn or WhatsApp. Partisan differences are also more discernible: parties such as Vox, PSOE, Sumar or Junts exhibit mild but consistent digital signatures across platforms. None of these patterns are large, yet they indicate a modest alignment between political identities and digital repertoires.

In contrast, Italy stands out for its almost total absence of political imprint on platform use. The digital environment does not reflect ideological cleavages or party competition; instead, it maps onto demographic contours, especially age. Spain shares the same demographic logic, but it retains small political inflections that suggest a more articulated interplay between digital behaviours and political identities. The comparison points to two parallel conclusions: in both countries, digital repertoires are primarily demographic phenomena, driven by generational preferences and platform affordances; but Spain preserves mild political structuring, whereas Italy’s patterns are almost entirely depoliticised, with social-media use functioning as a largely non-political, lifestyle-driven activity.

12 OLS regression model (Platform use as DV)

Code
# 14. OLS

library(broom)
library(car)
library(purrr)
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
Code
# 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
Code
# 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:"
  )

The Italian OLS models show that platform use is associated only weakly and selectively with socio-political traits, and that the structure of the predictors is far from homogeneous across platforms. Two variables stand out consistently: age and political interest.

Age displays the strongest and most systematic coefficients. Its effect is always negative for visually oriented or fast-paced platforms (Instagram, TikTok, YouTube, Telegram), indicating that younger respondents adopt these environments more intensively. Conversely, platforms such as Facebook and WhatsApp show weaker and sometimes negligible age gradients, consistent with their more mature user base.

Political interest emerges as a second robust predictor: more interested individuals tend to use a broader set of platforms more frequently. This is especially visible for platforms that support information-rich content (Twitter/X, YouTube, LinkedIn). However, even here the effect size remains modest, confirming that engagement in Italian digital spaces is only partially anchored to political motivation.

Other socio-political variables show fragmented and platform-specific patterns:
– Left–right orientation has no substantial effect except for marginal tendencies (e.g., slightly higher Twitter/X use among left-leaning individuals).
– Information-seeking behaviours (disagreement exposure, cross-checking, confirmation) produce small but coherent positive associations with Twitter/X and YouTube, reflecting their role as news-intensive platforms.
– Sex rarely matters, and when it does, coefficients are small.
– Party preference shows no meaningful systematic effect: differences across voters are minimal and unstable once covariates are included.

the OLS results reinforce the idea already seen in PCA and clustering: Italian social-media behaviour is primarily structured by age and individual media engagement, while political orientation, partisan alignment and mobilisation styles play a marginal role. Platforms do not map onto the partisan field; instead, they align with demographic and informational repertoires.

The Italian OLS models reveal a relatively structured set of predictors shaping platform-specific usage. Age is consistently the strongest and most stable negative predictor across all platforms, confirming a clear generational gradient. Political interest is also a robust and positive correlate, indicating that in Italy higher engagement with politics translates into higher intensity of social media use—especially on LinkedIn, Twitter/X, and Instagram. The ideological left–right axis shows only weak and platform-specific associations, with minor left-leaning overuse on Instagram and Twitter/X, while gender effects remain limited and inconsistent. Overall, Italian platform use is driven primarily by sociodemographic fundamentals (age, education) and general political engagement rather than by partisan or ideological alignment. In Spain, the pattern is more diffuse and substantially weaker. Age remains a strong negative predictor—but beyond this universal baseline, few variables show systematic and significant associations. Political interest is less consistently related to social media use, and the ideological dimension is almost entirely irrelevant across platforms. Partisan vote and left–right self-placement produce scattered effects that rarely cross significance thresholds. The Spanish models are therefore flatter and more fragmented, with platform use displaying fewer political or demographic structuring forces. The results point to a clearer and more hierarchical structure of predictors in Italy, where age and political interest jointly organize the digital space, and where some platforms show small but detectable ideological tilts. In Spain, by contrast, platform use appears more socially and politically “neutral,” with very limited differentiation across political groups and a much weaker imprint of political engagement. What emerges is a more politically stratified digital ecosystem in Italy, versus a more socially diffuse and weakly politicized one in Spain.