This report asks a simple question. When large European firms are linked because they share directors, does that network position work as organisational social capital, and does it show up in profitability?
The course brief allows either individual social capital (directors) or organisational social capital (firms). We study firms. A tie is a board interlock in 2022: two companies are linked when at least one person sits on both boards. We treat that tie as relational social capital, measure it with standard network statistics, and compare high- and low-capital firms on return on assets.
needed_pkgs <- c("igraph", "knitr")
missing_pkgs <- needed_pkgs[!vapply(needed_pkgs, requireNamespace, logical(1), quietly = TRUE)]
if (length(missing_pkgs) > 0) {
stop(paste("Install these packages before knitting:", paste(missing_pkgs, collapse = ", ")))
}
library(igraph)
library(knitr)| Name | Student ID |
|---|---|
| Mikołaj Stanisław Krzyżanek | 471762 |
| Artem Afonin | 486766 |
| Brianna-Alecsandra Manta | 488597 |
| Dongliang Zhang | 488390 |
Seven files were provided. Three enter the analysis. The others describe directors (shared university, shared graduation year, shared previous employment, and director attributes). They fit an individual-level design, which we do not pursue here.
| File | Role in this report |
|---|---|
1. companies interlocks one-mode network 2022.csv |
Binary company-by-company interlock matrix |
5. companies_covariates.csv |
Sector, country, profitability, employment, assets |
7. director_company_network_2022.csv |
Director-by-company seats; used to check what an interlock is |
2, 3, 4, 6 |
Director networks and attributes; not used |
The matrix files are semicolon-separated. The first column holds row names. The diagonal of the interlock matrix is a self-entry, so we set it to zero before any network statistic is computed. A firm is not tied to itself.
矩阵文件以分号分隔。第一列包含行名。互锁矩阵的对角线元素为自变量,因此在计算任何网络统计数据之前,我们将其设置为零。公司之间不存在关联。
data_dir <- "."
needed_files <- c(
"1. companies interlocks one-mode network 2022.csv",
"5. companies_covariates.csv",
"7. director_company_network_2022.csv"
)
missing_files <- needed_files[!file.exists(file.path(data_dir, needed_files))]
if (length(missing_files) > 0) {
stop(paste("Missing data files:", paste(missing_files, collapse = ", ")))
}
read_matrix <- function(file_name) {
dat <- read.csv(
file.path(data_dir, file_name),
sep = ";",
check.names = FALSE,
row.names = 1,
stringsAsFactors = FALSE
)
mat <- as.matrix(dat)
storage.mode(mat) <- "numeric"
mat
}
interlock_raw <- read_matrix("1. companies interlocks one-mode network 2022.csv")
if (!isSymmetric(interlock_raw)) {
stop("The interlock matrix is not symmetric.")
}
if (!identical(rownames(interlock_raw), colnames(interlock_raw))) {
stop("Row names and column names of the interlock matrix differ.")
}
interlock <- interlock_raw
diag(interlock) <- 0
firms <- read.csv(
file.path(data_dir, "5. companies_covariates.csv"),
sep = ";",
check.names = FALSE,
stringsAsFactors = FALSE
)
if (!identical(firms[["Company name (Orbis)"]], rownames(interlock))) {
firms <- firms[match(rownames(interlock), firms[["Company name (Orbis)"]]), ]
}
if (any(is.na(firms[["Company name (Orbis)"]]))) {
stop("Some firms in the interlock matrix have no covariates.")
}
seats <- read_matrix("7. director_company_network_2022.csv")
if (!identical(colnames(seats), colnames(interlock))) {
stop("Company columns in the director-company file do not match the interlock file.")
}
# One-mode projection: number of shared directors. The supplied interlock
# file keeps only the presence of a shared director.
shared_directors <- t(seats) %*% seats
diag(shared_directors) <- 0
projection_matches <- all((shared_directors > 0) == (interlock > 0))
if (!projection_matches) {
stop("The binary interlock file does not match the director-company projection.")
}
firm <- data.frame(
company = rownames(interlock),
sector = firms[["Stoxx Sector"]],
country = firms[["Country code (Orbis)"]],
roa = firms[["Returns_On_Assets_%_2022"]],
ros = firms[["Returns_on_Sales_%_2022"]],
ln_employees = firms[["ln_nr_of_employees_2022"]],
ln_assets = firms[["ln_total_assets_thousands_USD_2022"]],
board_size = as.numeric(colSums(seats)),
stringsAsFactors = FALSE
)g <- graph_from_adjacency_matrix(interlock, mode = "undirected", diag = FALSE)
if (any(which_loop(g))) {
stop("Self-loops remained in the graph.")
}
V(g)$sector <- firm$sector
V(g)$country <- firm$country
V(g)$roa <- firm$roa
V(g)$ros <- firm$ros
V(g)$ln_employees <- firm$ln_employees
V(g)$ln_assets <- firm$ln_assets
V(g)$board_size <- firm$board_size
# Access: how many other firms share a director.
# Brokerage: how often the firm sits on shortest paths between other firms.
# Closure: how often the firm's partners are also tied to each other.
V(g)$degree <- degree(g)
V(g)$betweenness <- betweenness(g, normalized = TRUE)
V(g)$clustering <- transitivity(g, type = "local")
V(g)$constraint <- constraint(g)
firm$degree <- V(g)$degree
firm$betweenness <- V(g)$betweenness
firm$clustering <- V(g)$clustering
firm$constraint <- V(g)$constraint
# High access starts at the upper quartile (degree 6). Low access is the
# lower quartile (degree 0 to 2). The middle band is everyone else.
firm$access_group <- ifelse(
firm$degree >= 6, "High (degree 6+)",
ifelse(firm$degree <= 2, "Low (degree 0-2)", "Medium (degree 3-5)")
)
firm$access_group <- factor(
firm$access_group,
levels = c("Low (degree 0-2)", "Medium (degree 3-5)", "High (degree 6+)")
)
upper <- upper.tri(shared_directors)
tie_weight <- shared_directors[upper][interlock[upper] == 1]
share_single_director <- mean(tie_weight == 1)
comp <- components(g)
giant_id <- which.max(comp$csize)
in_giant <- comp$membership == giant_idThe director-company file reproduces the binary interlock file exactly, so every tie in the analysis is a shared board seat. Most of those ties are thin.
init_summary <- data.frame(
Item = c(
"Firms",
"Directors listed in the seat file",
"Directors with at least one seat here",
"Directors who sit on two or more of these boards",
"Undirected interlocks",
"Interlocks carried by one director",
"Density",
"Components",
"Firms in the largest component",
"Isolates",
"Mean degree",
"Firms missing ROA"
),
Value = c(
vcount(g),
nrow(seats),
sum(rowSums(seats) >= 1),
sum(rowSums(seats) >= 2),
ecount(g),
sprintf("%.1f%%", 100 * share_single_director),
sprintf("%.3f", edge_density(g)),
comp$no,
max(comp$csize),
sum(degree(g) == 0),
sprintf("%.2f", mean(degree(g))),
sum(is.na(firm$roa))
),
stringsAsFactors = FALSE
)
kable(init_summary, caption = "Network after initialisation.")| Item | Value |
|---|---|
| Firms | 143 |
| Directors listed in the seat file | 499 |
| Directors with at least one seat here | 429 |
| Directors who sit on two or more of these boards | 249 |
| Undirected interlocks | 277 |
| Interlocks carried by one director | 90.6% |
| Density | 0.027 |
| Components | 11 |
| Firms in the largest component | 132 |
| Isolates | 9 |
| Mean degree | 3.87 |
| Firms missing ROA | 1 |
Sub-conclusion from the data build: the object of analysis is a sparse binary graph of 143 firms. An interlock almost always means one shared person, so these are thin bridges between organisations rather than thick, multi-director bonds.
If interlocks were mainly a strategic investment, size would not dominate the pattern. It does. Degree correlates with log employment at 0.44 and with log assets at 0.27. Board size correlates with degree at 0.82. A larger board offers more chances that one member also sits elsewhere. Part of what we call access is therefore a by-product of scale.
Sector differences are real but smaller than this size gradient. Consumer, food, automobile, and telecom firms sit a bit higher. Basic resources, energy, and real estate sit lower. Several sectors have very few firms, so those means are descriptive, not a ranking to over-interpret.
plot(
firm$ln_employees, firm$degree,
xlab = "Log number of employees, 2022",
ylab = "Degree",
main = "Larger employers have more board interlocks",
pch = 19, col = rgb(0.15, 0.35, 0.55, 0.75)
)
abline(lm(degree ~ ln_employees, data = firm), col = "#b2182b", lwd = 2)sector_mean <- sort(tapply(firm$degree, firm$sector, mean))
sector_n <- tapply(firm$degree, firm$sector, length)
sector_labels <- paste0(names(sector_mean), " (n=", sector_n[names(sector_mean)], ")")
old_par <- par(mar = c(4.2, 16, 3, 1))
barplot(
sector_mean,
horiz = TRUE,
names.arg = sector_labels,
las = 1,
cex.names = 0.72,
xlab = "Mean degree",
main = "Mean interlocks by sector",
col = "#4c78a8",
border = NA
)Sub-conclusion: the firms that look rich in relational social capital are, first, large firms with large boards. Sector colours the pattern. It does not replace size.
Homophily is the tendency of similar actors to tie to each other. Here the relevant similarity is the country of the firm, not its industry. National business systems still organise European corporate elites: careers, ownership, and board recruitment are more national than the product market is.
Two comparisons make the point. Country assortativity is high. Sector assortativity is close to zero. We also compare the share of ties that stay inside the same country, or the same sector, with the share we get by shuffling labels while keeping the graph fixed (1,000 permutations).
el <- as_edgelist(g, names = FALSE)
tie_share <- function(labels) {
mean(labels[el[, 1]] == labels[el[, 2]])
}
obs_country <- tie_share(V(g)$country)
obs_sector <- tie_share(V(g)$sector)
set.seed(2022)
perm_country <- replicate(1000, tie_share(sample(V(g)$country)))
perm_sector <- replicate(1000, tie_share(sample(V(g)$sector)))
assort_country <- assortativity_nominal(
g, as.integer(factor(V(g)$country)),
directed = FALSE
)
assort_sector <- assortativity_nominal(
g, as.integer(factor(V(g)$sector)),
directed = FALSE
)
homophily_tab <- data.frame(
Attribute = c("Country", "Sector"),
Assortativity = c(assort_country, assort_sector),
Observed_within_tie_share = c(obs_country, obs_sector),
Mean_share_under_label_shuffle = c(mean(perm_country), mean(perm_sector)),
Permutation_p = c(mean(perm_country >= obs_country), mean(perm_sector >= obs_sector)),
stringsAsFactors = FALSE
)
kable(
homophily_tab,
digits = 3,
caption = "Homophily. The permutation p-value is the share of label shuffles with a within-tie share at least as large as the observed share."
)| Attribute | Assortativity | Observed_within_tie_share | Mean_share_under_label_shuffle | Permutation_p |
|---|---|---|---|---|
| Country | 0.446 | 0.538 | 0.123 | 0.000 |
| Sector | 0.026 | 0.119 | 0.087 | 0.041 |
old_par <- par(mfrow = c(1, 2), mar = c(4.2, 4.2, 3, 1))
barplot(
rbind(
c(obs_country, obs_sector),
c(mean(perm_country), mean(perm_sector))
),
beside = TRUE,
names.arg = c("Country", "Sector"),
ylim = c(0, 0.7),
ylab = "Share of ties within the attribute",
main = "Ties stay in-country",
col = c("#4c78a8", "#d9d9d9"),
border = NA,
legend.text = c("Observed", "Label shuffle"),
args.legend = list(bty = "n", x = "topright")
)
country_mean <- sort(tapply(firm$degree, firm$country, mean))
barplot(
country_mean,
las = 2,
ylab = "Mean degree",
main = "France and Germany sit higher",
col = "#4c78a8",
border = NA
)About 54 percent of interlocks join two firms from the same country, against about 12 percent under a random labelling. The same comparison for sector is 12 percent observed against 9 percent expected. France (mean degree 6.0, n = 25) and Germany (4.6, n = 22) are the dense national cores. Britain has the most firms in the sample (n = 29) but a lower mean degree (3.1).
The picture of the largest component shows the same fact. Node colour is country, for the five countries with the most firms. Node area grows with degree. Same-coloured nodes cluster, and the largest nodes are not spread evenly across colours.
g_giant <- induced_subgraph(g, vids = which(in_giant))
core_countries <- c("FR", "DE", "GB", "CH", "NL")
giant_country <- ifelse(V(g_giant)$country %in% core_countries, V(g_giant)$country, "Other")
country_colours <- c(
FR = "#2166ac",
DE = "#b2182b",
GB = "#ef8a62",
CH = "#762a83",
NL = "#1b7837",
Other = "#bdbdbd"
)
set.seed(2022)
layout_giant <- layout_with_fr(g_giant, niter = 500)
plot(
g_giant,
layout = layout_giant,
vertex.size = 3 + 11 * degree(g_giant) / max(degree(g)),
vertex.color = country_colours[giant_country],
vertex.frame.color = NA,
vertex.label = NA,
edge.color = rgb(0.35, 0.35, 0.35, 0.35),
edge.width = 0.6,
main = "Largest component: colour is country, size is degree"
)
legend(
"topright",
legend = names(country_colours),
col = country_colours,
pch = 19,
pt.cex = 1.4,
bty = "n",
cex = 0.85
)Sub-conclusion: relational social capital in this sample is a national elite resource that crosses industry. French and German firms are the clearest high-capital groups. A shared sector does little to create a tie.
Organisational social capital, in this study, is the board-interlock position of a firm. Access is the number of other firms reached through shared directors. Brokerage is the extent to which the firm lies between others. Both are standard network readings of the same idea: relationships are a resource because they carry information, reputation, and a way to coordinate (Lin; Burt; Useem).
The measures support that idea as a description of the elite, and they do not support it as a profit formula for 2022.
The advantage of this social capital is therefore membership in a national corporate elite: more contacts, and a better chance of sitting between contacts. That is the advantage Burt and Useem describe. It is a different claim from “central firms earn a higher return on assets”, and the 2022 numbers do not support that second claim. Interlocks may stabilise access and status even when they do not raise the accounting return. They may also be costly, ceremonial, or a consequence of size rather than a cause of profit.
The limits of the evidence are straightforward. The design is one cross-section, so it cannot separate cause from effect. Profitability is a single year, and 2022 was a particular macroeconomic year. Ties are binary even though a few firm pairs share more than one director. Countries other than France, Germany, Britain, Switzerland, and the Netherlands have few firms. One firm is missing ROA. A later design could follow the same firms over time, or turn to the director files and ask the individual-level questions the brief also allows: brokerage versus closure among people, strong versus weak ties, and gender homophily.
## R version 4.5.2 (2025-10-31)
## Platform: x86_64-apple-darwin20
## Running under: macOS Sequoia 15.8.1
##
## Matrix products: default
## BLAS: /Library/Frameworks/R.framework/Versions/4.5-x86_64/Resources/lib/libRblas.0.dylib
## LAPACK: /Library/Frameworks/R.framework/Versions/4.5-x86_64/Resources/lib/libRlapack.dylib; LAPACK version 3.12.1
##
## locale:
## [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
##
## time zone: Europe/Warsaw
## tzcode source: internal
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] knitr_1.51 igraph_2.2.1
##
## loaded via a namespace (and not attached):
## [1] digest_0.6.39 R6_2.6.1 codetools_0.2-20 fastmap_1.2.0
## [5] xfun_0.56 magrittr_2.0.4 cachem_1.1.0 pkgconfig_2.0.3
## [9] htmltools_0.5.9 rmarkdown_2.30 lifecycle_1.0.5 cli_3.6.6
## [13] sass_0.4.10 jquerylib_0.1.4 compiler_4.5.2 rstudioapi_0.18.0
## [17] tools_4.5.2 evaluate_1.0.5 bslib_0.9.0 yaml_2.3.12
## [21] otel_0.2.0 jsonlite_2.0.0 rlang_1.2.0
3.2 Social capital is scarce and skewed
A firm of average position has about four interlocked partners. The upper tail stretches to 13. Nine firms have none. Betweenness is even more concentrated: many firms lie on almost no shortest path, and a few lie on a large share of them.
That shape is what a social-capital distribution should look like if the resource is an elite resource. Most organisations hold a little. A small inner set holds a lot. Isolates are the low-capital group in the strict sense: they have no access and no brokerage inside this set of firms.
The largest component contains 132 of the 143 firms. The remaining firms are nine isolates plus one small component. Mean distance inside the reachable pairs is 3.86 and the diameter is 9. The elite is not a complete clique. It is one loosely linked world with a centre.
Sub-conclusion: high social capital is a minority condition. Low social capital, including complete isolation from other firms in this sample, is common.