1 - Setup

Reads the raw data, creates the output folders, and defines every constant used later (industry codes, country groups, periods, figure style).

if (!dir.exists("Data")) {
  stop(
    "Working directory is not the project root.\n",
    "  Currently in: ", getwd(), "\n",
    "  Fix: open PKP26_manufacturing.Rproj in RStudio.",
    call. = FALSE
  )
}

getwd()
## [1] "/Users/pikaprincic/Documents/Magisterij /IMB /PKP /Data/PKP26_manufacturing"
required_packages <- c("dplyr", "ggplot2")

missing_packages <- required_packages[
  !required_packages %in% rownames(installed.packages())
]

if (length(missing_packages) > 0) {
  stop(
    "Missing required package(s): ", paste(missing_packages, collapse = ", "), "\n",
    "  Please run:\n",
    '  install.packages(c("', paste(missing_packages, collapse = '", "'), '"))',
    call. = FALSE
  )
}

suppressPackageStartupMessages({
  library(dplyr)
  library(ggplot2)
})
output_dirs <- c("output", "output/tables", "output/figures", "output/clean")

for (d in output_dirs) {
  if (!dir.exists(d)) dir.create(d, recursive = TRUE)
}

list.dirs("output")
## [1] "output"         "output/clean"   "output/figures" "output/tables"

1.1 The raw data

Source: EUKLEMS & INTANProd (LUISS). Two objects:

  • klems - industry x country x year, 1995-2021. The working dataset.
  • annual - country x year, total economy, 2010-2025. Macro context only.
raw_data_file <- "Data/Luiss_datasets.RData"

if (!file.exists(raw_data_file)) {
  stop("Raw data not found at: ", raw_data_file, call. = FALSE)
}

load(raw_data_file)

annual$year <- as.integer(annual$year)

dim(klems)
## [1] 61128   236
dim(annual)
## [1] 495  35

1.2 Project constants

focus_sections <- c("C")

industry_labels <- c(
  C = "Manufacturing"
)

industry_groups <- c(
  C = "Manufacturing"
)

1.3 Division-level codes, with the manufacturing knowledge-intensive / traditional split

For Slovenia, official investment statistics (GFCF, capital stocks, the tangible/intangible split, growth accounting) exist only at section level. Below that, at division level, only value added and the LUISS-estimated economic competencies (I_OrgCap, I_Brand, I_Train, I_Design and their capital stocks) are available.

Consequence for RQ3: the knowledge-intensive vs. traditional comparison cannot use the full tangible/intangible investment structure, only these four competency variables.

# Manufacturing only
division_parent <- c(
  "C10-C12" = "C", "C13-C15" = "C", "C16-C18" = "C", "C19" = "C",
  "C20" = "C", "C21" = "C", "C22-C23" = "C", "C24-C25" = "C",
  "C26" = "C", "C27" = "C", "C28" = "C", "C29-C30" = "C", "C31-C33" = "C"
)

division_codes <- names(division_parent)

# Manufacturing knowledge-intensive vs traditional split (PKP3 RQ3). The
# 6 KI codes and 6 of the 7 Traditional codes below are from
# PKP3.docx's RQ3 table. C19 (coke and refined petroleum) is NOT
# classified anywhere in that table, it is neither listed under
# "Knowledge-intensive manufacturing" nor "Traditional manufacturing". Placing
# it under Traditional here as an unverified assumption. 

manufacturing_division_group <- c(
  "C20"     = "Knowledge-intensive",
  "C21"     = "Knowledge-intensive",
  "C26"     = "Knowledge-intensive",
  "C27"     = "Knowledge-intensive",
  "C28"     = "Knowledge-intensive",
  "C29-C30" = "Knowledge-intensive",
  "C10-C12" = "Traditional",
  "C13-C15" = "Traditional",
  "C16-C18" = "Traditional",
  "C19"     = "Traditional",   # UNCONFIRMED - see note above
  "C22-C23" = "Traditional",
  "C24-C25" = "Traditional",
  "C31-C33" = "Traditional"
)

length(division_codes)
## [1] 13
table(division_parent)
## division_parent
##  C 
## 13
table(manufacturing_division_group)
## manufacturing_division_group
## Knowledge-intensive         Traditional 
##                   6                   7

1.4 Countries

# Only countries with usable tangible AND intangible investment data for the
# focus sections. PL, HR and IE have no intangibles at all; BE has tangibles
# but no intangibles; HU and EE have intangibles but no tangibles. Belgium and
# Ireland are usually described as intangible-intensive, so their absence is
# forced by coverage, not chosen.

country_groups <- list(
  slovenia  = "SI",
  cee       = c("CZ", "SK", "RO", "LV"),
  frontier  = c("SE", "DK", "FI", "NL"),
  neighbour = c("AT", "IT"),
  large     = c("DE", "ES", "FR"),
  outside   = c("US", "JP")
)

peer_countries <- unlist(country_groups, use.names = FALSE)

# No EU aggregate carries the intangible investment variables, so the EU
# comparison for investment is built from member states. EU12 does carry
# growth accounting and excludes Slovenia, making it a clean comparator.
ga_benchmark <- "EU12"

1.5 Periods

“1995-2021” conceals four different periods.

periods <- list(
  flows         = c(1995, 2021),
  stocks        = c(2000, 2021),
  contributions = c(2001, 2021),
  tfp           = c(2009, 2021)
)

periods
## $flows
## [1] 1995 2021
## 
## $stocks
## [1] 2000 2021
## 
## $contributions
## [1] 2001 2021
## 
## $tfp
## [1] 2009 2021

1.6 Figure style

Black and white only.

theme_pkp <- function(base_size = 11) {
  theme_bw(base_size = base_size) +
    theme(
      panel.grid.minor = element_blank(),
      panel.grid.major = element_line(colour = "grey85", linewidth = 0.3),
      panel.border     = element_rect(colour = "black", linewidth = 0.4),
      strip.background = element_rect(fill = "grey92", colour = "black"),
      legend.position  = "bottom",
      legend.title     = element_blank(),
      plot.title       = element_text(face = "bold", size = base_size)
    )
}

grey_palette <- c("black", "grey45", "grey70", "grey25", "grey85", "grey60")
save(focus_sections, industry_labels, industry_groups,
     division_codes, division_parent, manufacturing_division_group,
     country_groups, peer_countries, ga_benchmark, periods,
     theme_pkp, grey_palette,
     file = "output/clean/00_setup.RData")

cat("00_setup complete\n")
## 00_setup complete
cat("  klems  :", nrow(klems), "rows x", ncol(klems), "columns |",
    min(klems$year), "-", max(klems$year), "\n")
##   klems  : 61128 rows x 236 columns | 1995 - 2021
cat("  annual :", nrow(annual), "rows x", ncol(annual), "columns |",
    min(annual$year), "-", max(annual$year), "\n")
##   annual : 495 rows x 35 columns | 2010 - 2025
cat("  sections :", paste(focus_sections, collapse = " "), "\n")
##   sections : C
cat("  divisions:", length(division_codes), "\n")
##   divisions: 13
cat("  peers   :", length(peer_countries), "countries\n")
##   peers   : 16 countries

2 - Data cleaning

  1. Keeps only the six focus sections and the usable comparator countries
  2. Keeps only the variables the research questions need
  3. Derives the indicators (intensities, shares, composition)
  4. Checks the result adds up
  5. Saves it as output/clean/pkp_clean.rds

2.1 Filter: which rows do we keep?

Industries are matched exactly against the lists from the setup section. Never by pattern, because the industry column mixes four levels of one hierarchy. Countries are the usable comparators plus EU12.

keep_geo  <- c(peer_countries, ga_benchmark)
keep_nace <- c(focus_sections, division_codes)

dat <- klems %>%
  filter(nace_r2_code %in% keep_nace,
         geo_code     %in% keep_geo)

nrow(dat)
## [1] 6426
table(dat$geo_code)
## 
##   AT   CZ   DE   DK   ES EU12   FI   FR   IT   JP   LV   NL   RO   SE   SI   SK 
##  378  378  378  378  378  378  378  378  378  378  378  378  378  378  378  378 
##   US 
##  378

2.1.1 Marking the hierarchy level

Critical. Section C contains division C26; adding them together double-counts. Every row is labelled section or division, and every division records its parent. Always filter on level before aggregating.

dat <- dat %>%
  mutate(
    level  = if_else(nace_r2_code %in% focus_sections, "section", "division"),
    parent = if_else(level == "section",
                     nace_r2_code,
                     unname(division_parent[nace_r2_code])),
    manufacturing_group = if_else(
      nace_r2_code %in% names(manufacturing_division_group),
      unname(manufacturing_division_group[nace_r2_code]),
      NA_character_
    )
  )

table(dat$level)
## 
## division  section 
##     5967      459
table(dat$manufacturing_group, useNA = "ifany")
## 
## Knowledge-intensive         Traditional                <NA> 
##                2754                3213                 459

2.2 Select: which variables do we keep?

wanted <- c(
  "nace_r2_code", "nace_r2_name", "geo_code", "year", "level", "parent",
  "manufacturing_group",

  # output and labour input
  "VA_CP", "VA_Q", "VAadj", "VAadj_q", "EMP", "H_EMP",

  # investment, national accounts basis
  "I_GFCF", "I_IT", "I_CT", "I_Soft_DB", "I_RD", "I_OIPP",

  # investment, CHS basis
  "I_Tang", "I_Intang", "I_NatAcc", "I_NonNatAcc",
  "I_Innovprop", "I_EconComp",
  "I_OrgCap", "I_Brand", "I_Train", "I_Design",

  # investment in chained volumes (2015), needed for anything over time
  "Iq_GFCF", "Iq_Tang", "Iq_Intang",

  # capital stocks
  "K_GFCF", "K_RD", "K_Soft_DB", "K_Tang",
  "K_NatAcc", "K_NonNatAcc", "K_OrgCap", "K_Brand", "K_Train",

  # growth accounting: capital contributions split tangible/intangible/ICT/non-ICT,
  # labour quantity and quality, and both the TFP level indices and their
  # growth contributions.
  "CAPIntang_QI", "CAPTang_QI", "CAPICT_QI", "CAPNICT_QI",
  "LAB", "LAB_QI",
  "LP1TFP_I", "LP2TFP_I", "VATFP_I",
  "LP1ConTFP", "LP2ConTFP", "VAConTFP"
)

wanted <- intersect(wanted, names(dat))

dat <- dat %>%
  select(all_of(wanted)) %>%
  rename(nace = nace_r2_code,
         geo  = geo_code)

length(wanted)
## [1] 53

2.3 Deriving the indicators

All monetary variables are in millions of national currency, so levels cannot be compared across countries, every indicator below is a ratio. Two accounting bases exist and must not be mixed: national accounts (I_GFCF over VA_CP) and CHS (I_Intang, I_Tang over VAadj).

# An INTENSITY (flow relative to output) means net disinvestment. 
safe_intensity <- function(num, den) {
  if_else(!is.na(den) & den > 0, 100 * num / den, NA_real_)
}

# A SHARE (part of a whole) must lie between 0 and 100 by definition. It can
# fall outside that range only when some component of the whole is negative.
# Such a figure is not meaningful, so it is set to NA and counted, never
# silently kept or clamped to a boundary.
safe_share <- function(part, whole) {
  x <- if_else(!is.na(whole) & whole != 0, 100 * part / whole, NA_real_)
  if_else(!is.na(x) & x >= 0 & x <= 100, x, NA_real_)
}
dat <- dat %>%
  mutate(

    # -- investment intensities (percent of value added) --------------------
    inv_intensity    = safe_intensity(I_GFCF,   VA_CP),   # national accounts basis
    intang_intensity = safe_intensity(I_Intang, VAadj),   # CHS basis
    tang_intensity   = safe_intensity(I_Tang,   VAadj),

    # -- the headline structural indicator ----------------------------------
    intang_share     = safe_share(I_Intang, I_Intang + I_Tang),

    # -- CHS composition (shares of total intangible investment) ------------
    sh_compinfo      = safe_share(I_Soft_DB,   I_Intang),  # computerized information
    sh_innovprop     = safe_share(I_Innovprop, I_Intang),  # innovative property
    sh_econcomp      = safe_share(I_EconComp,  I_Intang),  # economic competencies

    # -- the measurement gap -------------------------------------------------
    sh_nonNA         = safe_share(I_NonNatAcc, I_Intang),

    # -- individual assets, as shares of intangible investment ---------------
    sh_rd            = safe_share(I_RD,      I_Intang),
    sh_orgcap        = safe_share(I_OrgCap,  I_Intang),
    sh_brand         = safe_share(I_Brand,   I_Intang),
    sh_train         = safe_share(I_Train,   I_Intang),
    sh_design        = safe_share(I_Design,  I_Intang),

    # -- tangible composition: ICT vs non-ICT (national accounts basis) ------
    ict_share        = safe_share(I_IT + I_CT + I_Soft_DB, I_GFCF),

    # -- labour productivity, CHS basis, real ---------------------------------
    lp_hour          = VAadj_q / H_EMP,

    # -- reconstructed intangible capital stock -------------------------------
    # K_Intang is unusable as delivered (one year for Slovenia). Its
    # components are complete from 2000, and their sum reproduces the
    # published figure exactly in the year it exists, so it is rebuilt here.
    K_Intang_rebuilt = K_NatAcc + K_NonNatAcc,

    # -- flag the known anomaly ----------------------------------------------
    # Slovenian stock variables spike implausibly in 2020 (K_OrgCap roughly
    # doubles and falls back). The anomaly is in the source LUISS module, not
    # introduced here. Flow variables are unaffected.
    stock_suspect    = (geo == "SI" & year == 2020)
  )

2.4 Adding labels and groups

dat <- dat %>%
  mutate(
    industry = if_else(level == "section",
                       unname(industry_labels[nace]),
                       nace_r2_name),
    group    = unname(industry_groups[parent]),
    is_focus_country = geo %in% peer_countries
  ) %>%
  select(-nace_r2_name) %>%
  relocate(nace, industry, level, parent, group, manufacturing_group, geo, year)

head(dat[dat$level == "division" & dat$parent == "C", 1:8])
## # A tibble: 6 × 8
##   nace    industry            level parent group manufacturing_group geo    year
##   <chr>   <chr>               <chr> <chr>  <chr> <chr>               <chr> <dbl>
## 1 C10-C12 Manufacture of foo… divi… C      Manu… Traditional         AT     1995
## 2 C10-C12 Manufacture of foo… divi… C      Manu… Traditional         AT     1996
## 3 C10-C12 Manufacture of foo… divi… C      Manu… Traditional         AT     1997
## 4 C10-C12 Manufacture of foo… divi… C      Manu… Traditional         AT     1998
## 5 C10-C12 Manufacture of foo… divi… C      Manu… Traditional         AT     1999
## 6 C10-C12 Manufacture of foo… divi… C      Manu… Traditional         AT     2000

2.5 Checks

# 1. Does industry + country + year still uniquely identify a row?
stopifnot(nrow(dat) == nrow(distinct(dat, nace, geo, year)))

# 1b. Is every division assigned to a parent section?
stopifnot(!any(is.na(dat$parent)))

# 2. Does the CHS identity hold?
chs_gap <- dat %>%
  filter(!is.na(I_Intang), I_Intang > 0) %>%
  mutate(d = abs(I_Soft_DB + I_Innovprop + I_EconComp - I_Intang) / I_Intang) %>%
  summarise(max_deviation_pc = 100 * max(d, na.rm = TRUE)) %>%
  pull(max_deviation_pc)

# 3. Does the national-accounts split hold?
na_gap <- dat %>%
  filter(!is.na(I_Intang), I_Intang > 0) %>%
  mutate(d = abs(I_NatAcc + I_NonNatAcc - I_Intang) / I_Intang) %>%
  summarise(max_deviation_pc = 100 * max(d, na.rm = TRUE)) %>%
  pull(max_deviation_pc)

# 4. Are the shares in a sensible range?
share_range <- range(dat$intang_share, na.rm = TRUE)

# 4b. How many observations were set aside because a component was negative?
n_suppressed <- sum(!is.na(dat$I_Intang) & !is.na(dat$I_Tang) &
                    is.na(dat$intang_share))

cat("unique key .................. OK\n")
## unique key .................. OK
cat("CHS identity, max deviation :", round(chs_gap, 6), "percent\n")
## CHS identity, max deviation : 0 percent
cat("NA split,     max deviation :", round(na_gap, 6), "percent\n")
## NA split,     max deviation : 0 percent
cat("intangible share range ......", round(share_range[1], 1), "to",
    round(share_range[2], 1), "percent\n")
## intangible share range ...... 2.7 to 100 percent
cat("shares set to NA (negative component):", n_suppressed, "\n")
## shares set to NA (negative component): 4
stopifnot(chs_gap < 0.01, na_gap < 0.01,
          share_range[1] >= 0, share_range[2] <= 100)
saveRDS(dat, "output/clean/pkp_clean.rds")

cat("01_prepare_data complete\n")
## 01_prepare_data complete
cat("  rows      :", nrow(dat), "\n")
##   rows      : 6426
cat("  columns   :", ncol(dat), "\n")
##   columns   : 72
cat("  countries :", length(unique(dat$geo)), "\n")
##   countries : 17
cat("  years     :", min(dat$year), "-", max(dat$year), "\n")
##   years     : 1995 - 2021

Later sections begin with:

load("output/clean/00_setup.RData")
dat <- readRDS("output/clean/pkp_clean.rds")

One of these before aggregating:

sections  <- dat %>% filter(level == "section")    # the main analysis
divisions <- dat %>% filter(level == "division")   # economic competencies only

Mixing the two levels in one total double-counts.


3 - Descriptive statistics

(TODO)

4 - Analysis A

(TODO)

5 - Analysis B

(TODO)

6 - Analysis C

(TODO)

7 - Interpretation

(TODO)