5. Tabellen mit flextable

Publikationsreife Tabellen für Word-Dokumente

Author
Zugehörigkeit

Dr. Paul Schmidt

Last updated

7. Februar 2026

Die Standard-R-Ausgabe von Tabellen sieht in Word-Dokumenten unprofessionell aus — sie erscheint als Konsolen-Output mit Monospace-Schrift. In diesem Kapitel lernt man, wie man mit dem flextable-Paket professionelle, formatierte Tabellen erstellt, die sich nahtlos in Word-Dokumente einfügen.

Warum flextable?

Es gibt mehrere R-Pakete für Tabellen (kable, gt, huxtable, flextable), aber für Word-Output ist flextable die beste Wahl:

  • Natives Word-Format (kein Umweg über HTML)
  • Volle Kontrolle über Formatierung
  • Aktiv gepflegt und gut dokumentiert
  • Teil des “Officeverse”-Ökosystems
Hinweis

Das gt-Paket ist hervorragend für HTML-Output, aber seine Word-Unterstützung ist eingeschränkter. Für Word-Dokumente empfehle ich flextable.

Grundlagen

Eine einfache Tabelle erstellen

Der einfachste Weg, eine flextable zu erstellen:

adelie %>%
  head(5) %>%
  select(island, bill_length_mm, bill_depth_mm, body_mass_g) %>%
  flextable()

island

bill_length_mm

bill_depth_mm

body_mass_g

Torgersen

39.1

18.7

3,750

Torgersen

39.5

17.4

3,800

Torgersen

40.3

18.0

3,250

Torgersen

36.7

19.3

3,450

Torgersen

39.3

20.6

3,650

Das sieht schon viel besser aus als print(df)! Aber die Spaltenbreiten sind noch nicht optimal.

Automatische Spaltenbreiten

Mit autofit() passt flextable die Spaltenbreiten automatisch an:

adelie %>%
  head(5) %>%
  select(island, bill_length_mm, bill_depth_mm, body_mass_g) %>%
  flextable() %>%
  autofit()

island

bill_length_mm

bill_depth_mm

body_mass_g

Torgersen

39.1

18.7

3,750

Torgersen

39.5

17.4

3,800

Torgersen

40.3

18.0

3,250

Torgersen

36.7

19.3

3,450

Torgersen

39.3

20.6

3,650

Tipp

autofit() sollte in der Regel am Ende der flextable-Pipeline stehen, nachdem alle anderen Formatierungen angewendet wurden.

Spalten umbenennen und formatieren

Spaltenüberschriften ändern

Die automatischen Spaltennamen aus dem Dataframe sind oft nicht ideal für einen Report:

adelie %>%
  head(5) %>%
  select(island, bill_length_mm, bill_depth_mm, body_mass_g) %>%
  flextable() %>%
  set_header_labels(
    island = "Insel",
    bill_length_mm = "Schnabellänge (mm)",
    bill_depth_mm = "Schnabeltiefe (mm)",
    body_mass_g = "Körpermasse (g)"
  ) %>%
  autofit()

Insel

Schnabellänge (mm)

Schnabeltiefe (mm)

Körpermasse (g)

Torgersen

39.1

18.7

3,750

Torgersen

39.5

17.4

3,800

Torgersen

40.3

18.0

3,250

Torgersen

36.7

19.3

3,450

Torgersen

39.3

20.6

3,650

Zahlen formatieren

Für wissenschaftliche Tabellen braucht man oft eine bestimmte Anzahl Dezimalstellen:

adelie %>%
  head(5) %>%
  select(island, bill_length_mm, bill_depth_mm, body_mass_g) %>%
  flextable() %>%
  set_header_labels(
    island = "Insel",
    bill_length_mm = "Schnabellänge (mm)",
    bill_depth_mm = "Schnabeltiefe (mm)",
    body_mass_g = "Körpermasse (g)"
  ) %>%
  colformat_double(j = c("bill_length_mm", "bill_depth_mm"), digits = 1) %>%
  colformat_double(j = "body_mass_g", digits = 0) %>%
  autofit()

Insel

Schnabellänge (mm)

Schnabeltiefe (mm)

Körpermasse (g)

Torgersen

39.1

18.7

3,750

Torgersen

39.5

17.4

3,800

Torgersen

40.3

18.0

3,250

Torgersen

36.7

19.3

3,450

Torgersen

39.3

20.6

3,650

Formatierung und Styling

Schriftart und -größe

adelie %>%
  head(5) %>%
  select(island, bill_length_mm, body_mass_g) %>%
  flextable() %>%
  font(fontname = "Arial", part = "all") %>%
  fontsize(size = 10, part = "body") %>%
  fontsize(size = 11, part = "header") %>%
  autofit()

island

bill_length_mm

body_mass_g

Torgersen

39.1

3,750

Torgersen

39.5

3,800

Torgersen

40.3

3,250

Torgersen

36.7

3,450

Torgersen

39.3

3,650

Ausrichtung

adelie %>%
  head(5) %>%
  select(island, bill_length_mm, body_mass_g) %>%
  flextable() %>%
  align(j = 1, align = "left", part = "all") %>%
  align(j = 2:3, align = "center", part = "all") %>%
  autofit()

island

bill_length_mm

body_mass_g

Torgersen

39.1

3,750

Torgersen

39.5

3,800

Torgersen

40.3

3,250

Torgersen

36.7

3,450

Torgersen

39.3

3,650

Rahmenlinien

adelie %>%
  head(5) %>%
  select(island, bill_length_mm, body_mass_g) %>%
  flextable() %>%
  border_remove() %>%
  hline_top(border = fp_border(width = 2), part = "header") %>%
  hline_bottom(border = fp_border(width = 1), part = "header") %>%
  hline_bottom(border = fp_border(width = 2), part = "body") %>%
  autofit()

island

bill_length_mm

body_mass_g

Torgersen

39.1

3,750

Torgersen

39.5

3,800

Torgersen

40.3

3,250

Torgersen

36.7

3,450

Torgersen

39.3

3,650

Header fett formatieren

adelie %>%
  head(5) %>%
  select(island, bill_length_mm, body_mass_g) %>%
  flextable() %>%
  bold(part = "header") %>%
  autofit()

island

bill_length_mm

body_mass_g

Torgersen

39.1

3,750

Torgersen

39.5

3,800

Torgersen

40.3

3,250

Torgersen

36.7

3,450

Torgersen

39.3

3,650

Eine Summary-Tabelle erstellen

Für unseren Pinguin-Report erstellen wir eine deskriptive Statistik-Tabelle:

summary_table <- adelie %>%
  summarise(
    n = n(),
    `Schnabellänge (mm)` = mean(bill_length_mm),
    `SD` = sd(bill_length_mm),
    `Schnabeltiefe (mm)` = mean(bill_depth_mm),
    `SD ` = sd(bill_depth_mm),
    `Körpermasse (g)` = mean(body_mass_g),
    `SD  ` = sd(body_mass_g)
  )

summary_table %>%
  flextable() %>%
  colformat_double(digits = 1) %>%
  colformat_double(j = "n", digits = 0) %>%
  set_header_labels(n = "N") %>%
  bold(part = "header") %>%
  autofit()

N

Schnabellänge (mm)

SD

Schnabeltiefe (mm)

SD

Körpermasse (g)

SD

146

38.8

2.7

18.3

1.2

3,706.2

458.6

Tabelle nach Gruppen

Eine Tabelle mit Statistiken pro Insel:

adelie %>%
  group_by(island) %>%
  summarise(
    N = n(),
    `Schnabellänge` = mean(bill_length_mm),
    `Körpermasse` = mean(body_mass_g),
    .groups = "drop"
  ) %>%
  flextable() %>%
  set_header_labels(island = "Insel") %>%
  colformat_double(j = c("Schnabellänge"), digits = 1) %>%
  colformat_double(j = c("Körpermasse"), digits = 0) %>%
  bold(part = "header") %>%
  hline_top(border = fp_border(width = 2), part = "header") %>%
  hline_bottom(border = fp_border(width = 1), part = "header") %>%
  hline_bottom(border = fp_border(width = 2), part = "body") %>%
  autofit()

Insel

N

Schnabellänge

Körpermasse

Biscoe

44

39.0

3,710

Dream

55

38.5

3,701

Torgersen

47

39.0

3,709

Tabellenüberschriften in Quarto

Um eine Tabellenüberschrift hinzuzufügen, verwendet man die Chunk-Option tbl-cap:

```{r}
#| label: tbl-summary
#| tbl-cap: "Deskriptive Statistik der Adelie-Pinguine"

summary_table %>%
flextable() %>%
autofit()
```

Das Label muss mit tbl- beginnen, damit Quarto es als Tabelle erkennt und Cross-Referenzen ermöglicht (siehe Kapitel 7).

Verwendung in Word-Dokumenten

Für die korrekte Darstellung in Word-Dokumenten ist die Chunk-Option output: asis oft nicht mehr nötig (aktuelle flextable-Versionen erkennen das Format automatisch). Falls die Tabelle nicht korrekt erscheint, kann man sie hinzufügen:

```{r}
#| label: tbl-example
#| output: asis

my_table %>%
flextable() %>%
autofit()
```

Komplettes Beispiel

Hier ist eine vollständige, publikationsreife Tabelle:

adelie %>%
  group_by(island, sex) %>%
  summarise(
    N = n(),
    `Schnabellänge (mm)` = mean(bill_length_mm),
    `Körpermasse (g)` = mean(body_mass_g),
    .groups = "drop"
  ) %>%
  flextable() %>%
  set_header_labels(
    island = "Insel",
    sex = "Geschlecht"
  ) %>%
  colformat_double(j = "Schnabellänge (mm)", digits = 1) %>%
  colformat_double(j = "Körpermasse (g)", digits = 0) %>%
  font(fontname = "Arial", part = "all") %>%
  fontsize(size = 10, part = "all") %>%
  bold(part = "header") %>%
  align(align = "center", part = "header") %>%
  align(j = 1:2, align = "left", part = "body") %>%
  align(j = 3:5, align = "right", part = "body") %>%
  border_remove() %>%
  hline_top(border = fp_border(width = 1.5), part = "header") %>%
  hline_bottom(border = fp_border(width = 0.75), part = "header") %>%
  hline_bottom(border = fp_border(width = 1.5), part = "body") %>%
  autofit()

Insel

Geschlecht

N

Schnabellänge (mm)

Körpermasse (g)

Biscoe

female

22

37.4

3,369

Biscoe

male

22

40.6

4,050

Dream

female

27

36.9

3,344

Dream

male

28

40.1

4,046

Torgersen

female

24

37.6

3,396

Torgersen

male

23

40.6

4,035

TippÜbung: Erstelle eine Summary-Tabelle
  1. Erstelle eine Tabelle mit der Anzahl Pinguine pro Insel und Geschlecht
  2. Füge eine Spalte mit dem Durchschnittsgewicht hinzu
  3. Formatiere die Tabelle professionell (Schriftart, Rahmen, Ausrichtung)
  4. Füge eine Tabellenüberschrift mit tbl-cap hinzu

Weiterführende Ressourcen

Was kommt als Nächstes

Jetzt können wir professionelle Tabellen erstellen. In Kapitel 6 lernen wir, wie man ggplot2-Grafiken optimal in Quarto-Dokumente einbindet — mit der richtigen Größe, Auflösung und Beschriftung.

Zitat

Mit BibTeX zitieren:
@online{schmidt2026,
  author = {{Dr. Paul Schmidt}},
  publisher = {BioMath GmbH},
  title = {5. Tabellen mit flextable},
  date = {2026-02-07},
  url = {https://biomathcontent.netlify.app/de/content/quarto/05_tables.html},
  langid = {de}
}
Bitte zitieren Sie diese Arbeit als:
Dr. Paul Schmidt. 2026. “5. Tabellen mit flextable.” BioMath GmbH. February 7, 2026. https://biomathcontent.netlify.app/de/content/quarto/05_tables.html.