Sankey (oder auch die ähnlichen Alluvial) Diagramme sind eigentlich nicht für Finanzstatements da. Doch habe ich im Internet schon einige Kombinationen gesehen, bei welchen die GUV als Sankey-Diagramm dargestellt wird. Es gibt sogar schon Anbieter hierfür; aber leider habe ich kein Tutorial und kaum Code-Beispiele gefunden. Im Folgenden versuche ich also das alles zu beheben und versuche das Q3 Ergebnis von Daimler Trucks als Sankey-Diagramm zu visualisieren.
die Daten
Zuerst müssen die Daten wiefolgt aufbereitet werden. Leider nicht ganz straight-forward, aber doch nachvollziehbar:
library(ggplot2)
library(ggsankey)
library(tidyverse)
data_q3 <- tribble(
~In, ~Mid, ~Mid2, ~Out, ~Value,
"Revenue", "Cost of Sales", NA, NA, 10.886,
"Revenue", "Gross Profit", NA, NA, 2.973,
NA, "Gross Profit", "EBIT", NA, 1.219,
NA, "Gross Profit", "Expenses", NA, 1.754,
NA, "Cost of Sales", "Out", NA, 10.886,
NA, NA, "EBIT", "Net Profit", 1.246,
NA, NA, "EBIT", "Interests", 0.03,
NA, NA, "EBIT", "Taxes", 0.03,
NA, NA, "Expenses", "Selling", 0.729,
NA, NA, "Expenses", "Administr.", 0.658,
NA, NA, "Expenses", "R&D", 0.439)
head(data_q3)
## # A tibble: 6 × 5
## In Mid Mid2 Out Value
## <chr> <chr> <chr> <chr> <dbl>
## 1 Revenue Cost of Sales <NA> <NA> 10.9
## 2 Revenue Gross Profit <NA> <NA> 2.97
## 3 <NA> Gross Profit EBIT <NA> 1.22
## 4 <NA> Gross Profit Expenses <NA> 1.75
## 5 <NA> Cost of Sales Out <NA> 10.9
## 6 <NA> <NA> EBIT Net Profit 1.25
Date Crunching
Doch für den Plot muss die folgende Neuformatierung durchgeführt werden:
data_long = data_q3 %>%
make_long(In, Mid, Mid2, Out, value = Value) %>%
mutate(exclude = case_when( #exclude = new column
is.na(node) ~ "X",
x == "Mid" & is.na(next_node) ~ "X", # exclude the mid values without a next_node attribute
x == "Mid2" & is.na(next_node) ~ "X", # exclude the mid2 values without a next_node attribute
)) %>%
filter(is.na(exclude)) %>%
select(-exclude) %>%
group_by(x, node) %>%
mutate(total = sum(value))
data_long$node <- factor(data_long$node,levels = c("Selling", "Administr.", "R&D", "Taxes", "Interests", "Net Profit", "Out", "Expenses", "EBIT","Cost of Sales", "Gross Profit", "Revenue"))
data_long$next_node <- factor(data_long$next_node,levels = c("Selling", "Administr.", "R&D", "Taxes", "Interests", "Net Profit", "Out", "Expenses", "EBIT","Cost of Sales", "Gross Profit", "Revenue"))
head(data_long)
## # A tibble: 6 × 6
## # Groups: x, node [4]
## x node next_x next_node value total
## <fct> <fct> <fct> <fct> <dbl> <dbl>
## 1 In Revenue Mid Cost of Sales 10.9 13.9
## 2 In Revenue Mid Gross Profit 2.97 13.9
## 3 Mid Gross Profit Mid2 EBIT 1.22 2.97
## 4 Mid Gross Profit Mid2 Expenses 1.75 2.97
## 5 Mid Cost of Sales Mid2 Out 10.9 10.9
## 6 Mid2 EBIT Out Net Profit 1.25 1.31
Die Visualisierung
Und nun der folgende Code zur Visualisierung:
data_long %>%
ggplot(aes(x = x,
next_x = next_x,
node = node,
next_node = next_node,
fill = factor(node),
value = value,
label = paste0(node, "\n (", round(total,1), ")")
)) +
geom_sankey(flow.alpha = 0.75, node.color = 1) +
geom_sankey_label(size = 3.5, color = 1, fill = "white") +
scale_fill_viridis_d(option = "A", alpha = 0.95) +
theme_sankey(base_size = 16) +
theme_void(base_size = 18) +
theme(legend.position = "none")