##k-means clustering----
#using all data
clustering_data_all <- scaled_full_data %>%
  select(-c(Country, Season, season_start, European_performance, lead_european_performance))
#considering optimal clusters
n <- 10
wss <- numeric(n)
set.seed(123)
for (i in 1:n) {
  km.out <- kmeans(clustering_data_all, centers = i, nstart = 20)
  wss[i] <- km.out$tot.withinss
}
wss_df <- tibble(clusters = 1:n, wss = wss)
ggplot(wss_df, aes(x = clusters, y = wss, group = 1)) +
  geom_point(size = 4)+
  geom_line() +
  scale_x_continuous(breaks = c(2, 4, 6, 8, 10)) +
  xlab('Number of clusters')
#perform clustering
set.seed(123)
kmeans_model_all <- kmeans(clustering_data_all, centers = 3, nstart = 50)
#joining to data and considering characteristics of clusters
clustered_data_all <- pivoted_scaled_full_data_comp_breakdown %>%
  mutate(cluster = as.factor(kmeans_model_all$cluster))
cluster_characteristics_all <- clustered_data_all %>%
  group_by(cluster) %>%
  summarise(across(where(is.numeric), mean, na.rm = TRUE)) %>%
  select(-season_start)


#using principal components
clustering_data_pc <- pca_results %>%
  select(contains("PC"))
#considering optimal clusters
n <- 10
wss <- numeric(n)
set.seed(123)
for (i in 1:n) {
  km.out <- kmeans(clustering_data_pc, centers = i, nstart = 20)
  wss[i] <- km.out$tot.withinss
}
wss_df <- tibble(clusters = 1:n, wss = wss)
ggplot(wss_df, aes(x = clusters, y = wss, group = 1)) +
  geom_point(size = 4)+
  geom_line() +
  scale_x_continuous(breaks = c(2, 4, 6, 8, 10)) +
  xlab('Number of clusters')
#perform clustering
set.seed(123)
kmeans_model_pc <- kmeans(clustering_data_pc, centers = 3, nstart = 50)
#joining to data and considering characteristics of clusters
clustered_data_pc <- pivoted_scaled_full_data_comp_breakdown %>%
  mutate(cluster = as.factor(kmeans_model_pc$cluster))
cluster_characteristics_pc <- clustered_data_pc %>%
  group_by(cluster) %>%
  summarise(across(where(is.numeric), mean, na.rm = TRUE)) %>%
  select(-season_start)


#using competitiveness indices
clustering_data_comp_index <- scaled_full_data_competitiveness_index %>%
  select(contains("index")) %>%
  select(1:3)
#considering optimal clusters
n <- 10
wss <- numeric(n)
set.seed(123)
for (i in 1:n) {
  km.out <- kmeans(clustering_data_comp_index, centers = i, nstart = 20)
  wss[i] <- km.out$tot.withinss
}
wss_df <- tibble(clusters = 1:n, wss = wss)
ggplot(wss_df, aes(x = clusters, y = wss, group = 1)) +
  geom_point(size = 4)+
  geom_line() +
  scale_x_continuous(breaks = c(2, 4, 6, 8, 10)) +
  xlab('Number of clusters')
#perform clustering
set.seed(123)
kmeans_model_comp_index <- kmeans(clustering_data_comp_index, centers = 3, nstart = 50)
#joining to data and considering characteristics of clusters
clustered_data_comp_index <- pivoted_scaled_full_data_comp_breakdown_competitiveness_index %>%
  mutate(cluster = as.factor(kmeans_model_comp_index$cluster))
cluster_characteristics_comp_index <- clustered_data_comp_index %>%
  group_by(cluster) %>%
  summarise(across(where(is.numeric), mean, na.rm = TRUE)) %>%
  select(-season_start)
plotting_cluster_data <- cluster_characteristics_comp_index %>% select(-11:-19)


##Evaluating clusters----
compare_clusters <- function(data, km_model, name) {
  dist_matrix <- dist(data)
  sil <- silhouette(km_model$cluster, dist_matrix)
  stats <- cluster.stats(dist_matrix, km_model$cluster)
  
  tibble(
    model = name,
    avg_silhouette = mean(sil[, 3]),
    dunn_index = stats$dunn,
    within_ss = km_model$tot.withinss,
    between_ss = km_model$betweenss,
    total_ss = km_model$totss,
    variance_explained = km_model$betweenss / km_model$totss
  )
}

comparison <- bind_rows(
  compare_clusters(clustering_data_all, kmeans_model_all, "All variables"),
  compare_clusters(clustering_data_pc, kmeans_model_pc, "Principal components"),
  compare_clusters(clustering_data_comp_index, kmeans_model_comp_index, "Theory-based indices")
) %>%
  arrange(desc(avg_silhouette), desc(dunn_index), desc(variance_explained))


##evaluating 'best' (indices) model
#full European performance
anova_model <- aov(European_performance ~ cluster, data = clustered_data_comp_index)
summary(anova_model)

kruskal.test(European_performance ~ cluster, data = clustered_data_comp_index)

panel_clusters <- plm(
  European_performance ~ cluster,
  data = clustered_data_comp_index,
  index = c("Country","season_start"),
  effect = "twoways",
  model = "within"
)
summary(panel_clusters)
coeftest(panel_clusters, vcov = vcovHC, type = "HC1")

#lead European performance
anova_model <- aov(lead_european_performance ~ cluster, data = clustered_data_comp_index)
summary(anova_model)

kruskal.test(lead_european_performance ~ cluster, data = clustered_data_comp_index)

panel_clusters_lead <- plm(
  lead_european_performance ~ cluster,
  data = clustered_data_comp_index,
  index = c("Country","season_start"),
  effect = "twoways",
  model = "within"
)
summary(panel_clusters_lead)
coeftest(panel_clusters_lead, vcov = vcovHC, type = "HC1")

#CL performance
anova_model <- aov(European_performance_CL ~ cluster, data = clustered_data_comp_index)
summary(anova_model)

kruskal.test(European_performance_CL ~ cluster, data = clustered_data_comp_index)

panel_clusters_CL <- plm(
  European_performance_CL ~ cluster,
  data = clustered_data_comp_index,
  index = c("Country","season_start"),
  effect = "twoways",
  model = "within"
)
summary(panel_clusters_CL)
coeftest(panel_clusters_CL, vcov = vcovHC, type = "HC1")

#EL performance
anova_model <- aov(European_performance_EL ~ cluster, data = clustered_data_comp_index)
summary(anova_model)

kruskal.test(European_performance_EL ~ cluster, data = clustered_data_comp_index)

panel_clusters_EL <- plm(
  European_performance_EL ~ cluster,
  data = clustered_data_comp_index,
  index = c("Country","season_start"),
  effect = "twoways",
  model = "within"
)
summary(panel_clusters_EL)
coeftest(panel_clusters_EL, vcov = vcovHC, type = "HC1")


##finding seasons closest to cluster centre
closest_n_per_cluster <- clustered_data_comp_index %>%
  group_by(cluster) %>%
  group_modify(~ {
    cluster_id <- as.character(.y$cluster)
    center_coords <- kmeans_model_comp_index$centers[cluster_id, , drop = FALSE]
    
    matrix_data <- .x %>% select(contains("index")) %>% as.matrix()
    
    center_matrix <- matrix(center_coords, nrow = nrow(matrix_data), ncol = ncol(matrix_data), byrow = TRUE)
    
    .x %>% mutate(
      Distance = sqrt(rowSums((matrix_data - center_matrix)^2))
    )
  }) %>%
  ungroup() %>%
  group_by(cluster) %>%
  slice_min(order_by = Distance, n = 10, with_ties = FALSE) %>%
  relocate(c(cluster, Season, Country, European_performance))
