Von der Tabelle zur Netzwerk-Visualisierung
Netzwerke sind überall in unserer Umgebung:
Lieferketten
N-Gramme in Text-Mining-Projekten
Ursache-Wirkungs-Ketten
Organigramme von hirarchischen Strukturen
Persönliche und geschäftliche Kontakte
Um nur einige zu nennen.
Eine interessante Anwendung von Netzwerken sind Mitbewerber-Analysen. Anhand einer stark vereinfachten Mitbewerber-Analyse wollen wir im Folgenden das Vorgehen erklären, um von einer Tabelle zu einer Netzwerkvisualisierung zu gelangen.
Für die Visualisierung nutzen wir das htmlwidget SigmaNet welches von Ian Kloo entwickelt wurde. Es baut auf sigma.js auf. Dadurch ist es in der Lage große Netzwerke interaktiv darzustellen. Zudem wird iGraph verwendet.
Die Quelle: Liste der größten deutschen Unternehmen (2017)
Startpunkt der Analyse ist die Liste der größten Unternehmen in Deutschland nach Forbes 2000, welche auf Wikipedia zu finden ist. Wir haben diese Tabelle gewählt, da sie neben den Kennzahlen der Unternehmen auch Branche und Hauptsitz beinhaltet. Wir wollen uns ansehen, welche Zusammenhänge zwischen den Unternehmen bezüglich Branche und Unternehmenssitz existieren.
Zunächst laden wir die benötigten Pakete:
# Laden notwendiger Pakete
library(rvest) # Datenbezug von Wikipedia
library(tidyr)
library(dplyr)
library(igraph) # Netzwerk generieren
library(sigmaNet) # Netzwerk visualisieren
Daten von Wikipedia importieren
Wir importieren die Tabelle mittels rvest
# Laden der Liste von Wikipedia
url <- "https://de.wikipedia.org/wiki/Liste_der_gr%C3%B6%C3%9Ften_Unternehmen_in_Deutschland_(Forbes_2000)"
ForbesRoh <- read_html(url) %>% html_nodes("table") %>% `[[`(1) %>% html_table()
str(ForbesRoh)
Data Cleaning
Die Daten sind noch nicht in der gewünschten Form. Die Spalten
Umsatz,
Gewinn,
Aktiva und
Marktwert
liegen nicht in numerischer Form vor, sondern als String. Die Ursache ist das Dezimaltrennzeichen (, statt .) Auch bei den Mitarbeiter-Zahlen scheint etwas nicht zu stimmen. Hier wird das Tausender-Trennzeichen (.) als Dezimaltrennung erkannt. Wir lösen das Problem mittels gsub-Befehlen.
## Daten vorbereiten
# 1. Als Strings übernommene Zahlen in numerische Werte umwandeln
ForbesDF <- ForbesRoh
ForbesDF[c(6:9)] <- lapply(ForbesDF[c(6:9)],
FUN = function(x){
as.numeric(gsub(pattern = ",",
replacement = ".",
x= x,
fixed = TRUE))})
ForbesDF$Mitarbeiter <- as.numeric(gsub(pattern = ".",
replacement = "",
x= as.character(ForbesDF$Mitarbeiter),
fixed = TRUE))
str(ForbesDF)
summary(ForbesDF)
Netzwerk-Vorüberlegungen
Unser Ziel ist eine Darstellung, auf der Unternehmen mit Branchen und Hauptsitzen verknüpft sind. Unser Hauptaugenmerk gilt der Branche. Es wäre also gut diese zusätzlich hervorzuheben. Zudem wollen wir den Umsatz der Unternehmen in der Grafik ebenfalls unterbringen.
Für das Netzwerk bedeutet dies:
Kanten sind Verbindungen zwischen Unternehmen und Branchen bzw. Städten
Knoten können Branchen, Städte und Unternehmen sein
Knotenattribute sollen der Umsatz, der Unternehmensname und die Branche sein
Wir werden zur Netzwerk-Erzeugung iGraph verwenden. Die Funktion graph_from_data_frame() benötigt einen Dataframe mit Kanten-Informationen. Optional kann ein Dataframe mit Knoten-Informationen angereichert werden.
Knoten- Informationen als Dataframe vorbereiten
Der Knoten-Dataframe beinhaltet eine ID und ein Label (die Unternehmens-/ Branchen-/ und Stadt-Namen). Als zusätzliche Informationen sollen die Aktiva, sowie Gewinn, Umsatz und Anzahl der Mitarbeiter je Unternehmen hinterlegt werden.
Da wir Unternehmen mit Städten und Branchen verknüpfen wollen, werden wir zunächst einen Vektor mit allen Unternehmen, Branchen und Städten anlegen. Diesen reichern wir um eine ID an. Hierbei wird der Vektor zudem in einen Dataframe gewandelt. Den Dataframe verknüpfen wir mittels merge mit den gewünschten zusätzlichen Knoten-Informationen.
Im letzten Schritt ersetzen wir die nicht vorhandenen Werte durch 0.01. Dies geschieht, um die Knoten der Städte und Branchen später darzustellen.
# 2. Knoten-Datensatz vorbereiten
# Knoten sollen die Merkmale aufweisen
# * Name inkl. Branche und Hauptsitz
# * Mitarbeiter
# * Marktwert
# * Aktiva
# * Gewinn
# * Umsatz
ForbesListe <- ForbesDF
ForbesListe[] <- lapply(ForbesDF[c(11, 5, 4)], as.character)
ForbesListe <- unique(unlist(ForbesListe))
ForbesKnoten <- data.frame(id = 1:length(ForbesListe))
ForbesKnoten$label <- ForbesListe
ForbesKnoten <- base::merge(x = ForbesKnoten, y = ForbesDF[4:11], by.x = "label", by.y = "Name", all.x = TRUE)
ForbesKnoten <- ForbesKnoten[c(2, 1, 3:ncol(ForbesKnoten))]
ForbesKnoten[is.na(ForbesKnoten)] <- 0.01 # Min innerhalb des DF ist 0.6
Kanten-Datensatz erstellen
Im Dataframe für die Kanten müssen die Spalten “to” und “from” an erster und zweiter Stelle stehen. Diese Spalten beinhalten die ID’s der zu verknüpfenden Knoten. Zudem können weitere Informationen übergeben werden. Wir wollen ein Attribut “Type” hinzufügen. Dieses gibt an, ob die Kante zwischen einer Stadt und einem Unternehmen (“Hauptsitz”) oder einer Branche und einem Unternehmen (“Branche”) besteht.
# 3. Unternehmen mit Branchen und Städten vernüpfen
# Branche und Name aus ForbesDF herausziehen
BranchenNamen <- ForbesDF[c("Branche", "Name")]
names(BranchenNamen) <- c("to", "from")
# Namen und Branchen durch ID ersetzen
BranchenKanten<- BranchenNamen
BranchenKanten[] <- ForbesKnoten$id[match(unlist(BranchenNamen), ForbesKnoten$label)]
BranchenKanten$Typ <- "Branche"
# Branche und Name aus ForbesDF herausziehen
StadtNamen <- ForbesDF[c("Hauptsitz", "Name")]
names(StadtNamen) <- c("from", "to")
# Namen und Branchen durch ID ersetzen
StadtKanten<- StadtNamen
StadtKanten[] <- ForbesKnoten$id[match(unlist(StadtNamen), ForbesKnoten$label)]
StadtKanten$Typ <- "Hauptsitz"
# Einen Dataframe erstellen mit KantenInfos
Kanten <- rbind(BranchenKanten, StadtKanten)
Netzwerk erzeugen
Nachdem wir unsere Dataframes vorbereitet haben, können wir nun das Netzwerk erstellen. Dazu nutzen wir graph_from_data_frame() aus dem Paket iGraph. Dem Parameter d wird der Kanten-Dataframe übergeben. Der Parameter vertices erhält den Kanten-Dataframe.
GraphHauptsitzBranche <- graph_from_data_frame(d = Kanten,
vertices = ForbesKnoten)
Wir können uns das Netzwerk bereits jetzt mittels plot-Befehl ansehen:
plot(GraphHauptsitzBranche)
HTML-Netzwerk mit SigmaNet
Das ungeschmückte iGraph-Netzwerk ist unübersichtlich und bietet keine Interaktivität, wie beispielsweise das Einblenden der benachbarten Knoten. Dazu verwenden wir SigmaNet. Ohne weitere Grafik-Optionen zu verwenden erhalten wir folgendes Netzwerk:
sigmaFromIgraph(GraphHauptsitzBranche)
Voreingestellt sind die Interaktivitäten:
Label on Hover
Nachbarschaft bei Klick auf 1 Knoten
Zoomen über Doppelklick und Mausrad
Wir können dem Netzwerk auch ein bestimmtes Layout zuweisen. Standardmäßig ist layout_nicely() eingestellt. Es sucht ein optimales Layout heraus.
Wir testen nun das kreisförmige Layout:
# SigmaNet als Kreis
Layout <-layout_in_circle(GraphHauptsitzBranche)
NetzwerkForbes <- sigmaFromIgraph(GraphHauptsitzBranche, Layout)
NetzwerkForbes
Netzwerk mit Grafik-Optionen
Nachdem wir uns für ein Layout (layout_with_kk()) entschieden haben, werden nun die Knoten mit
Name als Label
Umsatz als Knotengröße und
Branche als Knotenfarbe
dargestellt.
Den Kanten weisen wir den Typ (Branche oder Hauptsitz) als Farbattribut zu.
GraphHauptsitzBranche <- graph_from_data_frame(d = Kanten,
vertices = ForbesKnoten)
Layout <- layout_with_kk(GraphHauptsitzBranche)
NetzwerkBranchenHauptsitz <- sigmaFromIgraph(GraphHauptsitzBranche, layout = Layout)
# Farbe = Branche, Verknüpfung = Stadt, Größe Knoten = Umsatz, Kantenfarbe = Typ
NodeSize <- ForbesKnoten$`Umsatz(Mrd. $)`
NetzwerkBranchenHauptsitzFormatiert <- NetzwerkBranchenHauptsitz %>%
addNodeColors(colorAttr = "Branche", colorPal = "Set2") %>% # Kantenfarbe = Branche
addNodeLabels(labelAttr = "label") %>% # Namen der Unternehmen
addNodeSize(sizeVector = NodeSize, minSize = 1, maxSize = 10) %>% # Knotengröße = Umsatz
addEdgeColors(colorAttr = "Typ", colorPal = "Set3")
NetzwerkBranchenHauptsitzFormatiert
Abbildung 4: SigmaNet-Netzwerk in finaler Version
Zum Schluss speichern wir das Netzwerk und die zugehörigen Daten.
# Netzwerk als HTML speichern
saveSigma(NetzwerkBranchenHauptsitzFormatiert, "NetzwerkForbes2000.html")
# Daten speichern
save(list = ls(), file = "NetzwerkWorkSpace.RData")
Fazit
Netzwerke zu visualisieren ist eine großartige Möglichkeit um Verbindungen zwischen verschiedenen Objekten zu veranschaulichen. Mit SigmaNet können dabei besonders große Netzwerke visualisiert und interaktiv gestaltet werden. In Verbindung mit iGraph stehen vielfältige Layout-Optionen zur Verfügung. Da die Netzwerke als HTML speicherbar sind, können auch Personen ohne Programmierkenntnisse das Netzwerk für sich entdecken.
コメント