Het programma Pointer is samen met Follow The Money en Reporter Radio op zoek gegaan naar een manier om megawinsten in de zorg te kunnen onderzoeken. De uitzending van Pointer kun je hier terugkijken. Met openbare gegevens hebben zij 174 zorgbedrijven kunnen vinden met winstpercentages boven de 10%.

Ik was benieuwd of ik dit data-onderzoek zelf ook kon reproduceren. Ik heb daarbij deze verantwoording gebruikt. Op basis daarvan heb ik het onderstaande R script gemaakt.

Het handmatige onderzoek om tot de selectie van 97 verdachte zorgbedrijven te komen heb ik niet gedaan. Dus de waarschuwing van Pointer blijft van toepassing: enkel van deze lijst van 174 uitgaan en bedrijven beschuldigen is onverantwoordelijk.

Het onderzoek van Pointer is gebaseerd op gegevens van 2017. Inmiddels zijn ook gegevens van 2018 beschikbaar. Ik heb daarom dezelfde analyse ook uitgevoerd met deze gegevens.

Let op: het is mogelijk dat het script nog fouten bevat. Mocht je een fout tegenomen, dan hoor ik dat graag (bijvoorbeeld via de comments of een DM op Twitter)! Hieronder volgt het volledige script.

Eerst laden we de benodigde R pakketten.

library(tidyverse)
library(readxl)
library(knitr)
library(DT)

Analyse 2017

De dataset van CIBG is een zip-bestand met daarin ods-bestanden. Ik kreeg de ods-bestanden niet zonder foutmeldingen geladen in R. Daarom heb ik (helaas) het bestand x7conc_total_VOLLEDIG.ods eerst moeten openen in Excel en vervolgens opgeslagen als xlsx-bestand.
Vervolgens heb ik alleen de tabbladen die we nodig hebben ingeladen.

df_1 <- read_excel(path = "./Brondata/x7conc_total_VOLLEDIG.xlsx", sheet = "x7conc_total_VOLLEDIG_1", 
                   guess_max = 5000)
df_7 <- read_excel(path = "./Brondata/x7conc_total_VOLLEDIG.xlsx", sheet = "x7conc_total_VOLLEDIG_7", 
                   guess_max = 5000)
df_11 <- read_excel(path = "./Brondata/x7conc_total_VOLLEDIG.xlsx", sheet = "x7conc_total_VOLLEDIG_11", 
                    guess_max = 5000)
df_20 <- read_excel(path = "./Brondata/x7conc_total_VOLLEDIG.xlsx", sheet = "x7conc_total_VOLLEDIG_20", 
                    guess_max = 5000)

Daarna deze tabbladen samenvoegen tot 1 dataframe en alleen de kolommen selecteren die we nodig hebben.
De kolommen heb ik handmatig opgezocht in het CIBG-bronbestand. Als daar fouten in zitten dan hoor ik dat graag!

df <- df_1 %>% 
  left_join(df_7, by = "ConcernCode") %>% 
  left_join(df_11, by = "ConcernCode") %>% 
  left_join(df_20, by = "ConcernCode") %>% 
  select(concerncode = ConcernCode,
         bedrijfsnaam = c_naam, 
         rechtsvorm = qConcernRechtsvorm_qConcernRechtsvorm,
         plaats = c_plaats,
         geestelijkegezondheidszorg = `Q_TypeWTZi_Ans_TypeWTZi#8`,
         gehandicaptenzorg = `Q_TypeWTZi_Ans_TypeWTZi#10`,
         thuiszorg = `Q_TypeWTZi_Ans_TypeWTZi#13`,
         omzet2017 = jeu10800_jeu10800,
         winst2017 = jeu11500_jeu11500,
         personeelskostentotaal2017 = jeu10900_jeu10900,
         personeelskostenoverig2017 = jeu13241_jeu13241,
         omzet2016 = jeu10800_jeu10801,
         winst2016 = jeu11500_jeu11501)

Alleen de volgende drie zorgsectoren worden meegenomen in de analyse:
- Geestelijke gezondheidszorg
- Gehandicaptenzorg
- Verpleging, verzorging en thuiszorg

df <- df %>% 
  filter(!is.na(geestelijkegezondheidszorg) | 
           !is.na(gehandicaptenzorg) | 
           !is.na(thuiszorg))

Er blijven dan 1119 zorgbedrijven over.

Nog twee selecties:
- Geen VOF-bedrijven (Vennootschap Onder Firma) in de lijst, omdat tien procent winst daar geen opvallend gegeven is.
- Alleen bedrijven met een minimale omzet van 100.000 euro.

df <- df %>% 
  filter(rechtsvorm != "Vennootschap onder firma (VoF)" & 
           omzet2017 >= 100000) %>% 
  select(-rechtsvorm)

Nu zijn er nog 1077 zorgbedrijven over.

In de laatste stap berekenen we de percentages, vervolgens filteren we op een percentage winst in 2017 van meer dan 10%.

# Percentage kolommen maken
df <- df %>% 
  mutate(perc_winst2017 = round(winst2017 / omzet2017 * 100, 1),
         perc_ingehuurd2017 = round(personeelskostenoverig2017 / personeelskostentotaal2017 * 100, 1),
         perc_personeel2017 = round(personeelskostentotaal2017 / omzet2017 * 100, 1)) %>% 
  filter(perc_winst2017 > 10)

Het resultaat is deze tabel voor 2017 met 174 zorgbedrijven:

Analyse 2018

We kunnen de analyse ook doen met de nieuwe gegevens het CIBG van 2018. Daarvoor hebben we twee bestanden uit het zip-bestand nodig, omdat de rechtsvorm vreemd genoeg niet in hetzelfde bestand staat. Daarvoor heb ik een apart bestand gebruikt (namelijk van de entiteiten). Ook deze heb ik eerst moeten openen in Excel en vervolgens opgeslagen als xlsx-bestand. Vervolgens heb ik alleen de tabbladen die we nodig hebben ingeladen. Dit zijn andere tabbladen dan in het bestand van 2017.

df_1 <- read_excel(path = "./Brondata/x8conc_total.xlsx", sheet = "x8conc_total_1", 
                   guess_max = 5000)
df_5 <- read_excel(path = "./Brondata/x8conc_total.xlsx", sheet = "x8conc_total_5", 
                   guess_max = 5000)
df_21 <- read_excel(path = "./Brondata/x8conc_total.xlsx", sheet = "x8conc_total_21", 
                    guess_max = 5000)
df_ent <- read_excel(path = "./Brondata/x8ent_total.xlsx", sheet = "x8ent_total_1", 
                     guess_max = 5000)

De entiteiten-data moeten we filteren zodat we alleen de rechtsvormen van het type “Groepshoofd” overhouden. Zo voorkomen we dubbelingen.

df_ent <- df_ent %>% 
  filter(ent_Type == "Groepshoofd")

Daarna deze tabbladen samenvoegen tot 1 dataframe en alleen de kolommen selecteren die we nodig hebben.
Ook deze kolommen heb ik handmatig opgezocht in het CIBG-bronbestand. Als daar fouten in zitten dan hoor ik dat graag!

df <- df_1 %>% 
  left_join(df_ent, by = "ConcernCode") %>% 
  left_join(df_5, by = "ConcernCode") %>% 
  left_join(df_21, by = "ConcernCode") %>% 
  select(concerncode = ConcernCode, 
         bedrijfsnaam = c_naam, 
         rechtsvorm = ent_RechtsVorm_ent_RechtsVorm,
         plaats = c_plaats,
         geestelijkegezondheidszorg = `Q_TypeWTZi_Ans_TypeWTZi#8`,
         gehandicaptenzorg = `Q_TypeWTZi_Ans_TypeWTZi#10`,
         thuiszorg = `Q_TypeWTZi_Ans_TypeWTZi#13`,
         omzet2018 = jeu10800_jeu10800,
         winst2018 = jeu11500_jeu11500,
         personeelskostentotaal2018 = jeu10900_jeu10900,
         personeelskostenoverig2018 = jeu13241_jeu13241,
         omzet2017 = jeu10800_jeu10801,
         winst2017 = jeu11500_jeu11501)

Alleen de volgende drie zorgsectoren worden meegenomen in de analyse:
- Geestelijke gezondheidszorg
- Gehandicaptenzorg
- Verpleging, verzorging en thuiszorg

df <- df %>% 
  filter(!is.na(geestelijkegezondheidszorg) | 
           !is.na(gehandicaptenzorg) | 
           !is.na(thuiszorg))

Er blijven dan 1474 zorgbedrijven over.

Nog twee selecties:
- Geen VOF-bedrijven (Vennootschap Onder Firma) in de lijst, omdat tien procent winst daar geen opvallend gegeven is.
- Alleen bedrijven met een minimale omzet van 100.000 euro.

df <- df %>% 
  filter(rechtsvorm != "Vennootschap onder firma (VoF)" & 
           omzet2018 >= 100000) %>% 
  select(-rechtsvorm)

Nu zijn er nog 875 zorgbedrijven over.

In de laatste stap berekenen we de percentages, vervolgens filteren we op een percentage winst in 2018 van meer dan 10%.

# Percentage kolommen maken
df <- df %>% 
  mutate(perc_winst2018 = round(winst2018 / omzet2018 * 100, 1),
         perc_ingehuurd2018 = round(personeelskostenoverig2018 / personeelskostentotaal2018 * 100, 1),
         perc_personeel2018 = round(personeelskostentotaal2018 / omzet2018 * 100, 1)) %>% 
  filter(perc_winst2018 > 10)

Het resultaat is deze tabel voor 2018 met 127 zorgbedrijven: