Beispielanalysen

Wir glauben, dass HEX, trotz bestehender Einschränkungen, eine wertvolle Datenbasis für viele Fragestellungen in der Hochschulforschung sein kann. HEX bietet als Such- und Rechercheinstrument die Möglichkeit, Studierenden, Unternehmen und anderen Interessengruppen schnell die passenden Hochschulkurse aufzuzeigen. Zudem kann HEX Hochschulleitungen und politischen Entscheidungsträgern wichtige Steuerungsinformationen liefern. Um die vielfältigen Einsatzmöglichkeiten von HEX anschaulicher zu machen, präsentieren wir hier einige kurze Beispielanalysen. Diese basieren auf dem Vorlesungsverzeichnis der Universität zu Köln, die einer Verwendung in diesem Rahmen dankenswerterweise zugestimmt hat. Die Analysen werden mit der Programmiersprache R durchgeführt. Die durchgeführten Analysen könnten auch für das Gesamtsystem oder im Vergleich zu anderen Hochschulen, Regionen, Fakultäten und weiteren Organisationseinheiten durchgeführt werden. Dabei sollten jedoch die unterschiedlichen Strukturen der Vorlesungsverzeichnisse und weitere Limitationen beachtet werden, um valide Aussagen treffen zu können. HEX ermöglicht es, Trends, Lücken und Strukturen im Hochschulbereich zu identifizieren, die dann oftmals einer detaillierten Nachuntersuchung bedürfen. Das Ziel des Stifterverbandes ist es, Hochschulen zu unterstützen, damit sie ihre Aufgaben in Forschung, Lehre und Wissenstransfer bestmöglich erfüllen können. Das Projekt wird daher in Absprache mit den Hochschulen weitergeführt, sofern diese einen Mehrwert in HEX sehen. Hierzu erhalten die Hochschulen auch individuelle Auswertungen, in denen sie sich zu bestimmten Lehrprofilen und/oder Entwicklungen mit dem allgemeinen Datenbestand insgesamt sowie einer Vergleichsgruppe vergleichen können. Diese individuellen Auswertungen werden vom Stifterverband nicht öffentlich gemacht, sie werden der jeweiligen Hochschulleitung sowie den Stabsstellen für Hochschulentwicklung zugänglich gemacht.

Disclaimer

Bei den folgenden Beispielanalysen handelt es sich um Kurzanalysen, die lediglich einige Möglichkeiten von HEX aufzeigen sollen, d. h. die Analyse hat nicht alle wissenschaftlichen Standards durchlaufen und aufwendige Schritte in der Datenbereinigung und Prüfung der Datenvalidität wie beispielsweise Stemming oder das Testen verschiedener Modelle und Parameter im Bereich des maschinellem Lernen wurden nicht im gebotenen Maße durchgeführt. Wichtig: Auch immer die genannten Limitationen der Datenbasis für Interpretationen beachten! Für entsprechend geprüfte und “saubere” Analysen verweisen wir auf unsere sonstigen Veröffentlichungen im Rahmen von HEX auf www.higher-education-exlorer.de.

Zur Analyse wurde bereits ein Datenbankauszug getätigt und als df_koeln.rds im Arbeitsverzeichnis gespeichert. Zur Grafikerzeugung verwenden wir dabei ein selbstgeschriebenes Package namens svVis - im Prinzip werden dort Teile der bekannten R-Grafikbibliotheken ggplot2, plotly und highcharter Grafiken in ein Stifterverbands-Design überführt. svVis steht aktuell nicht auf CRAN zur Verfügung.

Setup

Laden wir zunächst die benötigten Packages sowie Daten und erstellen benötigte Funktionen.

Code
# load needed packages ---------------------------------------------------------

if (!require("pacman")) install.packages("pacman")
pacman::p_load(dplyr, flextable, officer, purrr, stringr, tidyr, tm, wordcloud, openxlsx, highcharter)
library(svVis)

# get data ---------------------------------------------------------------------

df_koeln <- readRDS("data/df_koeln.rds")
solariz_stopwords <- readRDS("data/solariz_stopwords.rds") 
university_stopwords <- readRDS("data/university_stopwords.rds") 

# create needed functions/objects ----------------------------------------------

# Funktion um sematische Fehlwerte (zum Beispiel "-") herauszufiltern

remove_semantic_na_values <- function(texts, min_num_letters = 20) {
  
  # browser()
  
  letters_only <- stringr::str_replace_all(texts, "[[:punct:]]", "")
  length_letters_only <- lapply(letters_only, nchar)
  texts[length_letters_only < min_num_letters] <- NA
  return(texts)
}

# Funktion um nach Keywords in dem Datensatz zu suchen

filter_df_koeln_by_keyword <- function(keyword) {
  
  # browser()
  
  df_koeln %>%
    filter(
    !Semester %in% c("2014_W", "2015_S", "2015_W", "2016_S"), # Ausschluss unvollstaendige Semester (siehe Text)
  ) %>% 
  mutate(
    Titel_und_Inhalt = str_c(Veranstaltungstitel, Inhalt, sep = " "),
    Titel_und_Inhalt = tolower(Titel_und_Inhalt)
  ) %>%  
  filter(grepl(keyword, Titel_und_Inhalt, ignore.case = TRUE)) %>%
  group_by(Semester) %>%
  summarise(Anzahl_Veranstaltungen = n()) %>%
  tidyr::pivot_wider(names_from = Semester, values_from = Anzahl_Veranstaltungen) %>% 
  mutate(
    across(everything(), ~ ifelse(is.na(.), 0, .)),
    Keyword = keyword,
  )
}

# Funktion zur Erstellung von Tabellen

create_table <- function(df){
  
  # browser()
  
  flextable(df) %>% 
  bg(bg = "#195365", part = "header") %>% 
  color(color = "white", part = "header") %>% 
  border_outer(part="all", border = fp_border(color = "black")) %>% 
  border_inner_h(part="all", border = fp_border(color = "black")) %>% 
  border_inner_v(part="all", border = fp_border(color = "black")) %>% 
  autofit() %>% 
  align(align = "center", part = "head") %>% 
  align(j = 2, align = "center", part = "body") %>% 
  colformat_double(big.mark = " ", digits = 0)
}

# Funktion zum Entfernen von Sonderzeichen und Leerzeichen

remove_special_characters_and_multi_whitespace <- function(text) {
  
  # browser()
  
    text <- gsub("\t|[\r\n]+", " ", text)
    text <- gsub('["“„…–]', '', text)
    text <- gsub("http[s]?://\\S+", "", text)
    text <- gsub("[^\\w\\säöüÄÖÜß]", " ", text, perl=TRUE)
    text <- gsub("\\s+", " ", text)
    text <- trimws(text)
    return(text)
}

# Funktion zum Wörterzusammenzählen

find_frequent_terms <- function(dtm, num_terms = 100) {
  
  # browser()
  
  term_frequencies <- colSums(as.matrix(dtm))
  term_frequencies_sorted <- sort(term_frequencies, decreasing = TRUE)
  top_terms <- head(term_frequencies_sorted, num_terms)
  return(top_terms)
}

# Funktion zur Vorbereitung von Textcorpi
  
prep_text_data <- function(text_vec) {
  
  # browser()
  
  corp <- Corpus(VectorSource(text_vec))
  corp <- tm_map(corp, content_transformer(tolower))
  corp <- tm_map(corp, removeNumbers)
  corp <- tm_map(corp, removePunctuation)
  corp <- tm_map(corp, content_transformer(remove_special_characters_and_multi_whitespace))
  corp <- tm_map(
    corp, 
    removeWords, 
    c(
      stopwords("de"), 
      solariz_stopwords, 
      university_stopwords
    )
  )
  dtm <- DocumentTermMatrix(corp)
  return(dtm)
}

Einfache deskriptive Analysen

Wir können nun in einem ersten Schritt erste allgemeine deskriptive Fragen an den Datensatz stellen. Hier beispielhaft drei Fragestellungen:

Wie hat sich die Anzahl der angebotenen Lehrveranstaltungen an der Universität zu Köln im Laufe der Zeit entwickelt?

Code
Kurse <- df_koeln %>% 
  mutate(Semester = str_replace(Semester, "_", " ")) %>%
  group_by(Semester) %>%
  summarise(n = n())

Grafik_Kurse <- create_lineplot(
    Kurse,
    x_var = Semester, 
    y_var = n,
    plot_title = "Anzahl angebotene Lehrveranstaltungen an der Universität zu Köln im Zeitverlauf",
    plot_subtitle = "Nach Semestern.",
    custom_caption = "",     
    plot_type = "highcharter"
  )

Grafik_Kurse

Wie wir sehen können, ist die Zahl der Veranstaltungen von Wintersemester 2014 bis Sommersemester 2016 deutlich geringer als in den nachfolgenden Semestern. Es ist davon auszugehen, dass hier das Campusmanagement-System noch nicht vollends an der Hochschule etabliert war bzw. in der Testphase war. Diese Semester sind daher aus den nachfolgenden Analysen auszuschließen. Des Weiteren können wir sehen, dass innerhalb der Studienjahre in den Wintersemestern mehr Veranstaltungen angeboten werden als in den Sommersemestern. Eine mögliche These wäre, dass dies mit dem Studienstart, der in der Regel im Wintersemester stattfindet, zusammenhängt.

Wie hoch ist der Anteil englischsprachiger Kurse nach Fakultäten an der Universität zu Köln?

Code
Englisch_Kurse <- 
  df_koeln %>%
  filter(
    !Semester %in% c("2014_W", "2015_S", "2015_W", "2016_S"), # Ausschluss unvollstaendige Semester (siehe oben)
    str_detect(Fakultaet, "Fakultät")                         # Ausschluss Verwaltung, An-Instituten etc. fuer bessere Uebersicht
  ) %>% 
  mutate(Semester = str_replace(Semester, "_", " ")) %>% 
  group_by(Semester, Fakultaet) %>%
  summarise(
    Veranstaltungen_insgesamt = n(),
    Veranstaltungen_Englisch = sum(Primaersprache == "Englisch")
  ) %>%
  ungroup() %>% 
  mutate(
    Anteil_Englisch = round(Veranstaltungen_Englisch / Veranstaltungen_insgesamt * 100, 1)
  ) 
  
Grafik_Englisch_Kurse <- create_lineplot(
  Englisch_Kurse,
  x_var = Semester,
  y_var = Anteil_Englisch,
  group_color = Fakultaet,
  plot_title = "Anteil primär englischsprachiger Veranstaltungen an der Universität zu Köln nach Fakultäten",
  plot_subtitle = "Anteil in Prozent.",
  custom_caption = "",
  plot_type = "highcharter",
)

Grafik_Englisch_Kurse

Die Analyse zeigt große Unterschiede im Anteil der primär als englischsprachig eingetragenen Veranstaltungen je nach Fakultät. Während der Anteil an der Humanwissenschaftlichen Fakultät, der Rechtswissenschaftlichen Fakultät und Medizinischen Fakultät jedes Semester bei deutlich unter 10 Prozent liegt, ist er an der Philosophischen Fakultät zuletzt bei etwa 14 Prozent. Im Mathematisch-Naturwissenschaftlichen Bereich sehen wir, dass jede fünfte Veranstaltung auf Englisch ist - an der Wirtschafts- und Sozialwissenschafltichen Fakultät wird mehr als die Hälfte aller Veranstaltungen auf Englisch durchgeführt. Es ist nicht unsere Absicht dies an dieser Stelle zu bewerten - dafür braucht es ein tieferes Einsteigen in die Literatur. Es gibt sowohl gute Gründe Veranstaltungen in deutsch (zum Beispiel Sprache als Integrationshilfe für ausländische Studierende, Erhöhung der Verständlichkeit für inländische Studierende) als auch auf Englisch (zum Beispiel Erlernen der de-facto-Wissenschaftssprache, leichterer Einstieg für ausländische Studierende) anzubieten. Jedoch hat man mit Kenntnis der Zahlen und Entwicklungen bessere Steuerungsmöglichkeiten Profile zu entwickeln und sich gestalterisch zu überlegen, in welche Richtung die Hochschulstrategie gehen soll. Auch sei hier darauf verwiesen, dass sich die Eintragpraxis bei der Primärsprache zwischen den Fakultäten unterscheiden kann.

In wie vielen Fällen stehen den Studierenden umfangreichere Veranstaltungsbeschreibungen an der Universität zu Köln zur Verfügung?

Code
Kursbeschreibungen <- 
  df_koeln %>%
  filter(
    !Semester %in% c("2014_W", "2015_S", "2015_W", "2016_S"), # Ausschluss unvollstaendige Semester (siehe oben)
  ) %>% 
  mutate(
    Inhalt = remove_semantic_na_values(Inhalt),
    Kursbeschreibung_vorhanden = ifelse(is.na(Inhalt), 0, 1),
    ausfuehrliche_Kursbeschreibung_vorhanden = ifelse(!is.na(Inhalt) & nchar(Inhalt) > 500, 1, 0)
  ) %>% 
  summarise(
    Veranstaltungen_insgesamt = n(),
    Veranstaltungen_mit_Kursbeschreibung = sum(Kursbeschreibung_vorhanden),
    Veranstaltungen_mit_ausfuehrlicher_Kursbeschreibung = sum(ausfuehrliche_Kursbeschreibung_vorhanden)
  ) %>% 
  mutate(
    Anteil_Kursbeschreibung_vorhanden = round(Veranstaltungen_mit_Kursbeschreibung / Veranstaltungen_insgesamt * 100, 1),
    Anteil_Kursbeschreibung_ausfuehrlich_vorhanden = round(Veranstaltungen_mit_ausfuehrlicher_Kursbeschreibung / Veranstaltungen_insgesamt * 100, 1),
  ) %>% 
  pivot_longer(
    cols = c(
      Anteil_Kursbeschreibung_vorhanden, 
      Anteil_Kursbeschreibung_ausfuehrlich_vorhanden)
  ) %>% 
  mutate(
    name = case_when(
      name == "Anteil_Kursbeschreibung_vorhanden" ~ "Kursbeschreibung vorhanden",
      name == "Anteil_Kursbeschreibung_ausfuehrlich_vorhanden" ~ "Ausführliche Kursbeschreibung vorhanden (über 500 Buchstaben)"
    )
  )

Grafik_Kursbeschreibungen <- create_bar(
  Kursbeschreibungen,
  x_var = name,
  y_var = value,
  plot_title = "Anteil der Veranstaltungen mit Kursbeschreibungen an der Universität zu Köln",
  plot_subtitle = paste0("Anteile in Prozent. Zeitraum: Wintersemester 2016 bis Sommersemester 2023. N = ", make_num_pretty_ger(pluck(Kursbeschreibungen[1, 1])), "."),
  source = "Stifterverband/HEX",
  remove_y_axis_text = FALSE,
  custom_caption = "",
  plot_type = "highcharter"
)
  
Grafik_Kursbeschreibungen

An der Universität zu Köln finden wir in 72,5 Prozent aller Veranstaltungsdaten eine Beschreibung zum Inhalt, in 43,2 Prozent aller Veranstaltungen findet sich ein Inhaltstext von mehr als 500 Buchstaben. Diese Werte sind auch zur Einschätzung der Datenvalidität von HEX mitentscheidend. Im Weiteren könnte man untersuchen, welche Fakultät oder Organisationseinheit sich beim Ausfüllen der Kursbeschreibungen hervortut. Auch könnte man sich zeitliche Entwicklungen anschauen. Studierende im Vorfeld über die Vorlesungsverzeichnisse und/oder gute Modulhandbücher über die Veranstaltungen zu informieren, finden wir normativ geboten. Im Vergleich zu anderen Universitäten sind die Quoten der ausgefüllten Kursbeschreibungen an der Universität zu Köln sehr hoch (Mittel an allen im Datensatz befindlichen Universitäten etwa bei 48 Prozent).

Komplexere deskriptive Analysen

In einem zweiten Schritt können wir auch etwas komplexere Auszählungen vornehmen, beispielsweise:

In welchem Maße wiederholen sich Kursangebote im Laufe der Zeit an der Universität zu Köln?

Code
Kurswiederholungen <- df_koeln %>% 
  filter(
    !Semester %in% c("2014_W", "2015_S", "2015_W", "2016_S", "2016_W", "2023_S"), # Ausschluss unvollstaendige Studienjahre (siehe oben)
  ) %>% 
  mutate(Titel_und_Inhalt = str_c(Veranstaltungstitel, Inhalt, sep = " ")) %>%  
  group_by(Titel_und_Inhalt) %>% 
  summarise(Kurshaeufigkeit = n()) %>% 
  ungroup() %>% 
  group_by(Kurshaeufigkeit) %>% 
  summarise(N = n()) %>% 
  ungroup() %>% 
  mutate(
    Kurshaeufigkeit_gruppiert = case_when(
      Kurshaeufigkeit == 1 ~ "Kurse werden einmalig im Zeitraum angeboten",
      Kurshaeufigkeit %in% c(2:4) ~ "Kurse werden 2 bis 4 mal im Zeitraum angeboten",
      Kurshaeufigkeit %in% c(5:7) ~ "Kurse werden 5 bis 7 mal im Zeitraum angeboten",
      Kurshaeufigkeit %in% c(7:10) ~ "Kurse werden 7 bis 10 mal im Zeitraum angeboten",
      Kurshaeufigkeit %in% c(11:13) ~ "Kurse werden 11 bis 13 mal im Zeitraum angeboten",
      Kurshaeufigkeit > 13 ~ "Kurse werden über 13 mal im Zeitraum angeboten"
    ),
    Kurshaeufigkeit_gruppiert = factor(
      Kurshaeufigkeit_gruppiert, 
      levels = c(
        "Kurse werden einmalig im Zeitraum angeboten",
        "Kurse werden 2 bis 4 mal im Zeitraum angeboten",
        "Kurse werden 5 bis 7 mal im Zeitraum angeboten",
        "Kurse werden 7 bis 10 mal im Zeitraum angeboten",
        "Kurse werden 11 bis 13 mal im Zeitraum angeboten",
        "Kurse werden über 13 mal im Zeitraum angeboten"
      )
    ),
  ) %>% 
  group_by(Kurshaeufigkeit_gruppiert) %>% 
  summarise(N = sum(N)) %>% 
  ungroup() %>% 
  mutate(N = svVis::make_num_pretty_ger(N)) %>% 
  arrange(Kurshaeufigkeit_gruppiert) %>% 
  rename("Kurshäufigkeit gruppiert" = Kurshaeufigkeit_gruppiert)

Tabelle_Kurswiederholungen <- 
  Kurswiederholungen %>% 
  create_table()


Tabelle_Kurswiederholungen

Kurshäufigkeit gruppiert

N

Kurse werden einmalig im Zeitraum angeboten

36.279

Kurse werden 2 bis 4 mal im Zeitraum angeboten

8.151

Kurse werden 5 bis 7 mal im Zeitraum angeboten

1.567

Kurse werden 7 bis 10 mal im Zeitraum angeboten

300

Kurse werden 11 bis 13 mal im Zeitraum angeboten

306

Kurse werden über 13 mal im Zeitraum angeboten

89

Bei Betrachtung der Studienjahre 2017 bis 2022 (46.692 Veranstaltungen) zeigt sich, dass mehr als drei Viertel der Veranstaltungen einmalig angeboten wurden oder zumindest Änderungen in der Veranstaltungsbeschreibung aufweisen. Etwa je Studienjahr wurden mit dem gleichen Titel und dem gleichen Veranstaltungsinhalt 1.567 Veranstaltungen durchgeführt - häufig Grundlagenvorlesungen. Etwa jedes Semester werden 306 Veranstaltungen ohne Änderungen in Titel oder Inhalt durchgeführt, 89 Veranstaltungen (vor allem Einführungen in das wissenschaftliche Arbeiten) wurden noch häufiger gleichbleibend angeboten. Runtergebrochen auf einzelne Studiengänge/Organisationseinheiten kann HEX hier ein Proxy für Varianz im Lehrangebot sein.

Code
# Organisationseinheiten_NegPos10 <- df_koeln %>% 
#   filter(Studienjahr %in% c("2017", "2022")) %>% 
#   group_by(Studienjahr, Organisationseinheit) %>% 
#   summarise(n = n()) %>% 
#   tidyr::pivot_wider(names_from = Studienjahr, values_from = n) %>% 
#   mutate(
#     `2017` = ifelse(is.na(`2017`), 0, `2017`),
#     `2022` = ifelse(is.na(`2022`), 0, `2022`),
#     Differenz = `2017` - `2022`
#   ) %>% 
#   arrange(Differenz) %>%
#   mutate(Differenz = - Differenz) %>% 
#   { rbind(head(., 10), tail(., 10)) } %>% 
#   add_row(Organisationseinheit = "...", .before = 11) %>% 
#   rename(
#     "Anzahl Kurse 2017" = `2017`,
#     "Anzahl Kurse 2022" = `2022`
#   )
# 
# Tabelle_Organisationseinheiten_NegPos10 <- 
#   Organisationseinheiten_NegPos10 %>% 
#   create_table()
#   
# Tabelle_Organisationseinheiten_NegPos10

Keyword-Suche und Wortfrequenzen

Hinweis zu den folgenden Auswertungen

Alle linguistischen Analysen (ab hier) hängen direkt mit der Verfügbarkeit, Länge/Ausführlichkeit und „Qualität“ der Kursbeschreibungen zusammen.

Alle Analysen sind immer vor dem Hintergrund zu verstehen, dass nicht alle Veranstaltungen eine (ausführliche) schriftliche Veranstaltungsbeschreibung haben und nicht alle Veranstaltungsbeschreibungen nach demselben Muster funktionieren. Zudem unterscheidet sich die Eintragepraxis von Hochschulen und Fachbereichen stark.

Gehen wir auf eine inhaltliche Ebene - mittels einfacher Keyword und/oder Taxonomie-Suche sowie dem Bag-of-Words-Ansatz mit einigen Beispielfragestellungen:

Welche Programmiersprachen werden an der Universität zu Köln vermittelt?

Code
Programmiersprachen <-
  bind_rows(
   python <- filter_df_koeln_by_keyword(" python "),
    filter_df_koeln_by_keyword(" javascript "),
    filter_df_koeln_by_keyword(" rust "),
    filter_df_koeln_by_keyword(" java "),
    filter_df_koeln_by_keyword(" c\\+\\+ "),
  ) %>% 
  select(Keyword, `2016_W`, everything()) %>% 
  mutate(across(.cols = !where(is.character), ~if_else(is.na(.), 0, .))) %>% 
  pivot_longer(-Keyword, names_to = "Semester") %>% 
  mutate(Semester = str_replace(Semester, "_", " ")) 

  
Grafik_Programmiersprachen <- create_lineplot(
  Programmiersprachen,
  x_var = Semester,
  y_var = value,
  group_color = Keyword,
  plot_type = "highcharter",
  plot_title = "Kurse mit ausgewählte Programmiersprachen an der Universität zu Köln",
  plot_subtitle = "Nach Semestern.",
  custom_caption = ""
)

Grafik_Programmiersprachen

Wie wir sehen hat sich das sichtbare Angebot zu Python stark gesteigert. Java und JavaScript werden in der Wirtschaftsinformatik der Universität zu Köln auch nachweislich behandelt. Dies gilt nicht für die vergleichsweise neue Programmiersprache Rust. Natürlich ist es auch möglich, dass die Sprache einfach nicht in den Kursbescheibungen genannt und dennoch vermittelt wird - im Zweifel ist dies dann aber für die Studierenden bei der Kursauswahl auch nicht ersichtlich. Dies ist ebenfalls eine vorläufige Analyse. Für aussagekräftigere Daten sind weitere Sichtkontrollen erforderlich, beispielsweise ob es sich bei dem Python-Angebot nicht lediglich um Angebote der Zoologie und damit um die Schlangenart geht und weitere Programmiersprachen hinzufügen. Auch müsste man noch Kurse aufspüren, bei denen es um Programmierung geht, aber keine konkrete Sprache geannnt wird und Abschätzungen vornehmen. Und auch inhaltlich sollte in der Informatiklehre die Vermittlung grundlegender Programmierprinzipien statt konkreter Sprachen im Vordergrund stehen. Dennoch: Man könnte mit HEX Trends und Tendenzen bei Technologien mit den Anforderungen und Tendenzen auf dem Arbeitsmarkt zusammenbringen und so Indizien finden, ob die Ausbildung an dieser Stelle Praxisanforderungen nachkommt. Spannend bei derartigen Auswertungen ist auch, wie sich bestimmte Events wie die Einführung des Studiengangs Bachelors Informatik an der Universität zu Köln zum Wintersemester 2024/25 auswirken.

Schafft es die Universität zu Köln das Lehrangebot zu Entrepreneurship auszubauen?

Code
Taxonomie_Entrepreneurship <- c(
  "entrepreneurship",
  "intrapreneurship",
  "unternehmertum",
  "start-up",
  "start up",
  "unternehmen gründen",
  "unternehmen gruenden",
  "unternehmensgründung",
  "unternehmsgruendung",
  "business-plan",
  "business plan",
  "existenzgründung",
  "existenzgruendung"
)

Entrepreneurship_Veranstaltungen <-
  df_koeln %>%
  filter(
    !Semester %in% c("2014_W", "2015_S", "2015_W", "2016_S", "2016_W", "2023_S"), # Ausschluss unvollstaendige Studienjahre (siehe oben)
  ) %>% 
  mutate(across(where(is.character), ~ tolower(.))) %>%
  filter_all(any_vars(grepl(paste(Taxonomie_Entrepreneurship, collapse = "|"), ., ignore.case = TRUE))) %>%
  group_by(Studienjahr) %>%
  summarise(Anzahl_Veranstaltungen = n()) %>% 
  ungroup()

Grafik_Entrepreneurship_Veranstaltungen <- 
  Entrepreneurship_Veranstaltungen %>% 
  create_lineplot(
    x_var = Studienjahr,
    y_var = Anzahl_Veranstaltungen,
    plot_title = "Anzahl curricuraler Veranstaltungen zu Entrepreneurship an der Universität zu Köln",
    plot_subtitle = "Auf Grundlage der Suchbegriffe: entrepreneurship, intrapreneurship, unternehmertum, start-up, start up, unternehmen gründen,unternehmen gruenden,<br> unternehmensgründung, unternehmsgruendung, business-plan, business plan, existenzgründung, existenzgruendung.",
    custom_caption = "",
    plot_type = "highcharter"
  )

Grafik_Entrepreneurship_Veranstaltungen

Hier haben wir eine einfache Suche nach Begriffen zum Thema Entrepreneurship angewendet. Diese kann man sicherlich nochmal überarbeiten, die Grundtendenz ist jedoch klar: An der Universität zu Köln finden Studierende im Jahr 2022 mehr Veranstaltungen zum Themenfeld bei Eingabe entsprechender Suchbegriffe in ihr Vorlesungsverzeichnis als fünf Jahren zuvor. Politikerinnen und Politiker, die Förderprogramme zum Thema Entrepreneurship auflegen, haben zur Evaluation dieser Programme ein weiteren - jedoch nicht alleinig nutzbaren - Indikator.

Im Dezember 2017 wurden erstmalig sogenannte Transformer, eine wichtige Grundlage für generative Sprachmodelle und Chatbots wie ChatGPT, vorgestellt. Kam diese Entwicklung in der Lehre der Universität zu Köln an? Gab es Veranstaltungen?

Code
Transformer_Taxonomie <- c(
  "BERT",
  "GPT",
  "LLaMA",
  "RoBERTa",
  "DeBERTa",
  "XLM",
  "DistilBERT",
  "XLNet",
  "ChatGPT",
  "SetFit",
  "ELECTRA",
  "PaLM",
  "Longformer",
  "SBERT",
  "SentenceTransformer",
  "(t|T)ransformer(s)?",
  "LLM(s)?"
)

Transformer_Veranstaltungen <-
  df_koeln %>%
  filter(
    !Semester %in% c("2014_W", "2015_S", "2015_W", "2016_S"), # Ausschluss unvollstaendige Semester (siehe oben)
  ) %>% 
  mutate(across(where(is.character), ~ tolower(.))) %>%
  filter_all(any_vars(grepl(paste(Transformer_Taxonomie, collapse = "|"), .))) %>% 
  select(Semester, Organisationseinheit, Veranstaltungstitel, Inhalt) %>% 
  filter(
    Veranstaltungstitel != "mann, bay, and film theory tomorrow" # Entfernen, da es um den Film Transformers: The last Knight geht und nicht um Transformer-Archithekturen für KI Modelle
  ) %>% 
  mutate(Inhalt = str_replace(Inhalt, "gereon frahling", "xx"))
 
Tabelle_Transformer_Veranstaltungen <- 
  Transformer_Veranstaltungen %>% 
  create_table()

Tabelle_Transformer_Veranstaltungen

Semester

Organisationseinheit

Veranstaltungstitel

Inhalt

2021_w

institut für digital humanities (idh)

anwendung von machine learning: neuronale netze (epc)

beschreibung: mit werkzeugen wie pytorch und tensorflow werden grundlegende kenntnisse von neuronalen netzen in praxisbeispielen vermittelt. je nach kenntnisstand des seminars werden aktuelle architekturen neuronaler netze implementiert und angewendet. mögliche themen sind dabei: long short-term memorys, convolutional neural networks, transformer netzwerke und bert. vorkenntnisse in python sind vorteilhaft.

2022_s

abteilung informatik

deep learning

dozent der vorlesung ist prof. dr. xx

neue entwicklungen im bereich der tiefen neuronalen netze haben in den letzten jahren eine große menge von anwendungen ermöglicht, die vorher in hoher qualität undenkbar waren: von bilderkennung, spracherkennung, simulation von proteinfaltung, automatischem spielen von computerspielen, bildgenerierung, bis zu sprachgenerierung und automatischer übersetzung von texten.
in dieser vorlesung werden die konzepte hinter tiefen neuronalen netzen behandelt, insbesondere convolutional neural networks (cnns), rekurrente neuronale netze (rnns), attention-mechanismen, moderne transformer-architekturen und deren erweiterungen. wir konzentrieren uns hierbei auf das sogenannte supervised deep learning, bei dem für eine bestimmte aufgabe jeweils viele trainingsbeispiele mit ihren jeweiligen lösungen bereitstehen und das netzwerk selbständig aus diesen daten lernt.
in der vorlesung wird ein mathematisches verständnis der mechanismen und des designs neuronaler netze vermittelt. gleichzeitig werden beispiele behandelt, wie man mit hilfe moderner deep learning-frameworks wie pytorch neuronale netze effizient implementieren und einsetzen kann.

2023_s

wirtschaftsinformatik

artificial intelligence and information management

this course provides you with knowledge and skills required for assessing, managing, and deploying artificial intelligence (ai) for tasks of information management (im). more recent advancements in data analytics and ai, e.g. deep learning, natural language processing (nlp), transformer models, and convolutional neural networks, provide a powerful basis for data modeling, data analysis, and new services. the methodological approaches are deployable in many industries facing tasks of information management (im). the course brings together both a technical and a managerial perspective. the technical perspective will cover (1) a general overview over artificial neural networks (ann or in short: nn) and the training process, (2) specific architectures like convolutional neural networks and their application in computer vision (cv). (3) natural language processing (nlp) including important concepts like word embeddings. especially nlp-based approaches leveraging the word embedding concept will be of foremost interest including transformer models. foundational prerequisites will be briefly revisited including types of data, feature selection, pre-processing of textual data, techniques for parameter optimization. the management perspective will cover selected topics at the interplay of ai and im relevant for information managers including:
• ai innovation: transform data into valuable information with an eye on data-based business model innovation
• building organizational ai capability: identification, incorporation and development of necessary skillsets for managing ai and preparing an organization to become data-centric
• ethics and ai, e.g., how to define and realize fair /un-biased use of data, algorithms and ai at large, aka responsible ai, explainable ai/ xai
• ai and automation – future of work: how work will be separated between man and machine in the future and how far can we get with ai in terms of automation?
• ai and regulation: is there need to regulate ai? how?
regulation and systems engineering the course strives for the state-of-the-art application of data analytics, ai approaches and issues in terms of information management. the course is less on mastering all theoretical underpinnings of the techniques or in the further development of the methods themselves. rather, it is more on deploying ai and understanding the challenges of real-world problems. we will examine selected types of questions that can be treated with means of artificial intelligence and associated methods and tools. the emphasis is on understanding the concepts and logic behind a selected set of data analytics techniques. we will deploy a variety of flipped classroom elements, including team and lab work, small competitions and presentations. individual and team assignments will be on provided data sets. students will work in teams on a kaggle-type competition.

Hierbei handelt es sich um eine Beispielanalyse, ob und wenn ja wann neue Technologie Eingang in die Lehre finden. An der Universität zu Köln finden wir – im ersten Analyseschritt – drei Veranstaltungen die in Titel oder Beschreibung Veranstaltungen zu Transformer-Modellen behandeln in den letzten Semestern. An wenigen anderen Hochschulen gibt es bereits seit dem Jahr 2020 Kurse zu dieser relativ neuen Technologie und diese sind mit HEX identifizierbar – man kann dann qualitativ diese Lehrstühle/Organisationseinheiten untersuchen, um Gelingensfaktoren über den Transferweg Forschung zu Lehre zu gewinnen. Ähnliche Untersuchungen, inwieweit gesellschaftliche Fragestellungen, Entwicklungen und Phänomene in der Hochschullehre ankommen (zum Beispiel Long-Covid, Quantentechnologien, TikTok bis zu Taylor Swift oder Ähnliches), sind denkbar.

Wie kann man das Profil des Beispielbereiches Beratungsforschung an der Universität zu Köln beschreiben?

Code
Beratungsforschung <- df_koeln %>% 
  filter(Organisationseinheit == "Arbeitsbereich Beratungsforschung") %>% 
  mutate(
    Titel_und_Inhalt = str_c(Veranstaltungstitel, Inhalt, sep = " "),
    Titel_und_Inhalt = tolower(Titel_und_Inhalt)
  ) %>% 
  select(Titel_und_Inhalt)

dtm <- prep_text_data(Beratungsforschung)

Top_Begriffe_Beratungsforschung <- find_frequent_terms(dtm) %>% 
  tibble(Begriff = names(.), Nummer = .) %>% 
  mutate(Gruppierter_Begriff = case_when(
  Begriff %in% c("systemische", "systemischen") ~ "systemisch",
  Begriff %in% c("reflektieren", "reflektiert", "reflexion") ~ "systemisch",
  Begriff %in% c("werkstattcharakternndie") ~ "werkstattcharakter",
  TRUE ~ Begriff
  )) %>%
  group_by(Gruppierter_Begriff) %>%
  summarise(Nummer = sum(Nummer))

Farben <- sample(c(svVis:::give_color_set_list()$sv0_allmain[1:3]), size = nrow(Top_Begriffe_Beratungsforschung), replace = TRUE)

wordcloud(
  words = Top_Begriffe_Beratungsforschung$Gruppierter_Begriff, 
  freq = Top_Begriffe_Beratungsforschung$Nummer, 
  min.freq = 1, 
  random.order = FALSE, 
  rot.per = 0.35, 
  colors = Farben
)

Mit einem vereinfachten Bag-of-Words Ansatz haben wir hier die Veranstaltungen der Organisationseinheit in Tokens überführt, Stopwords ausgeschlossen und – entgegen der allgemeinen Darstellungsempfehlungen im Bereich Daten – eine Wortwolke daraus erstellt. Wir können anhand dieser das Profil der Organisationseinheit in der Lehre ein wenig abschätzen und mit anderen Organisationseinheiten vergleichen. So wird in dem Arbeitsbereich beispielsweise scheinbar vor allem systemische Beratung gemacht. Auch diese Analyse ließe sich durch Lemmatisierung nochmals verbessern. Derartige Analysen können bei Strategie- und Profilbildung an Hochschulen helfen.

Einsatz von maschinellem Lernen

Topic Modelling

Topic-Modell des Fachbereichs Informatik

Code
import pandas as pd
from pandasgui import show   
import stopwords
from bertopic import BERTopic
from sentence_transformers import SentenceTransformer
from umap import UMAP
from hdbscan import HDBSCAN
from sklearn.feature_extraction.text import CountVectorizer
import re
import spacy
import numpy as np
import random
import torch

hex_info = pd.read_csv('data/hex_info.csv')

hex_info = (hex_info.query('hochschule == "Universität zu Köln"')
                    .apply(lambda x: x.fillna('') if x.dtype == 'O' else x))

hex_info['titel_kursbesch'] = hex_info['titel'] + ' ' + hex_info['kursbeschreibung']

docs = hex_info['titel_kursbesch'].tolist()

irrelevant_terms = [
    "vl",
    "übung",
    "übungen",
    "seminar",
    "arbeitsgruppenseminar",
    "oberseminar",
    "proseminar",
    "blockveranstaltung",
    "vorlesung",
    "kolloquium",
    "theoriekolloquium",
    "einführung",
    "tutorium",
    "ue",
    "vereinbarung",
    "projekt",
    "praktikum",
    "masterprojekt",
    "wiederholerklausur",
    "fortgeschrittenenpraktikum",
    "hauptseminar",
    "fachpraktikum",
    "ergänzungsvorlesung",
    "forschungspraktikum",
    "begleitseminar",
    "abschlussarbeiten",
    "unterrichtspraktikum",
    "masterseminar",
    "proseminare",
    "praxisseminar",
    "praxissemester",
    "schulpraxis",
    "ringpraktikum",
    "basispraktikum",
    "praxistage",
    "industriepraktikum",
    "vorkurs",
    "projektseminar",
    "juniorprofessur",
    "masterarbeiten",
    "forschungsseminar",
    "modulbeschreibung",
    "veranstaltung",
    "kommentare",
    "raum",
    "uhrzeit",
    "vereinbarung",

    "Informatik","gleichnamigen", "übungsaufgaben", "vorlesungsstoff vertieft", "vorlesungsstoff", "grundlagen programmierung", "schriftliche übungsaufgaben", "vertieft schriftliche übungsaufgaben", "vorlesungsstoff vertieft schriftliche", "vertieft schriftliche", "lehre",

    "siehe", "klausur", "inf misc", "sitzungen", "misc", "idee",
]

sw = list(stopwords.get_stopwords("en"))
sw.extend(list(stopwords.get_stopwords("de")))
sw.extend(irrelevant_terms)
 
vectorizer = CountVectorizer(
    stop_words=sw,
    token_pattern=r'\b\w+\b',
    ngram_range=(1, 3)
)
 
UMAPSettings = {
    "n_neighbors": 15,
    "n_components": 5,
    "min_dist": 0.1,
    "metric": "cosine",
    "random_state": 13,
}
 
HDBSCANSettings = {
    "min_samples": 10,
    "gen_min_span_tree": True,
    "prediction_data": True,
    "min_cluster_size": 10
}

EmbeddingSettings = {
    "embedding_model": SentenceTransformer,
    "model_name_or_path": "sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2",
}

BERTopicSettings = {
    "top_n_words": 10, 
    "language": "multilingual",
    "n_gram_range": (1, 4), 
    "min_topic_size": 10, 
    "calculate_probabilities": True,
    "verbose": True,
    "nr_topics": 20,
}

topic_model = BERTopic(
    vectorizer_model=vectorizer,
    embedding_model=EmbeddingSettings["embedding_model"](EmbeddingSettings["model_name_or_path"]),
    umap_model=UMAP(**UMAPSettings),
    hdbscan_model=HDBSCAN(**HDBSCANSettings),
    **BERTopicSettings
)

topics, probs = topic_model.fit_transform(docs)

new_topics = topic_model.reduce_outliers(docs, topics, strategy="distributions")

documents = pd.DataFrame({"Document": docs, "Topic": new_topics})
topic_model._update_topic_size(documents)

df_topic_model = topic_model.get_topic_info().head(50).set_index('Topic')[['Count', 'Name', 'Representation']]

df_topic_model.to_excel('data/df_topic_model.xlsx', index=False)
Code
tm_results <- read.xlsx('data/df_topic_model.xlsx')

# Hinzufügen der neuen Namen als neue Variable mit case_when
tm_results <- tm_results |>
  mutate(short_name = case_when(
    Name == '-1_networks_social_will_data' ~ 'Other_Courses',
    Name == '0_informatik_visualisierung_vertieft_daten' ~ 'Other_Courses',
    Name == '1_privatissime_doktorandenseminar_stunden_2 stunden' ~ 'Other_Courses',
    Name == '2_wissenschaftlichen_arbeiten_prof_wissenschaftlichen arbeiten' ~ 'Other_Courses',
    Name == '3_software_engineering_anforderungen_studierenden' ~ 'Software Engineering',
    Name == '4_wirtschaftsinformatik_information_betriebliche_informationstechnik' ~ 'Other_Courses',
    Name == '5_digital_transformation_digital transformation_innovation' ~ 'Digital Transformation',
    Name == '6_algorithmen_optimierung_learning_probleme' ~ 'Algorithmen',
    Name == '7_environments_electronic business_context_business' ~ 'Smart Environments',
    Name == '8_energy_systems_sustainable_sustainability' ~ 'Sustainable Energy Systems',
    Name == '9_programmierkurs_java_integrale_studium integrale' ~ 'Java',
    Name == '10_anleitung wissenschaftlichen_anleitung wissenschaftlichen arbeiten_moderation_workshops' ~ 'Other_Courses',
    Name == '11_quality_research_theoretical_empirical' ~ 'Other_Courses',
    Name == '12_graphen_graphentheorie_planare_planare graphen' ~ 'Graphentheorie',
    Name == '13_data_data science_science_business' ~ 'Data Science',
    Name == '14_systems analysis_analysis_systems analysis design_analysis design' ~ 'Systemanalyse',
    Name == '15_kneser_kombinatorik_60_borsuk ulam' ~ 'Kombinatorik',
    Name == '16_introduction data science_introduction data_science machine learning_data science machine' ~ 'Other_Courses',
    Name == '17_ag_robotik ag_robotik_roboter' ~ 'Robotik',
    Name == '18_games_game_diesem_engines' ~ 'Gameing',
    TRUE ~ Name  # Default case
  )) |>
  filter(!short_name=="Other_Courses")

Grafik_TM <- create_bar(
  tm_results,
  x_var = short_name,
  y_var = Count,
  plot_title = "Topic Model zum Bereich Informatik an der Universität zu Köln",
  #plot_subtitle = paste0("Anteile in Prozent. Zeitraum: Wintersemester 2016 bis Sommersemester 2023. N = ", make_num_pretty_ger(pluck(Kursbeschreibungen[1, 1])), "."),
  source = "Stifterverband/HEX",
  remove_y_axis_text = FALSE,
  custom_caption = "",
  plot_type = "highcharter"
)

Grafik_TM

Man kann – über Bag-of-Word-Ansätze hinausgehend – mittels maschinellem Lernens/Topic Modells auch Profile von Hochschulen, Instituten, Lehrstühlen usw. aufzeigen. Hier als Beispiel das Profil des Bereichs (Wirtschafts-)Informatik. Derartige Profile kann man dann mit den Informatik-Bereichen anderer Hochschulen vergleichen und die Profile, wenn gewünscht und unter Berücksichtigung der Limitationen, schärfen oder sich stärker für eine allgemeinere Ausbildung angleichen.Die Universität zu Köln baut zum Wintersemester 2024/25 das Informatikangebot aus mit einem neuen Studiengang.

Future Skill Classifier

Tech-Skill-Kurse im Zeitverlauf

Code
# # Aufbau Verbindung zur Datenbank
# 
# conn <- svHex::create_connection()
# 
# # Laden der benoetigten Daten
# 
# fs_tech_veranstaltungen <- svHex::get_data("veranstaltung_future_skill") %>% 
#   dplyr::filter(future_skill_id %in% 1:6)
# 
# fs_names <- svHex::get_data("future_skill")
# 
# veranstaltungen_koeln_insgesamt <- svHex::get_data("view_infopaper_veranstaltungen") %>% 
#   filter(
#     hochschule == "U Köln",
#     jahr %in% (2016:2021)
#   )
# 
# # Disconnect
# 
# DBI::dbDisconnect(conn = conn)
# 
# # Zusammenfuegen der Tables/Views zum Analyse-Datensatz
# 
# koeln_fs_tech <- dplyr::left_join(veranstaltungen_koeln_insgesamt, fs_tech_veranstaltungen) %>% 
#   left_join(fs_names, by = c("future_skill_id" = "id"))
# 
# # Data Wrangling
# 
# einzelne_tech_fs <- koeln_fs_tech %>% 
#   filter(!is.na(future_skill_id)) %>% 
#   group_by(name, jahr) %>% 
#   summarise(
#     N = n()
#   )
# 
# gesamt_tech_fs <- koeln_fs_tech %>% 
#   filter(!is.na(future_skill_id)) %>%
#   distinct(id, .keep_all = TRUE) %>% 
#   group_by(jahr) %>% 
#   summarise(
#     name = "Gesamt Tech-Future-Skills",
#     N = n()
#   ) %>% 
#   select(name, jahr, N)
# 
# gesamt_veranstaltungen_je_semester <- veranstaltungen_koeln_insgesamt %>% 
#   group_by(jahr)  %>% 
#   summarise(Total = n())
# 
# plot_data <- bind_rows(einzelne_tech_fs, gesamt_tech_fs) %>% 
#   left_join(gesamt_veranstaltungen_je_semester) %>% 
#   mutate(Anteil = round(N / Total * 100, 2))
# 
# saveRDS(plot_data, "data/plot_data.rds") # need to save because cant host to netlifly with connected to SV Network (Proxy-Again) - iterate updates manually

plot_data <- readRDS("data/plot_data.rds")

# Abbildung

svVis::create_lineplot(
  plot_data,
  jahr,
  Anteil,
  group_color = name,
  plot_type = "highcharter",
  plot_title = "Anteil Kurse an der Universität die sich expliziet mit der Vermittlung von technischen Future Skills nach dem Framework von Stifterverband und McKinsey beschäftigen",
  plot_subtitle = "Angaben in Prozent. Klassifizierung der Veranstaltungen mittels SetFit.",
  custom_caption = "Stifterverband/HEX."
)

Wie im Abschnitt zu den Analysemethoden beschrieben, haben wir ein Modell entwickelt, das Veranstaltungen hinsichtlich unseres Future Skills Framework klassifiziert. Wir haben uns in der Auswertung stark auf die technischen Future Skills beschränkt, da unseres Erachtens nur bei diesen Vorlesungsverzeichniskommentierungen eine gewisse Aussagekraft haben. Auch hier können wir die Tendenzen beobachten, ob die Ausbildung im Sinne des Frameworks in die richtige Richtung geht oder nicht.

Weitere Fragestellungen und Ausblick

Mit HEX hat man eine Datenbasis, um hochschulübergreifenden und hochschulspezifischen Fragestellungen nachzugehen. Entweder

  • das gesamte Hochschulsystem betreffend (zum Beispiel Wie entwickelt sich das Verhältnis Vorlesungen zu Seminaren in Deutschland?),
  • Regionen betreffend (Gibt es in ganz Norddeutschland Veranstaltungen zu Thema X?),
  • auf Ebene der einzelnen Hochschule wie oben veranschaulicht oder
  • auf kleinere Organisationseinheiten wie einzelne Fachbereiche, Institute oder Professuren (zum Beispiel findet R/Python in den Sozialwissenschaften mittlerweile mehr Verwendung als SPSS/Stata?).

Neben der Beantwortung solcher Fragen liegt die große Stärke von HEX darin, dass es relativ einfach ist, Kurse zu bestimmten Themen zu filtern, sich von der verwendeten Literatur und den aufgeworfenen Fragen inspirieren zu lassen und Dozierende in den relevanten Themenfeldern schnell zu identifizieren. In einer ersten weitergehenden Erprobung von HEX, über derartige Kurzanalysen hinaus, wollen wir uns in verschiedenen Projekten mit den Themen Unterrichtssprache, Quantentechnologien, Künstlicher Intelligenz (KI) und Cyber-Security beschäftigen.

Ideen für Forschungsfragen?

Sie sind Expertin oder Experte auf einem Fachgebiet und hätten relvante Forschungsfragen an die Datenbasis? Der Stifterverband lädt Expertinnen oder Experten ein, gemeinsam Themen, Trends und strukturelle Voraussetzungen der Lehre zu analysieren. Besonders interessieren uns spezifische Fragestellungen und die Analyseergebnisse aus verschiedenen Fachbereichen. Kommen Sie daher gerne mit Ihren Forschungsfragen, Projektideen oder Vorschlägen zur Weiterentwicklung von HEX auf uns zu. Kontakt: hex@stifterverband.de.