08-1: Making Tables with flextable

Tips to make the most of the lecture notes

Transcript

The usual two navigation tricks: the stacked lines bottom left for a table of contents, and the letter o for a panel view of every slide. Worth knowing on this deck more than most, because between the sections there are three animated walkthroughs that step through a long pipeline one line at a time. Those take up quite a few slides each. If you are hunting for a specific function rather than watching an animation, the table of contents will get you there far faster than arrowing through. You can always come back to the animations once you know what you are looking for.

  • Click on the three horizontally stacked lines at the bottom left corner of the slide, then you will see table of contents, and you can jump to the section you want

  • Hit letter “o” on your keyboard and you will have a panel view of all the slides

Transcript

The code boxes work as usual: blue area is an editor, Run Code runs it, copy button takes it to your machine. One thing particular to this deck, though. Almost every table you see here was built when the slides were rendered, on my machine, rather than in your browser. flextable produces rich output that does not travel well through browser R. So treat the code here as something to copy into RStudio rather than something to run in place. The handful of genuinely live cells on this deck are mostly help pages. You do not have to run an entire live cell. Highlight just the lines you want, then press Command plus Enter on a Mac or Control plus Enter on Windows to evaluate that selection. The two-sheets button copies the code currently in the cell, and the circular reload button beside it restores the cell after your experiments. Those controls let you test an idea here without losing the example you started from. One more, at the right end of the toolbar: the eye icon hides that cell’s output and a second click brings it back. Some of these results run long, and once you have read one it is just pushing the rest of the slide out of view.

  • The box area with a hint of blue as the background color is where you can write code (hereafter referred to as the “code area”).
  • Hit the “Run Code” button to execute all the code inside the code area.
  • You can evaluate (run) code selectively by highlighting the parts you want to run and hitting Command + Enter for Mac (Ctrl + Enter for Windows).
  • If you want to run the codes on your computer, you can first click on the icon with two sheets of paper stacked on top of each other (top right corner of the code chunk), which copies the code in the code area. You can then paste it onto your computer.
  • You can click on the reload button (top right corner of the code chunk, left to the copy button) to revert back to the original code.
  • Click the eye icon to hide a code area’s output, and click it again to bring it back. It sits at the right end of the toolbar, next to the copy button, or on the Output banner when the output is shown beside the code. Useful when a long result pushes the rest of the slide out of view.

Create tables with the flextable package


Taste of the flextable package

head(mtcars, 20)
                     mpg cyl  disp  hp drat    wt  qsec vs am gear carb
Mazda RX4           21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4
Mazda RX4 Wag       21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4
Datsun 710          22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1
Hornet 4 Drive      21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1
Hornet Sportabout   18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2
Valiant             18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1
Duster 360          14.3   8 360.0 245 3.21 3.570 15.84  0  0    3    4
Merc 240D           24.4   4 146.7  62 3.69 3.190 20.00  1  0    4    2
Merc 230            22.8   4 140.8  95 3.92 3.150 22.90  1  0    4    2
Merc 280            19.2   6 167.6 123 3.92 3.440 18.30  1  0    4    4
Merc 280C           17.8   6 167.6 123 3.92 3.440 18.90  1  0    4    4
Merc 450SE          16.4   8 275.8 180 3.07 4.070 17.40  0  0    3    3
Merc 450SL          17.3   8 275.8 180 3.07 3.730 17.60  0  0    3    3
Merc 450SLC         15.2   8 275.8 180 3.07 3.780 18.00  0  0    3    3
Cadillac Fleetwood  10.4   8 472.0 205 2.93 5.250 17.98  0  0    3    4
Lincoln Continental 10.4   8 460.0 215 3.00 5.424 17.82  0  0    3    4
Chrysler Imperial   14.7   8 440.0 230 3.23 5.345 17.42  0  0    3    4
Fiat 128            32.4   4  78.7  66 4.08 2.200 19.47  1  1    4    1
Honda Civic         30.4   4  75.7  52 4.93 1.615 18.52  1  1    4    2
Toyota Corolla      33.9   4  71.1  65 4.22 1.835 19.90  1  1    4    1

Taste of the flextable package

head(mtcars, 20) %>%
  dplyr::select(am, carb, gear, mpg, drat)
                    am carb gear  mpg drat
Mazda RX4            1    4    4 21.0 3.90
Mazda RX4 Wag        1    4    4 21.0 3.90
Datsun 710           1    1    4 22.8 3.85
Hornet 4 Drive       0    1    3 21.4 3.08
Hornet Sportabout    0    2    3 18.7 3.15
Valiant              0    1    3 18.1 2.76
Duster 360           0    4    3 14.3 3.21
Merc 240D            0    2    4 24.4 3.69
Merc 230             0    2    4 22.8 3.92
Merc 280             0    4    4 19.2 3.92
Merc 280C            0    4    4 17.8 3.92
Merc 450SE           0    3    3 16.4 3.07
Merc 450SL           0    3    3 17.3 3.07
Merc 450SLC          0    3    3 15.2 3.07
Cadillac Fleetwood   0    4    3 10.4 2.93
Lincoln Continental  0    4    3 10.4 3.00
Chrysler Imperial    0    4    3 14.7 3.23
Fiat 128             1    1    4 32.4 4.08
Honda Civic          1    2    4 30.4 4.93
Toyota Corolla       1    1    4 33.9 4.22

Taste of the flextable package

head(mtcars, 20) %>%
  dplyr::select(am, carb, gear, mpg, drat) %>%
  flextable()

am

carb

gear

mpg

drat

1

4

4

21.0

3.90

1

4

4

21.0

3.90

1

1

4

22.8

3.85

0

1

3

21.4

3.08

0

2

3

18.7

3.15

0

1

3

18.1

2.76

0

4

3

14.3

3.21

0

2

4

24.4

3.69

0

2

4

22.8

3.92

0

4

4

19.2

3.92

0

4

4

17.8

3.92

0

3

3

16.4

3.07

0

3

3

17.3

3.07

0

3

3

15.2

3.07

0

4

3

10.4

2.93

0

4

3

10.4

3.00

0

4

3

14.7

3.23

1

1

4

32.4

4.08

1

2

4

30.4

4.93

1

1

4

33.9

4.22

Taste of the flextable package

head(mtcars, 20) %>%
  dplyr::select(am, carb, gear, mpg, drat) %>%
  flextable() %>%
  theme_vanilla()

am

carb

gear

mpg

drat

1

4

4

21.0

3.90

1

4

4

21.0

3.90

1

1

4

22.8

3.85

0

1

3

21.4

3.08

0

2

3

18.7

3.15

0

1

3

18.1

2.76

0

4

3

14.3

3.21

0

2

4

24.4

3.69

0

2

4

22.8

3.92

0

4

4

19.2

3.92

0

4

4

17.8

3.92

0

3

3

16.4

3.07

0

3

3

17.3

3.07

0

3

3

15.2

3.07

0

4

3

10.4

2.93

0

4

3

10.4

3.00

0

4

3

14.7

3.23

1

1

4

32.4

4.08

1

2

4

30.4

4.93

1

1

4

33.9

4.22

Taste of the flextable package

head(mtcars, 20) %>%
  dplyr::select(am, carb, gear, mpg, drat) %>%
  flextable() %>%
  theme_vanilla() %>%
  set_header_labels(mpg = "miles per gallon")

am

carb

gear

miles per gallon

drat

1

4

4

21.0

3.90

1

4

4

21.0

3.90

1

1

4

22.8

3.85

0

1

3

21.4

3.08

0

2

3

18.7

3.15

0

1

3

18.1

2.76

0

4

3

14.3

3.21

0

2

4

24.4

3.69

0

2

4

22.8

3.92

0

4

4

19.2

3.92

0

4

4

17.8

3.92

0

3

3

16.4

3.07

0

3

3

17.3

3.07

0

3

3

15.2

3.07

0

4

3

10.4

2.93

0

4

3

10.4

3.00

0

4

3

14.7

3.23

1

1

4

32.4

4.08

1

2

4

30.4

4.93

1

1

4

33.9

4.22

Taste of the flextable package

head(mtcars, 20) %>%
  dplyr::select(am, carb, gear, mpg, drat) %>%
  flextable() %>%
  theme_vanilla() %>%
  set_header_labels(mpg = "miles per gallon") %>%
  autofit()

am

carb

gear

miles per gallon

drat

1

4

4

21.0

3.90

1

4

4

21.0

3.90

1

1

4

22.8

3.85

0

1

3

21.4

3.08

0

2

3

18.7

3.15

0

1

3

18.1

2.76

0

4

3

14.3

3.21

0

2

4

24.4

3.69

0

2

4

22.8

3.92

0

4

4

19.2

3.92

0

4

4

17.8

3.92

0

3

3

16.4

3.07

0

3

3

17.3

3.07

0

3

3

15.2

3.07

0

4

3

10.4

2.93

0

4

3

10.4

3.00

0

4

3

14.7

3.23

1

1

4

32.4

4.08

1

2

4

30.4

4.93

1

1

4

33.9

4.22

Taste of the flextable package

head(mtcars, 20) %>%
  dplyr::select(am, carb, gear, mpg, drat) %>%
  flextable() %>%
  theme_vanilla() %>%
  set_header_labels(mpg = "miles per gallon") %>%
  autofit() %>%
  merge_v(j = c("am", "carb"))

am

carb

gear

miles per gallon

drat

1

4

4

21.0

3.90

4

21.0

3.90

1

4

22.8

3.85

0

3

21.4

3.08

2

3

18.7

3.15

1

3

18.1

2.76

4

3

14.3

3.21

2

4

24.4

3.69

4

22.8

3.92

4

4

19.2

3.92

4

17.8

3.92

3

3

16.4

3.07

3

17.3

3.07

3

15.2

3.07

4

3

10.4

2.93

3

10.4

3.00

3

14.7

3.23

1

1

4

32.4

4.08

2

4

30.4

4.93

1

4

33.9

4.22

Taste of the flextable package

head(mtcars, 20) %>%
  dplyr::select(am, carb, gear, mpg, drat) %>%
  flextable() %>%
  theme_vanilla() %>%
  set_header_labels(mpg = "miles per gallon") %>%
  autofit() %>%
  merge_v(j = c("am", "carb")) %>%
  italic(j = 1)

am

carb

gear

miles per gallon

drat

1

4

4

21.0

3.90

4

21.0

3.90

1

4

22.8

3.85

0

3

21.4

3.08

2

3

18.7

3.15

1

3

18.1

2.76

4

3

14.3

3.21

2

4

24.4

3.69

4

22.8

3.92

4

4

19.2

3.92

4

17.8

3.92

3

3

16.4

3.07

3

17.3

3.07

3

15.2

3.07

4

3

10.4

2.93

3

10.4

3.00

3

14.7

3.23

1

1

4

32.4

4.08

2

4

30.4

4.93

1

4

33.9

4.22

Taste of the flextable package

head(mtcars, 20) %>%
  dplyr::select(am, carb, gear, mpg, drat) %>%
  flextable() %>%
  theme_vanilla() %>%
  set_header_labels(mpg = "miles per gallon") %>%
  autofit() %>%
  merge_v(j = c("am", "carb")) %>%
  italic(j = 1) %>%
  bg(bg = "#C90000", part = "header")

am

carb

gear

miles per gallon

drat

1

4

4

21.0

3.90

4

21.0

3.90

1

4

22.8

3.85

0

3

21.4

3.08

2

3

18.7

3.15

1

3

18.1

2.76

4

3

14.3

3.21

2

4

24.4

3.69

4

22.8

3.92

4

4

19.2

3.92

4

17.8

3.92

3

3

16.4

3.07

3

17.3

3.07

3

15.2

3.07

4

3

10.4

2.93

3

10.4

3.00

3

14.7

3.23

1

1

4

32.4

4.08

2

4

30.4

4.93

1

4

33.9

4.22

Taste of the flextable package

head(mtcars, 20) %>%
  dplyr::select(am, carb, gear, mpg, drat) %>%
  flextable() %>%
  theme_vanilla() %>%
  set_header_labels(mpg = "miles per gallon") %>%
  autofit() %>%
  merge_v(j = c("am", "carb")) %>%
  italic(j = 1) %>%
  bg(bg = "#C90000", part = "header") %>%
  color(color = "blue", j = 5)

am

carb

gear

miles per gallon

drat

1

4

4

21.0

3.90

4

21.0

3.90

1

4

22.8

3.85

0

3

21.4

3.08

2

3

18.7

3.15

1

3

18.1

2.76

4

3

14.3

3.21

2

4

24.4

3.69

4

22.8

3.92

4

4

19.2

3.92

4

17.8

3.92

3

3

16.4

3.07

3

17.3

3.07

3

15.2

3.07

4

3

10.4

2.93

3

10.4

3.00

3

14.7

3.23

1

1

4

32.4

4.08

2

4

30.4

4.93

1

4

33.9

4.22

Taste of the flextable package

head(mtcars, 20) %>%
  dplyr::select(am, carb, gear, mpg, drat) %>%
  flextable() %>%
  theme_vanilla() %>%
  set_header_labels(mpg = "miles per gallon") %>%
  autofit() %>%
  merge_v(j = c("am", "carb")) %>%
  italic(j = 1) %>%
  bg(bg = "#C90000", part = "header") %>%
  color(color = "blue", j = 5) %>%
  color(color = "red", i = 5:10, j = 2)

am

carb

gear

miles per gallon

drat

1

4

4

21.0

3.90

4

21.0

3.90

1

4

22.8

3.85

0

3

21.4

3.08

2

3

18.7

3.15

1

3

18.1

2.76

4

3

14.3

3.21

2

4

24.4

3.69

4

22.8

3.92

4

4

19.2

3.92

4

17.8

3.92

3

3

16.4

3.07

3

17.3

3.07

3

15.2

3.07

4

3

10.4

2.93

3

10.4

3.00

3

14.7

3.23

1

1

4

32.4

4.08

2

4

30.4

4.93

1

4

33.9

4.22

Taste of the flextable package

head(mtcars, 20) %>%
  dplyr::select(am, carb, gear, mpg, drat) %>%
  flextable() %>%
  theme_vanilla() %>%
  set_header_labels(mpg = "miles per gallon") %>%
  autofit() %>%
  merge_v(j = c("am", "carb")) %>%
  italic(j = 1) %>%
  bg(bg = "#C90000", part = "header") %>%
  color(color = "blue", j = 5) %>%
  color(color = "red", i = 5:10, j = 2) %>%
  color(color = "white", part = "header")

am

carb

gear

miles per gallon

drat

1

4

4

21.0

3.90

4

21.0

3.90

1

4

22.8

3.85

0

3

21.4

3.08

2

3

18.7

3.15

1

3

18.1

2.76

4

3

14.3

3.21

2

4

24.4

3.69

4

22.8

3.92

4

4

19.2

3.92

4

17.8

3.92

3

3

16.4

3.07

3

17.3

3.07

3

15.2

3.07

4

3

10.4

2.93

3

10.4

3.00

3

14.7

3.23

1

1

4

32.4

4.08

2

4

30.4

4.93

1

4

33.9

4.22

Taste of the flextable package

head(mtcars, 20) %>%
  dplyr::select(am, carb, gear, mpg, drat) %>%
  flextable() %>%
  theme_vanilla() %>%
  set_header_labels(mpg = "miles per gallon") %>%
  autofit() %>%
  merge_v(j = c("am", "carb")) %>%
  italic(j = 1) %>%
  bg(bg = "#C90000", part = "header") %>%
  color(color = "blue", j = 5) %>%
  color(color = "red", i = 5:10, j = 2) %>%
  color(color = "white", part = "header") %>%
  bold(~ drat > 3.2, ~gear, bold = TRUE)

am

carb

gear

miles per gallon

drat

1

4

4

21.0

3.90

4

21.0

3.90

1

4

22.8

3.85

0

3

21.4

3.08

2

3

18.7

3.15

1

3

18.1

2.76

4

3

14.3

3.21

2

4

24.4

3.69

4

22.8

3.92

4

4

19.2

3.92

4

17.8

3.92

3

3

16.4

3.07

3

17.3

3.07

3

15.2

3.07

4

3

10.4

2.93

3

10.4

3.00

3

14.7

3.23

1

1

4

32.4

4.08

2

4

30.4

4.93

1

4

33.9

4.22

Taste of the flextable package

head(mtcars, 20) %>%
  dplyr::select(am, carb, gear, mpg, drat) %>%
  flextable() %>%
  theme_vanilla() %>%
  set_header_labels(mpg = "miles per gallon") %>%
  autofit() %>%
  merge_v(j = c("am", "carb")) %>%
  italic(j = 1) %>%
  bg(bg = "#C90000", part = "header") %>%
  color(color = "blue", j = 5) %>%
  color(color = "red", i = 5:10, j = 2) %>%
  color(color = "white", part = "header") %>%
  bold(~ drat > 3.2, ~gear, bold = TRUE) %>%
  align(j = 1)

am

carb

gear

miles per gallon

drat

1

4

4

21.0

3.90

4

21.0

3.90

1

4

22.8

3.85

0

3

21.4

3.08

2

3

18.7

3.15

1

3

18.1

2.76

4

3

14.3

3.21

2

4

24.4

3.69

4

22.8

3.92

4

4

19.2

3.92

4

17.8

3.92

3

3

16.4

3.07

3

17.3

3.07

3

15.2

3.07

4

3

10.4

2.93

3

10.4

3.00

3

14.7

3.23

1

1

4

32.4

4.08

2

4

30.4

4.93

1

4

33.9

4.22

Taste of the flextable package

head(mtcars, 20) %>%
  dplyr::select(am, carb, gear, mpg, drat) %>%
  flextable() %>%
  theme_vanilla() %>%
  set_header_labels(mpg = "miles per gallon") %>%
  autofit() %>%
  merge_v(j = c("am", "carb")) %>%
  italic(j = 1) %>%
  bg(bg = "#C90000", part = "header") %>%
  color(color = "blue", j = 5) %>%
  color(color = "red", i = 5:10, j = 2) %>%
  color(color = "white", part = "header") %>%
  bold(~ drat > 3.2, ~gear, bold = TRUE) %>%
  align(j = 1) %>%
  fontsize(i = 12:18, size = 8)

am

carb

gear

miles per gallon

drat

1

4

4

21.0

3.90

4

21.0

3.90

1

4

22.8

3.85

0

3

21.4

3.08

2

3

18.7

3.15

1

3

18.1

2.76

4

3

14.3

3.21

2

4

24.4

3.69

4

22.8

3.92

4

4

19.2

3.92

4

17.8

3.92

3

3

16.4

3.07

3

17.3

3.07

3

15.2

3.07

4

3

10.4

2.93

3

10.4

3.00

3

14.7

3.23

1

1

4

32.4

4.08

2

4

30.4

4.93

1

4

33.9

4.22

Taste of the flextable package

head(mtcars, 20) %>%
  dplyr::select(am, carb, gear, mpg, drat) %>%
  flextable() %>%
  theme_vanilla() %>%
  set_header_labels(mpg = "miles per gallon") %>%
  autofit() %>%
  merge_v(j = c("am", "carb")) %>%
  italic(j = 1) %>%
  bg(bg = "#C90000", part = "header") %>%
  color(color = "blue", j = 5) %>%
  color(color = "red", i = 5:10, j = 2) %>%
  color(color = "white", part = "header") %>%
  bold(~ drat > 3.2, ~gear, bold = TRUE) %>%
  align(j = 1) %>%
  fontsize(i = 12:18, size = 8) %>%
  add_footer_row(values = "blah blah", colwidths = 5)

am

carb

gear

miles per gallon

drat

1

4

4

21.0

3.90

4

21.0

3.90

1

4

22.8

3.85

0

3

21.4

3.08

2

3

18.7

3.15

1

3

18.1

2.76

4

3

14.3

3.21

2

4

24.4

3.69

4

22.8

3.92

4

4

19.2

3.92

4

17.8

3.92

3

3

16.4

3.07

3

17.3

3.07

3

15.2

3.07

4

3

10.4

2.93

3

10.4

3.00

3

14.7

3.23

1

1

4

32.4

4.08

2

4

30.4

4.93

1

4

33.9

4.22

blah blah

Taste of the flextable package

head(mtcars, 20) %>%
  dplyr::select(am, carb, gear, mpg, drat) %>%
  flextable() %>%
  theme_vanilla() %>%
  set_header_labels(mpg = "miles per gallon") %>%
  autofit() %>%
  merge_v(j = c("am", "carb")) %>%
  italic(j = 1) %>%
  bg(bg = "#C90000", part = "header") %>%
  color(color = "blue", j = 5) %>%
  color(color = "red", i = 5:10, j = 2) %>%
  color(color = "white", part = "header") %>%
  bold(~ drat > 3.2, ~gear, bold = TRUE) %>%
  align(j = 1) %>%
  fontsize(i = 12:18, size = 8) %>%
  add_footer_row(values = "blah blah", colwidths = 5) %>%
  border_outer(fp_border(color = "red", width = 2))

am

carb

gear

miles per gallon

drat

1

4

4

21.0

3.90

4

21.0

3.90

1

4

22.8

3.85

0

3

21.4

3.08

2

3

18.7

3.15

1

3

18.1

2.76

4

3

14.3

3.21

2

4

24.4

3.69

4

22.8

3.92

4

4

19.2

3.92

4

17.8

3.92

3

3

16.4

3.07

3

17.3

3.07

3

15.2

3.07

4

3

10.4

2.93

3

10.4

3.00

3

14.7

3.23

1

1

4

32.4

4.08

2

4

30.4

4.93

1

4

33.9

4.22

blah blah

Taste of the flextable package

head(mtcars, 20) %>%
  dplyr::select(am, carb, gear, mpg, drat) %>%
  flextable() %>%
  theme_vanilla() %>%
  set_header_labels(mpg = "miles per gallon") %>%
  autofit() %>%
  merge_v(j = c("am", "carb")) %>%
  italic(j = 1) %>%
  bg(bg = "#C90000", part = "header") %>%
  color(color = "blue", j = 5) %>%
  color(color = "red", i = 5:10, j = 2) %>%
  color(color = "white", part = "header") %>%
  bold(~ drat > 3.2, ~gear, bold = TRUE) %>%
  align(j = 1) %>%
  fontsize(i = 12:18, size = 8) %>%
  add_footer_row(values = "blah blah", colwidths = 5) %>%
  border_outer(fp_border(color = "red", width = 2)) %>%
  line_spacing(space = 1.5)

am

carb

gear

miles per gallon

drat

1

4

4

21.0

3.90

4

21.0

3.90

1

4

22.8

3.85

0

3

21.4

3.08

2

3

18.7

3.15

1

3

18.1

2.76

4

3

14.3

3.21

2

4

24.4

3.69

4

22.8

3.92

4

4

19.2

3.92

4

17.8

3.92

3

3

16.4

3.07

3

17.3

3.07

3

15.2

3.07

4

3

10.4

2.93

3

10.4

3.00

3

14.7

3.23

1

1

4

32.4

4.08

2

4

30.4

4.93

1

4

33.9

4.22

blah blah

Taste of the flextable package

head(mtcars, 20) %>%
  dplyr::select(am, carb, gear, mpg, drat) %>%
  flextable() %>%
  theme_vanilla() %>%
  set_header_labels(mpg = "miles per gallon") %>%
  autofit() %>%
  merge_v(j = c("am", "carb")) %>%
  italic(j = 1) %>%
  bg(bg = "#C90000", part = "header") %>%
  color(color = "blue", j = 5) %>%
  color(color = "red", i = 5:10, j = 2) %>%
  color(color = "white", part = "header") %>%
  bold(~ drat > 3.2, ~gear, bold = TRUE) %>%
  align(j = 1) %>%
  fontsize(i = 12:18, size = 8) %>%
  add_footer_row(values = "blah blah", colwidths = 5) %>%
  border_outer(fp_border(color = "red", width = 2)) %>%
  line_spacing(space = 1.5) %>%
  theme_tron()

am

carb

gear

miles per gallon

drat

1

4

4

21.0

3.90

4

21.0

3.90

1

4

22.8

3.85

0

3

21.4

3.08

2

3

18.7

3.15

1

3

18.1

2.76

4

3

14.3

3.21

2

4

24.4

3.69

4

22.8

3.92

4

4

19.2

3.92

4

17.8

3.92

3

3

16.4

3.07

3

17.3

3.07

3

15.2

3.07

4

3

10.4

2.93

3

10.4

3.00

3

14.7

3.23

1

1

4

32.4

4.08

2

4

30.4

4.93

1

4

33.9

4.22

blah blah

Create table and modify Parts

Transcript

Two packages to install before anything else. flextable is the one that makes tables. officer is the one that describes formatting, and it matters more than it looks, because the fp underscore functions you will use all afternoon to specify text, paragraph and cell properties live in officer rather than in flextable. That split catches people out. You will be halfway through a flextable pipeline and reaching for an officer function. Install and load both, and do not be surprised when the help page for something you are using turns out to belong to the other package. The two install dot packages calls download the packages to your computer, so you normally run those only once. The two library calls attach them for the current R session, so those belong in the analysis script you run each time. The chunk is marked eval false because a lecture slide should not reinstall software whenever the deck renders. Copy these lines to your own R session and run the installation lines only if the packages are missing.

Install the following packages and library them.

#--- install if you have not ---#
install.packages("flextable")
install.packages("officer")

#--- library ---#
library(flextable)
library(officer)
Transcript

The dataset for the rest of the lecture. It comes from countrypops in the gt package, filtered to ten Pacific and Australasian countries and three years, then pivoted so each year becomes its own column. Ten rows, deliberately small enough that you can see the whole table on a slide and check that your formatting did what you expected. Note the region column built with case when, because we use it repeatedly for row selection later. And the ratio column at the bottom has been renamed: it divides twenty fifteen by twenty oh five, so oh five to fifteen is the honest name. Read the preparation from the top. The first three character vectors collect the two-letter country codes for Australasia, Melanesia and Polynesia. Loading gt makes countrypops available. The assignment to tab data is wrapped in parentheses so R both stores the finished data and prints it for inspection. The first filter keeps codes appearing in any of those three vectors, and the second keeps nineteen ninety-five, two thousand five and two thousand fifteen. Case when then tests membership in each regional vector and writes the matching region label. Pivot wider takes population as the cell values, turns year into separate columns, and adds the y underscore prefix, giving columns such as y underscore nineteen ninety-five. Arrange sorts regions alphabetically and, within each region, puts the largest two thousand fifteen population first. Select minus starts with country underscore code removes both country-code fields. The final mutate adds the verified two thousand fifteen divided by two thousand five ratio and a common date string. This careful preparation is why later formatting examples can select meaningful groups and display a compact table without repeating data-wrangling code.

#--- Define regions ---#
Australasia <- c("AU", "NZ")
Melanesia <- c("NC", "PG", "SB", "VU")
Polynesia <- c("PF", "WS", "TO", "TV")

library(gt)

#--- create a dataset ---#
(
  tab_data <-
    countrypops %>%
    dplyr::filter(country_code_2 %in% c(
      Australasia, Melanesia, Polynesia
    )) %>%
    dplyr::filter(year %in% c(1995, 2005, 2015)) %>%
    mutate(region = case_when(
      country_code_2 %in% Australasia ~ "Australasia",
      country_code_2 %in% Melanesia ~ "Melanesia",
      country_code_2 %in% Polynesia ~ "Polynesia",
    )) %>%
    pivot_wider(
      values_from = population,
      names_from = year,
      names_prefix = "y_"
    ) %>%
    dplyr::arrange(region, desc(y_2015)) %>%
    dplyr::select(-starts_with("country_code")) %>%
    mutate(
      #--- CHANGED: was named pop_ratio_10_15, but it divides 2015 by 2005 ---#
      pop_ratio_05_15 = y_2015 / y_2005,
      date = "2013-11-14"
    )
)
# A tibble: 10 × 7
   country_name     region        y_1995   y_2005   y_2015 pop_ratio_05_15 date 
   <chr>            <chr>          <int>    <int>    <int>           <dbl> <chr>
 1 Australia        Australasia 18004882 20176844 23815995            1.18 2013…
 2 New Zealand      Australasia  3673400  4133900  4609400            1.12 2013…
 3 Papua New Guinea Melanesia    4616439  6498818  8682174            1.34 2013…
 4 Solomon Islands  Melanesia     375189   482486   612660            1.27 2013…
 5 Vanuatu          Melanesia     170612   217632   276438            1.27 2013…
 6 New Caledonia    Melanesia     193816   232250   269460            1.16 2013…
 7 French Polynesia Polynesia     231446   271060   291787            1.08 2013…
 8 Samoa            Polynesia     174902   188626   203571            1.08 2013…
 9 Tonga            Polynesia      99977   105633   106122            1.00 2013…
10 Tuvalu           Polynesia       9585     9912    10877            1.10 2013…
Transcript

Turning a data frame into a flextable is one function call. The interesting argument is col keys, which does two jobs at once. It selects which columns appear, and it sets the order they appear in, so you do not need a separate select step beforehand. Then look at the odd string in the example, the one that is clearly not a column name. Naming something that does not exist does not throw an error. It creates a blank column, deliberately, and blank columns are how you put visual gaps between groups of columns in a finished table. Here the table starts from tab data and requests country name, the nonexistent lufhierh key, region, y underscore nineteen ninety-five and y underscore two thousand five in exactly that order. In the How tab, eval false shows the syntax without executing it. In Example, the left chunk is likewise code-only, while echo false on the right hides the repeated source and displays the resulting table. Compare the two sides and locate the empty column between country name and region. That visible gap is the practical reason col keys accepts a name that is absent from the data.

We can apply flextable() to a data.frame to initiate a table:

flextable(
  tab_data,
  col_keys =
    c(
      "country_name",
      "lufhierh",
      "region",
      "y_1995",
      "y_2005"
    )
)

where col_keys are the list of the name of the variables from the data.frame (providing variable names that do not exist in the dataset creates blank columns)

flextable(
  tab_data,
  col_keys =
    c(
      "country_name",
      "lufhierh",
      "region",
      "y_1995",
      "y_2005"
    )
)

country_name

region

y_1995

y_2005

Australia

Australasia

18,004,882

20,176,844

New Zealand

Australasia

3,673,400

4,133,900

Papua New Guinea

Melanesia

4,616,439

6,498,818

Solomon Islands

Melanesia

375,189

482,486

Vanuatu

Melanesia

170,612

217,632

New Caledonia

Melanesia

193,816

232,250

French Polynesia

Polynesia

231,446

271,060

Samoa

Polynesia

174,902

188,626

Tonga

Polynesia

99,977

105,633

Tuvalu

Polynesia

9,585

9,912

Selector

Transcript

Nearly every formatting function in flextable takes the same two arguments, so learning them once buys you the whole package. i selects rows, j selects columns. What makes them flexible is that each accepts several forms. Rows can be a formula describing a condition, a vector of row numbers, or a vector of TRUEs and FALSEs. Columns can be a formula, column names, or column numbers. And you can mix them freely. The next four tabs work through the combinations, and once you have seen them, the rest of this deck is just naming which property to change.

Many functions let you choose specifically where you apply changes. Those functions have

  • i for selecting rows
    • formula
    • integer vector
    • logical vector
  • j for selecting columns
    • formula
    • character vector
    • integer vector

You can use any combinations of the reference methods for i and j.

Transcript

This creates ft, the table object we build on for most of the rest of the lecture. Four columns, ten rows, no formatting yet. Worth pausing on the fact that it is stored in a variable at all. A flextable is just an object, so you can build it once and pipe it into different formatting experiments without rebuilding it each time. Every example from here starts from ft and adds one thing, which makes it easy to see what each function actually did. Run it and look at the plain version, so you have a baseline to compare against. The pipe sends tab data into flextable, and col keys keeps country name, region, y underscore nineteen ninety-five and y underscore two thousand five in that order. The assignment itself does not print the object, so the right-hand chunk evaluates ft on its own. Echo false hides that one-line printing command and leaves only the baseline table visible. Keeping the setup on the left and the result on the right lets you connect the object-building code to the object you will format in the following tabs.

We will be building on ft created below:

ft <-
  tab_data %>%
  flextable(
    col_keys =
      c(
        "country_name",
        "region",
        "y_1995",
        "y_2005"
      )
  )

country_name

region

y_1995

y_2005

Australia

Australasia

18,004,882

20,176,844

New Zealand

Australasia

3,673,400

4,133,900

Papua New Guinea

Melanesia

4,616,439

6,498,818

Solomon Islands

Melanesia

375,189

482,486

Vanuatu

Melanesia

170,612

217,632

New Caledonia

Melanesia

193,816

232,250

French Polynesia

Polynesia

231,446

271,060

Samoa

Polynesia

174,902

188,626

Tonga

Polynesia

99,977

105,633

Tuvalu

Polynesia

9,585

9,912

Transcript

The formula form, and it is the one worth defaulting to. For rows you write a tilde and then a condition using the column names directly, so tilde y two thousand five greater than two hundred thousand selects exactly the rows where that holds. For columns you write a tilde and then the column names joined with plus signs. That plus is not addition, it is just formula syntax for listing several things. The appeal is that the selection describes itself. Somebody reading the code later sees which rows and why, rather than numbers they have to work out. The generic syntax at the top separates i, the row condition, from j, the column list. In the concrete call, two e five is scientific notation for two hundred thousand. Color then makes the country name and region text red only in rows above that population threshold. Eval false keeps the left chunk as the readable recipe, while echo false hides the duplicate code on the right and shows the formatted table. Use the output to verify both dimensions of the selection: only qualifying rows change, and only those two named columns turn red.

Syntax

function(
  i = ~ condition based on variables,
  j = ~ variable 1 + variable 2 + ...,
  .
)


Example

ft %>%
  color(
    i = ~ y_2005 > 2e5,
    j = ~ country_name + region,
    color = "red"
  )

country_name

region

y_1995

y_2005

Australia

Australasia

18,004,882

20,176,844

New Zealand

Australasia

3,673,400

4,133,900

Papua New Guinea

Melanesia

4,616,439

6,498,818

Solomon Islands

Melanesia

375,189

482,486

Vanuatu

Melanesia

170,612

217,632

New Caledonia

Melanesia

193,816

232,250

French Polynesia

Polynesia

231,446

271,060

Samoa

Polynesia

174,902

188,626

Tonga

Polynesia

99,977

105,633

Tuvalu

Polynesia

9,585

9,912

Transcript

The same job with plain numbers and plain names. Row numbers as a vector, column names as strings. This works, and sometimes it is the clearest thing to write, particularly when you genuinely do mean the fourth row rather than a row satisfying some condition. The note at the top prefers formulas for columns, and its reason is mostly typing, since a formula avoids the quotes. But there is a stronger argument it does not make. Hard-coded row numbers break silently when your data changes. A formula that says which rows you meant keeps working. In this example, c of two comma four colon nine selects row two and the continuous range from row four through row nine. The character vector selects country name and y underscore nineteen ninety-five, and color makes the text in that rectangular selection red. The left chunk is marked eval false so you can study the call, and the right one uses echo false so the formatted result occupies the output side. Check that row three and row ten stay unchanged. That is the easiest visual confirmation that the integer selector did exactly what the code says.

Using a character vector for j is not recommended because using a formula involves less typing.

ft %>%
  color(
    i = c(2, 4:9),
    j = c("country_name", "y_1995"),
    color = "red"
  )

country_name

region

y_1995

y_2005

Australia

Australasia

18,004,882

20,176,844

New Zealand

Australasia

3,673,400

4,133,900

Papua New Guinea

Melanesia

4,616,439

6,498,818

Solomon Islands

Melanesia

375,189

482,486

Vanuatu

Melanesia

170,612

217,632

New Caledonia

Melanesia

193,816

232,250

French Polynesia

Polynesia

231,446

271,060

Samoa

Polynesia

174,902

188,626

Tonga

Polynesia

99,977

105,633

Tuvalu

Polynesia

9,585

9,912

Transcript

And the third form: a logical vector for rows, column numbers for columns. The logical vector has to be exactly as long as the table has rows, which is why the example builds ten TRUEs and FALSEs for a ten-row table. Get that length wrong and you get an error. This form is most useful when you have computed the condition somewhere else and are carrying it around as a variable. If you are writing the condition inline, the formula version reads better. Rep of true comma false, each equals five produces five TRUE values followed by five FALSE values. That selects the first five body rows. The column vector c of one comma three selects the first and third columns, and color makes their selected text red. The left code is not evaluated on the slide, while the right copy hides its source and shows the result. Look for red only in the upper half of country name and y underscore nineteen ninety-five. This tab completes the selector combinations before we add the part of the table as another dimension.

ft %>%
  color(
    i = rep(c(TRUE, FALSE), each = 5),
    j = c(1, 3),
    color = "red"
  )

country_name

region

y_1995

y_2005

Australia

Australasia

18,004,882

20,176,844

New Zealand

Australasia

3,673,400

4,133,900

Papua New Guinea

Melanesia

4,616,439

6,498,818

Solomon Islands

Melanesia

375,189

482,486

Vanuatu

Melanesia

170,612

217,632

New Caledonia

Melanesia

193,816

232,250

French Polynesia

Polynesia

231,446

271,060

Samoa

Polynesia

174,902

188,626

Tonga

Polynesia

99,977

105,633

Tuvalu

Polynesia

9,585

9,912

Transcript

A table is not one thing, it is three: a header, a body and a footer. The part argument says which you are formatting, and forgetting it is the single most common reason a formatting call appears to do nothing at all. Note that all really does mean all, footer included; this slide previously said otherwise. Then read the last line carefully, because it is a genuine trap. Different functions default to different parts. So when a change does not appear where you expected it, check the default before concluding the function is broken. The four choices on screen are header for column labels, body for data cells, footer for any rows added below, and all for every one of those parts. In the example, tab data first becomes a four-column flextable using the familiar col keys. Color then sets part equal to header and color equal to red, so only the label text changes. The left chunk shows the unevaluated recipe and the right chunk suppresses the repeated code while displaying its output. Compare the red header with the unchanged body to see that i and j locate rows and columns within the part that you choose.

You can refer to parts of the table using part = option. The available options are

  • header: the header part of the table
  • footer: the footer part of the table
  • body: the body part of the table
  • all: every part of the table – body, header and footer


tab_data %>%
  flextable(
    col_keys = c("country_name", "region", "y_1995", "y_2005")
  ) %>%
  color(
    part = "header",
    color = "red"
  )

country_name

region

y_1995

y_2005

Australia

Australasia

18,004,882

20,176,844

New Zealand

Australasia

3,673,400

4,133,900

Papua New Guinea

Melanesia

4,616,439

6,498,818

Solomon Islands

Melanesia

375,189

482,486

Vanuatu

Melanesia

170,612

217,632

New Caledonia

Melanesia

193,816

232,250

French Polynesia

Polynesia

231,446

271,060

Samoa

Polynesia

174,902

188,626

Tonga

Polynesia

99,977

105,633

Tuvalu

Polynesia

9,585

9,912

Different functions have different default values for part.

Style

Transcript

The style function is the general-purpose way to format a table, and its structure tells you how flextable thinks. You select where with i, j and part, then say what to change using one of three property arguments. pr underscore t for text, pr underscore p for paragraphs, pr underscore c for cells. Each takes a matching function from officer: fp underscore text, fp underscore par, fp underscore cell. The pr stands for property. Hold on to that pairing and the next several tabs are simply working through what each of the three can control. In the syntax, x is the flextable entering the function. The defaults of NULL for i and j mean no narrower row or column selection, and the NULL property defaults mean that property layer is left alone. Part defaults to body, so an otherwise unqualified style call formats data cells rather than the header. The three property objects can be supplied together in one call, which is useful when the same selection needs coordinated text, paragraph and cell formatting. The next tabs separate them so you can see which layer owns each effect.

You can use the style() function to change the style and format of a table.

Syntax

style(
  x,
  i = NULL,
  j = NULL,
  pr_t = NULL,
  pr_p = NULL,
  pr_c = NULL,
  part = "body"
)

We can use fp_*() functions from the officer package to specify the style of texts, paragraphs, and cells.

  • pr_t = fp_text(): format texts
  • pr_p = fp_par(): format paragraphs
  • pr_c = fp_cell(): format cells

(pr in pr_* = stands for property.)

Transcript

The first of the three, and the one you will use most. fp underscore text controls anything about the characters themselves: colour, size, bold, italic, underline, the font. The nested Introduction tab points you at the help page rather than listing every option, which is the right instinct, because there are a lot of them and you will look them up every time regardless. Then the example applies red, bold and underlined to three rows of one column at once. Notice that where and what stay separate, which is exactly the separation the selector tabs set up. The live help cell runs question mark fp underscore text so you can inspect the current package documentation. In Example, i equals four colon six selects body rows four through six, and j equals tilde country underscore name limits the change to that column. Pr underscore t receives the fp text object whose color is red, bold is TRUE and underlined is TRUE. The code-only left chunk uses eval false, and the result-only right chunk uses echo false. Compare the output with ft and you will see that all three character properties land on the same selected text without changing its cell or paragraph.

fp_text() lets you update the appearance of texts, including color, font size, bold or not, etc (see the help page below for the complete list of options).


Syntax

ft %>%
  style(
    i = 4:6,
    j = ~country_name,
    pr_t =
      fp_text(
        color = "red",
        bold = TRUE,
        underlined = TRUE
      )
  )

country_name

region

y_1995

y_2005

Australia

Australasia

18,004,882

20,176,844

New Zealand

Australasia

3,673,400

4,133,900

Papua New Guinea

Melanesia

4,616,439

6,498,818

Solomon Islands

Melanesia

375,189

482,486

Vanuatu

Melanesia

170,612

217,632

New Caledonia

Melanesia

193,816

232,250

French Polynesia

Polynesia

231,446

271,060

Samoa

Polynesia

174,902

188,626

Tonga

Polynesia

99,977

105,633

Tuvalu

Polynesia

9,585

9,912

Transcript

This distinction confuses everybody at first, so look at what the example draws. Inside every cell there is a paragraph, and inside the paragraph there is text. Three nested boxes. So a bottom border on the paragraph and a bottom border on the cell are different lines in different places, which is precisely what the blue and red borders show you. As a rule of thumb: if you are positioning text within its box, that is the paragraph. If you are changing the box itself, its background or its borders, that is the cell. The style call supplies both property objects and leaves i and j unspecified, so the default body part is formatted throughout. Pr underscore p receives an fp par with a two-unit blue bottom border, while pr underscore c receives an fp cell with a two-unit red bottom border. Each border is itself described by fp underscore border. Eval false keeps the full nested construction visible on the left, and echo false lets the right side concentrate on the result. The separation between the two colored lines is the visual evidence that paragraph and cell borders belong to different rectangles.

  • paragraphs: rectangular boxes around the texts inside the cells
  • cells: rectangular boxes that contain paragraphs and texts inside
ft %>%
  style(
    pr_p = fp_par(
      border.bottom = fp_border(width = 2, color = "blue")
    ),
    pr_c = fp_cell(
      border.bottom = fp_border(width = 2, color = "red")
    )
  )

country_name

region

y_1995

y_2005

Australia

Australasia

18,004,882

20,176,844

New Zealand

Australasia

3,673,400

4,133,900

Papua New Guinea

Melanesia

4,616,439

6,498,818

Solomon Islands

Melanesia

375,189

482,486

Vanuatu

Melanesia

170,612

217,632

New Caledonia

Melanesia

193,816

232,250

French Polynesia

Polynesia

231,446

271,060

Samoa

Polynesia

174,902

188,626

Tonga

Polynesia

99,977

105,633

Tuvalu

Polynesia

9,585

9,912

Transcript

The paragraph properties. This is where text alignment lives, along with shading, paragraph-level borders and spacing. The example sets alignment to left and adds grey shading to three cells in one column. Worth noting that alignment is a paragraph property rather than a text property, which is not obvious until you think about the nesting from the previous tab. Alignment is about where text sits inside its box, so it belongs to the box immediately containing it, and that is the paragraph. If you go looking for alignment in fp underscore text, you will not find it. Use the live help cell, which runs question mark fp underscore par, when you need the complete argument list. In Example, i equals four colon six chooses three body rows and j equals tilde country underscore name chooses one column. The fp par object sets text dot align to left and shading dot color to grey, and pr underscore p hands that paragraph description to style. The left side is an unevaluated code example; the right hides the same code and shows the selected paragraphs. Their text moves left and their paragraph shading changes, while the rest of the table remains the baseline.

fp_par() lets you update the appearance of paragraphs (see the help page below for the complete list of options).


Syntax

ft %>%
  style(
    i = 4:6,
    j = ~country_name,
    pr_p = fp_par(
      text.align = "left",
      shading.color = "grey"
    )
  )

country_name

region

y_1995

y_2005

Australia

Australasia

18,004,882

20,176,844

New Zealand

Australasia

3,673,400

4,133,900

Papua New Guinea

Melanesia

4,616,439

6,498,818

Solomon Islands

Melanesia

375,189

482,486

Vanuatu

Melanesia

170,612

217,632

New Caledonia

Melanesia

193,816

232,250

French Polynesia

Polynesia

231,446

271,060

Samoa

Polynesia

174,902

188,626

Tonga

Polynesia

99,977

105,633

Tuvalu

Polynesia

9,585

9,912

Transcript

The third of the three, controlling the cell itself: background colour, margins, vertical alignment, and cell borders. The example sets three of those at once on a small selection. Note that background colour lives here even though shading appeared under paragraphs, which is the sort of overlap that sends you to the help page. In practice you will rarely write the full style call with fp underscore cell, because the convenience functions on the next slide do the common jobs in a single line. Learn this one so you understand what those shortcuts are doing underneath. The Introduction help cell runs question mark fp underscore cell. In Example, i equals four colon six and j equals tilde country underscore name select the same three cells used in the preceding tab. Pr underscore c takes an fp cell object with margin equal to two, vertical dot align equal to top and background dot color equal to red. The left chunk preserves that recipe without evaluating it, and the right chunk hides the duplicate source while showing the formatted cells. This makes the contrast with fp par direct: the selection is unchanged, but the property layer is now the outer cell box.

fp_cell() lets you update the appearance of cells (see the help page below for the complete list of options).


Syntax

ft %>%
  style(
    i = 4:6,
    j = ~country_name,
    pr_c = fp_cell(
      margin = 2,
      vertical.align = "top",
      background.color = "red"
    )
  )

country_name

region

y_1995

y_2005

Australia

Australasia

18,004,882

20,176,844

New Zealand

Australasia

3,673,400

4,133,900

Papua New Guinea

Melanesia

4,616,439

6,498,818

Solomon Islands

Melanesia

375,189

482,486

Vanuatu

Melanesia

170,612

217,632

New Caledonia

Melanesia

193,816

232,250

French Polynesia

Polynesia

231,446

271,060

Samoa

Polynesia

174,902

188,626

Tonga

Polynesia

99,977

105,633

Tuvalu

Polynesia

9,585

9,912

Formatting: convenience functions

Transcript

Everything you have just learned with style and the fp functions has a shortcut. Rather than building a property object, you call a function named after the thing you want: bg for background, color for text colour, bold, italic, fontsize, align, and so on. The full list is on screen. They all take the same i, j and part selectors, so there is nothing new to learn about where. This is what you will actually write day to day. The style route matters when you want several properties at once, or when no convenience function exists for what you need. Read the list by task. Align sets alignment for a selection, while align text col and align nottext col quickly apply the conventional left alignment for text columns and right alignment for nontext columns. Bg changes the cell background. Font chooses a font family, fontsize changes its size, italic and bold switch those faces on or off, and color changes the characters. Padding controls the space around paragraph content, valign moves content vertically within cells, and rotate changes text direction. Empty blanks collapses deliberately blank spacer columns and makes them transparent. Each shortcut still returns a flextable, which is why you can pipe several of them together in the next tab.

  • Instead of using the style() function in combination with fp_*() functions, you can easily work on a specific aesthetic feature using convenience functions like below:
    • align(), align_text_col(), align_nottext_col(): Set text alignment
    • bg(): Set background color
    • font(): Set font
    • fontsize(): Set font size
    • italic(): Set italic font
    • bold(): Set bold font
    • color(): Set font color
    • padding(): Set paragraph paddings
    • valign(): Set vertical alignment
    • rotate(): rotate cell text
    • empty_blanks(): make blank columns as transparent
  • You can use the selector syntax to specify where the specified effects take place
Transcript

Three convenience functions chained together, and this is what real formatting code looks like. One call colours a single cell, one shades a column conditionally on a value, one bumps the font size of a row. Read them and notice each specifies its own where. That is the pattern: a pipeline of small independent instructions, each saying which cells it applies to. And because they are just functions in a pipe, you can comment one out to see what it was doing, which is much the easiest way to debug a table that has come out looking wrong. The first call uses i equal to one and j equal to two, so only the second cell of the first body row gets the gold text color hash f c b a zero three. Because that color is the unnamed third argument, it fills the function’s color parameter. The bg call selects rows where y underscore two thousand five is below two hundred thousand, limits the change to region, and fills those cells grey. Fontsize selects row seven and, because no j is supplied, applies size sixteen across all its columns. Eval false leaves the pipeline visible on the left; echo false hides the repeated source on the right. Use the output to trace each independent change back to its selector.

ft %>%
  color(
    i = 1,
    j = 2,
    "#fcba03"
  ) %>%
  bg(
    i = ~ y_2005 < 2e5,
    j = c("region"),
    bg = "grey"
  ) %>%
  fontsize(
    i = 7,
    size = 16
  )

country_name

region

y_1995

y_2005

Australia

Australasia

18,004,882

20,176,844

New Zealand

Australasia

3,673,400

4,133,900

Papua New Guinea

Melanesia

4,616,439

6,498,818

Solomon Islands

Melanesia

375,189

482,486

Vanuatu

Melanesia

170,612

217,632

New Caledonia

Melanesia

193,816

232,250

French Polynesia

Polynesia

231,446

271,060

Samoa

Polynesia

174,902

188,626

Tonga

Polynesia

99,977

105,633

Tuvalu

Polynesia

9,585

9,912

Demonstration: Formatting

tab_data
# A tibble: 10 × 7
   country_name     region        y_1995   y_2005   y_2015 pop_ratio_05_15 date 
   <chr>            <chr>          <int>    <int>    <int>           <dbl> <chr>
 1 Australia        Australasia 18004882 20176844 23815995            1.18 2013…
 2 New Zealand      Australasia  3673400  4133900  4609400            1.12 2013…
 3 Papua New Guinea Melanesia    4616439  6498818  8682174            1.34 2013…
 4 Solomon Islands  Melanesia     375189   482486   612660            1.27 2013…
 5 Vanuatu          Melanesia     170612   217632   276438            1.27 2013…
 6 New Caledonia    Melanesia     193816   232250   269460            1.16 2013…
 7 French Polynesia Polynesia     231446   271060   291787            1.08 2013…
 8 Samoa            Polynesia     174902   188626   203571            1.08 2013…
 9 Tonga            Polynesia      99977   105633   106122            1.00 2013…
10 Tuvalu           Polynesia       9585     9912    10877            1.10 2013…

Demonstration: Formatting

tab_data %>%
  flextable(
    col_keys = c("country_name", "region", "y_1995", "y_2005")
  )

country_name

region

y_1995

y_2005

Australia

Australasia

18,004,882

20,176,844

New Zealand

Australasia

3,673,400

4,133,900

Papua New Guinea

Melanesia

4,616,439

6,498,818

Solomon Islands

Melanesia

375,189

482,486

Vanuatu

Melanesia

170,612

217,632

New Caledonia

Melanesia

193,816

232,250

French Polynesia

Polynesia

231,446

271,060

Samoa

Polynesia

174,902

188,626

Tonga

Polynesia

99,977

105,633

Tuvalu

Polynesia

9,585

9,912

Demonstration: Formatting

tab_data %>%
  flextable(
    col_keys = c("country_name", "region", "y_1995", "y_2005")
  ) %>%
#--- text color ---#
  color(i = 1, j = 2, "#fcba03")

country_name

region

y_1995

y_2005

Australia

Australasia

18,004,882

20,176,844

New Zealand

Australasia

3,673,400

4,133,900

Papua New Guinea

Melanesia

4,616,439

6,498,818

Solomon Islands

Melanesia

375,189

482,486

Vanuatu

Melanesia

170,612

217,632

New Caledonia

Melanesia

193,816

232,250

French Polynesia

Polynesia

231,446

271,060

Samoa

Polynesia

174,902

188,626

Tonga

Polynesia

99,977

105,633

Tuvalu

Polynesia

9,585

9,912

Demonstration: Formatting

tab_data %>%
  flextable(
    col_keys = c("country_name", "region", "y_1995", "y_2005")
  ) %>%
#--- text color ---#
  color(i = 1, j = 2, "#fcba03") %>%
#--- background ---#
  bg(i = ~ y_2005 < 2e5, j = c("region"), bg = "grey")

country_name

region

y_1995

y_2005

Australia

Australasia

18,004,882

20,176,844

New Zealand

Australasia

3,673,400

4,133,900

Papua New Guinea

Melanesia

4,616,439

6,498,818

Solomon Islands

Melanesia

375,189

482,486

Vanuatu

Melanesia

170,612

217,632

New Caledonia

Melanesia

193,816

232,250

French Polynesia

Polynesia

231,446

271,060

Samoa

Polynesia

174,902

188,626

Tonga

Polynesia

99,977

105,633

Tuvalu

Polynesia

9,585

9,912

Demonstration: Formatting

tab_data %>%
  flextable(
    col_keys = c("country_name", "region", "y_1995", "y_2005")
  ) %>%
#--- text color ---#
  color(i = 1, j = 2, "#fcba03") %>%
#--- background ---#
  bg(i = ~ y_2005 < 2e5, j = c("region"), bg = "grey") %>%
#--- font type ---#
  font(i = 5, j = ~ country_name + y_2005, fontname = "Times")

country_name

region

y_1995

y_2005

Australia

Australasia

18,004,882

20,176,844

New Zealand

Australasia

3,673,400

4,133,900

Papua New Guinea

Melanesia

4,616,439

6,498,818

Solomon Islands

Melanesia

375,189

482,486

Vanuatu

Melanesia

170,612

217,632

New Caledonia

Melanesia

193,816

232,250

French Polynesia

Polynesia

231,446

271,060

Samoa

Polynesia

174,902

188,626

Tonga

Polynesia

99,977

105,633

Tuvalu

Polynesia

9,585

9,912

Demonstration: Formatting

tab_data %>%
  flextable(
    col_keys = c("country_name", "region", "y_1995", "y_2005")
  ) %>%
#--- text color ---#
  color(i = 1, j = 2, "#fcba03") %>%
#--- background ---#
  bg(i = ~ y_2005 < 2e5, j = c("region"), bg = "grey") %>%
#--- font type ---#
  font(i = 5, j = ~ country_name + y_2005, fontname = "Times") %>%
#--- font size ---#
  fontsize(i = 7, size = 16)

country_name

region

y_1995

y_2005

Australia

Australasia

18,004,882

20,176,844

New Zealand

Australasia

3,673,400

4,133,900

Papua New Guinea

Melanesia

4,616,439

6,498,818

Solomon Islands

Melanesia

375,189

482,486

Vanuatu

Melanesia

170,612

217,632

New Caledonia

Melanesia

193,816

232,250

French Polynesia

Polynesia

231,446

271,060

Samoa

Polynesia

174,902

188,626

Tonga

Polynesia

99,977

105,633

Tuvalu

Polynesia

9,585

9,912

Demonstration: Formatting

tab_data %>%
  flextable(
    col_keys = c("country_name", "region", "y_1995", "y_2005")
  ) %>%
#--- text color ---#
  color(i = 1, j = 2, "#fcba03") %>%
#--- background ---#
  bg(i = ~ y_2005 < 2e5, j = c("region"), bg = "grey") %>%
#--- font type ---#
  font(i = 5, j = ~ country_name + y_2005, fontname = "Times") %>%
#--- font size ---#
  fontsize(i = 7, size = 16) %>%
#--- italicize ---#
  italic(j = 2)

country_name

region

y_1995

y_2005

Australia

Australasia

18,004,882

20,176,844

New Zealand

Australasia

3,673,400

4,133,900

Papua New Guinea

Melanesia

4,616,439

6,498,818

Solomon Islands

Melanesia

375,189

482,486

Vanuatu

Melanesia

170,612

217,632

New Caledonia

Melanesia

193,816

232,250

French Polynesia

Polynesia

231,446

271,060

Samoa

Polynesia

174,902

188,626

Tonga

Polynesia

99,977

105,633

Tuvalu

Polynesia

9,585

9,912

Demonstration: Formatting

tab_data %>%
  flextable(
    col_keys = c("country_name", "region", "y_1995", "y_2005")
  ) %>%
#--- text color ---#
  color(i = 1, j = 2, "#fcba03") %>%
#--- background ---#
  bg(i = ~ y_2005 < 2e5, j = c("region"), bg = "grey") %>%
#--- font type ---#
  font(i = 5, j = ~ country_name + y_2005, fontname = "Times") %>%
#--- font size ---#
  fontsize(i = 7, size = 16) %>%
#--- italicize ---#
  italic(j = 2) %>%
#--- bold ---#
  bold(j = 4)

country_name

region

y_1995

y_2005

Australia

Australasia

18,004,882

20,176,844

New Zealand

Australasia

3,673,400

4,133,900

Papua New Guinea

Melanesia

4,616,439

6,498,818

Solomon Islands

Melanesia

375,189

482,486

Vanuatu

Melanesia

170,612

217,632

New Caledonia

Melanesia

193,816

232,250

French Polynesia

Polynesia

231,446

271,060

Samoa

Polynesia

174,902

188,626

Tonga

Polynesia

99,977

105,633

Tuvalu

Polynesia

9,585

9,912

Demonstration: Formatting

tab_data %>%
  flextable(
    col_keys = c("country_name", "region", "y_1995", "y_2005")
  ) %>%
#--- text color ---#
  color(i = 1, j = 2, "#fcba03") %>%
#--- background ---#
  bg(i = ~ y_2005 < 2e5, j = c("region"), bg = "grey") %>%
#--- font type ---#
  font(i = 5, j = ~ country_name + y_2005, fontname = "Times") %>%
#--- font size ---#
  fontsize(i = 7, size = 16) %>%
#--- italicize ---#
  italic(j = 2) %>%
#--- bold ---#
  bold(j = 4) %>%
#--- vertical text alignment ---#
  valign(i = ~ region == "Australasia", j = 4, valign = "top")

country_name

region

y_1995

y_2005

Australia

Australasia

18,004,882

20,176,844

New Zealand

Australasia

3,673,400

4,133,900

Papua New Guinea

Melanesia

4,616,439

6,498,818

Solomon Islands

Melanesia

375,189

482,486

Vanuatu

Melanesia

170,612

217,632

New Caledonia

Melanesia

193,816

232,250

French Polynesia

Polynesia

231,446

271,060

Samoa

Polynesia

174,902

188,626

Tonga

Polynesia

99,977

105,633

Tuvalu

Polynesia

9,585

9,912

Demonstration: Formatting

tab_data %>%
  flextable(
    col_keys = c("country_name", "region", "y_1995", "y_2005")
  ) %>%
#--- text color ---#
  color(i = 1, j = 2, "#fcba03") %>%
#--- background ---#
  bg(i = ~ y_2005 < 2e5, j = c("region"), bg = "grey") %>%
#--- font type ---#
  font(i = 5, j = ~ country_name + y_2005, fontname = "Times") %>%
#--- font size ---#
  fontsize(i = 7, size = 16) %>%
#--- italicize ---#
  italic(j = 2) %>%
#--- bold ---#
  bold(j = 4) %>%
#--- vertical text alignment ---#
  valign(i = ~ region == "Australasia", j = 4, valign = "top") %>%
#--- text direction ---#
  rotate(i = 1, j = 2, rotation = "tbrl")

country_name

region

y_1995

y_2005

Australia

Australasia

18,004,882

20,176,844

New Zealand

Australasia

3,673,400

4,133,900

Papua New Guinea

Melanesia

4,616,439

6,498,818

Solomon Islands

Melanesia

375,189

482,486

Vanuatu

Melanesia

170,612

217,632

New Caledonia

Melanesia

193,816

232,250

French Polynesia

Polynesia

231,446

271,060

Samoa

Polynesia

174,902

188,626

Tonga

Polynesia

99,977

105,633

Tuvalu

Polynesia

9,585

9,912

Borders: convenience functions

Transcript

Borders get their own family of functions, and the list looks longer than it is. There are really three groups. hline and vline draw lines wherever you select. The top, bottom, left and right variants are shortcuts for the edges. And the inner and outer functions treat the table as a whole. Then two odd ones worth remembering. border remove strips everything, which is often the right first step when you want full control. And fix border issues exists because merging cells can leave the borders in a mess, and this puts them right. More specifically, hline draws horizontal borders at selected body positions, with hline top and hline bottom targeting the table part’s outer horizontal edges. Vline draws vertical separators, and vline left and vline right target the corresponding vertical edges. Border can set the top, bottom, left and right sides of selected individual cells. Border inner applies both internal directions, while border inner h and border inner v let you choose only horizontal or only vertical internal lines. Border outer frames the selected table part. The following tabs show that all of these placement functions take a border description rather than forcing you to repeat line aesthetics in several arguments.

Here is a list of convenience functions that you can use to draw border lines on a table:

  • hline(): set horizontal borders
  • hline_bottom(): set bottom horizontal border
  • hline_top(): set top horizontal border
  • vline(): set vertical borders
  • vline_left(): set flextable left vertical borders
  • vline_right(): set flextable right vertical borders
  • border(): Set cell borders
  • border_inner(): set vertical & horizontal inner borders
  • border_inner_h(): set inner borders
  • border_inner_v(): set vertical inner borders
  • border_outer(): set outer borders
  • border_remove(): remove borders
  • fix_border_issues(): fix border issues when cell are merged
Transcript

Two things to combine here. The selector syntax you already know says where the border goes. Then the border argument, taking fp underscore border from officer, says what it looks like: colour, style, width. Note that fp underscore border is another officer function, like fp underscore text and fp underscore cell earlier. That is the consistent division across this package. flextable decides which cells, officer describes the appearance. Keep that split in mind and you will usually guess correctly which of the two packages a function you half remember belongs to. In the example, hline is the placement function. I equals three targets row three and j equals one colon three limits the line to the first three columns. Its border argument receives an fp border object with red color, dotted style and width four. The flextable object itself is omitted from this isolated syntax because, in a real pipeline, it arrives as the first argument from the pipe. The next tab puts ft in front of this same call and shows the result.

  • Use the selector syntax to specify where
  • Use the border = option along with fp_border() from the officer package to specify what kind of borders you would like to draw

Example

hline(
  i = 3,
  j = 1:3,
  border = fp_border(
    color = "red",
    style = "dotted",
    width = 4
  )
)
Transcript

The border description itself, and it takes only a few arguments: colour, style and width. Style is the one worth experimenting with, since dotted, dashed and solid change the character of a table quite a lot. The example draws a thick red dotted line under part of row three. Worth noticing that fp underscore border knows nothing about tables at all. It just describes a line, and flextable applies it wherever you selected. That is why the same border object can be handed to hline, to vline, or to the border function for individual cells.

fp_border() lets you specify the aesthetics of the borders you are drawing.


Syntax

ft %>%
  hline(
    i = 3,
    j = 1:3,
    border = fp_border(
      color = "red",
      style = "dotted",
      width = 4
    )
  )

country_name

region

y_1995

y_2005

Australia

Australasia

18,004,882

20,176,844

New Zealand

Australasia

3,673,400

4,133,900

Papua New Guinea

Melanesia

4,616,439

6,498,818

Solomon Islands

Melanesia

375,189

482,486

Vanuatu

Melanesia

170,612

217,632

New Caledonia

Melanesia

193,816

232,250

French Polynesia

Polynesia

231,446

271,060

Samoa

Polynesia

174,902

188,626

Tonga

Polynesia

99,977

105,633

Tuvalu

Polynesia

9,585

9,912

Demonstration: Borders

tab_data
# A tibble: 10 × 7
   country_name     region        y_1995   y_2005   y_2015 pop_ratio_05_15 date 
   <chr>            <chr>          <int>    <int>    <int>           <dbl> <chr>
 1 Australia        Australasia 18004882 20176844 23815995            1.18 2013…
 2 New Zealand      Australasia  3673400  4133900  4609400            1.12 2013…
 3 Papua New Guinea Melanesia    4616439  6498818  8682174            1.34 2013…
 4 Solomon Islands  Melanesia     375189   482486   612660            1.27 2013…
 5 Vanuatu          Melanesia     170612   217632   276438            1.27 2013…
 6 New Caledonia    Melanesia     193816   232250   269460            1.16 2013…
 7 French Polynesia Polynesia     231446   271060   291787            1.08 2013…
 8 Samoa            Polynesia     174902   188626   203571            1.08 2013…
 9 Tonga            Polynesia      99977   105633   106122            1.00 2013…
10 Tuvalu           Polynesia       9585     9912    10877            1.10 2013…

Demonstration: Borders

tab_data %>%
  flextable(
    col_keys = c("country_name", "region", "y_1995", "y_2005")
  )

country_name

region

y_1995

y_2005

Australia

Australasia

18,004,882

20,176,844

New Zealand

Australasia

3,673,400

4,133,900

Papua New Guinea

Melanesia

4,616,439

6,498,818

Solomon Islands

Melanesia

375,189

482,486

Vanuatu

Melanesia

170,612

217,632

New Caledonia

Melanesia

193,816

232,250

French Polynesia

Polynesia

231,446

271,060

Samoa

Polynesia

174,902

188,626

Tonga

Polynesia

99,977

105,633

Tuvalu

Polynesia

9,585

9,912

Demonstration: Borders

tab_data %>%
  flextable(
    col_keys = c("country_name", "region", "y_1995", "y_2005")
  ) %>%
#--- remove all borders ---#
  border_remove()

country_name

region

y_1995

y_2005

Australia

Australasia

18,004,882

20,176,844

New Zealand

Australasia

3,673,400

4,133,900

Papua New Guinea

Melanesia

4,616,439

6,498,818

Solomon Islands

Melanesia

375,189

482,486

Vanuatu

Melanesia

170,612

217,632

New Caledonia

Melanesia

193,816

232,250

French Polynesia

Polynesia

231,446

271,060

Samoa

Polynesia

174,902

188,626

Tonga

Polynesia

99,977

105,633

Tuvalu

Polynesia

9,585

9,912

Demonstration: Borders

tab_data %>%
  flextable(
    col_keys = c("country_name", "region", "y_1995", "y_2005")
  ) %>%
#--- remove all borders ---#
  border_remove() %>%
#--- horizontal lines ---#
  hline(i = 3, j = 1:3, border = fp_border(color = "red"))

country_name

region

y_1995

y_2005

Australia

Australasia

18,004,882

20,176,844

New Zealand

Australasia

3,673,400

4,133,900

Papua New Guinea

Melanesia

4,616,439

6,498,818

Solomon Islands

Melanesia

375,189

482,486

Vanuatu

Melanesia

170,612

217,632

New Caledonia

Melanesia

193,816

232,250

French Polynesia

Polynesia

231,446

271,060

Samoa

Polynesia

174,902

188,626

Tonga

Polynesia

99,977

105,633

Tuvalu

Polynesia

9,585

9,912

Demonstration: Borders

tab_data %>%
  flextable(
    col_keys = c("country_name", "region", "y_1995", "y_2005")
  ) %>%
#--- remove all borders ---#
  border_remove() %>%
#--- horizontal lines ---#
  hline(i = 3, j = 1:3, border = fp_border(color = "red")) %>%
#--- horizontal line at the bottom ---#
  hline_bottom(j = 3:4, border = fp_border(color = "green"))

country_name

region

y_1995

y_2005

Australia

Australasia

18,004,882

20,176,844

New Zealand

Australasia

3,673,400

4,133,900

Papua New Guinea

Melanesia

4,616,439

6,498,818

Solomon Islands

Melanesia

375,189

482,486

Vanuatu

Melanesia

170,612

217,632

New Caledonia

Melanesia

193,816

232,250

French Polynesia

Polynesia

231,446

271,060

Samoa

Polynesia

174,902

188,626

Tonga

Polynesia

99,977

105,633

Tuvalu

Polynesia

9,585

9,912

Demonstration: Borders

tab_data %>%
  flextable(
    col_keys = c("country_name", "region", "y_1995", "y_2005")
  ) %>%
#--- remove all borders ---#
  border_remove() %>%
#--- horizontal lines ---#
  hline(i = 3, j = 1:3, border = fp_border(color = "red")) %>%
#--- horizontal line at the bottom ---#
  hline_bottom(j = 3:4, border = fp_border(color = "green")) %>%
#--- horizontal line at the top ---#
  hline_top(j = 1:3, border = fp_border(color = "orange"))

country_name

region

y_1995

y_2005

Australia

Australasia

18,004,882

20,176,844

New Zealand

Australasia

3,673,400

4,133,900

Papua New Guinea

Melanesia

4,616,439

6,498,818

Solomon Islands

Melanesia

375,189

482,486

Vanuatu

Melanesia

170,612

217,632

New Caledonia

Melanesia

193,816

232,250

French Polynesia

Polynesia

231,446

271,060

Samoa

Polynesia

174,902

188,626

Tonga

Polynesia

99,977

105,633

Tuvalu

Polynesia

9,585

9,912

Demonstration: Borders

tab_data %>%
  flextable(
    col_keys = c("country_name", "region", "y_1995", "y_2005")
  ) %>%
#--- remove all borders ---#
  border_remove() %>%
#--- horizontal lines ---#
  hline(i = 3, j = 1:3, border = fp_border(color = "red")) %>%
#--- horizontal line at the bottom ---#
  hline_bottom(j = 3:4, border = fp_border(color = "green")) %>%
#--- horizontal line at the top ---#
  hline_top(j = 1:3, border = fp_border(color = "orange")) %>%
#--- vertical lines ---#
  vline(border = fp_border(color = "orange"))

country_name

region

y_1995

y_2005

Australia

Australasia

18,004,882

20,176,844

New Zealand

Australasia

3,673,400

4,133,900

Papua New Guinea

Melanesia

4,616,439

6,498,818

Solomon Islands

Melanesia

375,189

482,486

Vanuatu

Melanesia

170,612

217,632

New Caledonia

Melanesia

193,816

232,250

French Polynesia

Polynesia

231,446

271,060

Samoa

Polynesia

174,902

188,626

Tonga

Polynesia

99,977

105,633

Tuvalu

Polynesia

9,585

9,912

Demonstration: Borders

tab_data %>%
  flextable(
    col_keys = c("country_name", "region", "y_1995", "y_2005")
  ) %>%
#--- remove all borders ---#
  border_remove() %>%
#--- horizontal lines ---#
  hline(i = 3, j = 1:3, border = fp_border(color = "red")) %>%
#--- horizontal line at the bottom ---#
  hline_bottom(j = 3:4, border = fp_border(color = "green")) %>%
#--- horizontal line at the top ---#
  hline_top(j = 1:3, border = fp_border(color = "orange")) %>%
#--- vertical lines ---#
  vline(border = fp_border(color = "orange")) %>%
#--- vertical on the left edge  ---#
  vline_left(border = fp_border(color = "grey", width = 2))

country_name

region

y_1995

y_2005

Australia

Australasia

18,004,882

20,176,844

New Zealand

Australasia

3,673,400

4,133,900

Papua New Guinea

Melanesia

4,616,439

6,498,818

Solomon Islands

Melanesia

375,189

482,486

Vanuatu

Melanesia

170,612

217,632

New Caledonia

Melanesia

193,816

232,250

French Polynesia

Polynesia

231,446

271,060

Samoa

Polynesia

174,902

188,626

Tonga

Polynesia

99,977

105,633

Tuvalu

Polynesia

9,585

9,912

Demonstration: Borders

tab_data %>%
  flextable(
    col_keys = c("country_name", "region", "y_1995", "y_2005")
  ) %>%
#--- remove all borders ---#
  border_remove() %>%
#--- horizontal lines ---#
  hline(i = 3, j = 1:3, border = fp_border(color = "red")) %>%
#--- horizontal line at the bottom ---#
  hline_bottom(j = 3:4, border = fp_border(color = "green")) %>%
#--- horizontal line at the top ---#
  hline_top(j = 1:3, border = fp_border(color = "orange")) %>%
#--- vertical lines ---#
  vline(border = fp_border(color = "orange")) %>%
#--- vertical on the left edge  ---#
  vline_left(border = fp_border(color = "grey", width = 2)) %>%
#--- vertical on the right edge  ---#
  vline_right(border = fp_border(color = "red", width = 2))

country_name

region

y_1995

y_2005

Australia

Australasia

18,004,882

20,176,844

New Zealand

Australasia

3,673,400

4,133,900

Papua New Guinea

Melanesia

4,616,439

6,498,818

Solomon Islands

Melanesia

375,189

482,486

Vanuatu

Melanesia

170,612

217,632

New Caledonia

Melanesia

193,816

232,250

French Polynesia

Polynesia

231,446

271,060

Samoa

Polynesia

174,902

188,626

Tonga

Polynesia

99,977

105,633

Tuvalu

Polynesia

9,585

9,912

Demonstration: Borders

tab_data %>%
  flextable(
    col_keys = c("country_name", "region", "y_1995", "y_2005")
  ) %>%
#--- remove all borders ---#
  border_remove() %>%
#--- horizontal lines ---#
  hline(i = 3, j = 1:3, border = fp_border(color = "red")) %>%
#--- horizontal line at the bottom ---#
  hline_bottom(j = 3:4, border = fp_border(color = "green")) %>%
#--- horizontal line at the top ---#
  hline_top(j = 1:3, border = fp_border(color = "orange")) %>%
#--- vertical lines ---#
  vline(border = fp_border(color = "orange")) %>%
#--- vertical on the left edge  ---#
  vline_left(border = fp_border(color = "grey", width = 2)) %>%
#--- vertical on the right edge  ---#
  vline_right(border = fp_border(color = "red", width = 2)) %>%
#--- borders of individual cells ---#
  border(
    i = 4, j = 2,
    border.top = fp_border(color = "red", width = 3),
    border.left = fp_border(color = "green", width = 3),
    border.right = fp_border(color = "black", width = 3),
    border.bottom = fp_border(color = "pink", width = 3)
  )

country_name

region

y_1995

y_2005

Australia

Australasia

18,004,882

20,176,844

New Zealand

Australasia

3,673,400

4,133,900

Papua New Guinea

Melanesia

4,616,439

6,498,818

Solomon Islands

Melanesia

375,189

482,486

Vanuatu

Melanesia

170,612

217,632

New Caledonia

Melanesia

193,816

232,250

French Polynesia

Polynesia

231,446

271,060

Samoa

Polynesia

174,902

188,626

Tonga

Polynesia

99,977

105,633

Tuvalu

Polynesia

9,585

9,912

Demonstration: Borders

tab_data %>%
  flextable(
    col_keys = c("country_name", "region", "y_1995", "y_2005")
  ) %>%
#--- remove all borders ---#
  border_remove() %>%
#--- horizontal lines ---#
  hline(i = 3, j = 1:3, border = fp_border(color = "red")) %>%
#--- horizontal line at the bottom ---#
  hline_bottom(j = 3:4, border = fp_border(color = "green")) %>%
#--- horizontal line at the top ---#
  hline_top(j = 1:3, border = fp_border(color = "orange")) %>%
#--- vertical lines ---#
  vline(border = fp_border(color = "orange")) %>%
#--- vertical on the left edge  ---#
  vline_left(border = fp_border(color = "grey", width = 2)) %>%
#--- vertical on the right edge  ---#
  vline_right(border = fp_border(color = "red", width = 2)) %>%
#--- borders of individual cells ---#
  border(
    i = 4, j = 2,
    border.top = fp_border(color = "red", width = 3),
    border.left = fp_border(color = "green", width = 3),
    border.right = fp_border(color = "black", width = 3),
    border.bottom = fp_border(color = "pink", width = 3)
  ) %>%
  #--- horizontal lines (inner) ---#  #--- horizontal lines (inner) ---#
  border_inner_h(border = fp_border(color = "black"))

country_name

region

y_1995

y_2005

Australia

Australasia

18,004,882

20,176,844

New Zealand

Australasia

3,673,400

4,133,900

Papua New Guinea

Melanesia

4,616,439

6,498,818

Solomon Islands

Melanesia

375,189

482,486

Vanuatu

Melanesia

170,612

217,632

New Caledonia

Melanesia

193,816

232,250

French Polynesia

Polynesia

231,446

271,060

Samoa

Polynesia

174,902

188,626

Tonga

Polynesia

99,977

105,633

Tuvalu

Polynesia

9,585

9,912

Demonstration: Borders

tab_data %>%
  flextable(
    col_keys = c("country_name", "region", "y_1995", "y_2005")
  ) %>%
#--- remove all borders ---#
  border_remove() %>%
#--- horizontal lines ---#
  hline(i = 3, j = 1:3, border = fp_border(color = "red")) %>%
#--- horizontal line at the bottom ---#
  hline_bottom(j = 3:4, border = fp_border(color = "green")) %>%
#--- horizontal line at the top ---#
  hline_top(j = 1:3, border = fp_border(color = "orange")) %>%
#--- vertical lines ---#
  vline(border = fp_border(color = "orange")) %>%
#--- vertical on the left edge  ---#
  vline_left(border = fp_border(color = "grey", width = 2)) %>%
#--- vertical on the right edge  ---#
  vline_right(border = fp_border(color = "red", width = 2)) %>%
#--- borders of individual cells ---#
  border(
    i = 4, j = 2,
    border.top = fp_border(color = "red", width = 3),
    border.left = fp_border(color = "green", width = 3),
    border.right = fp_border(color = "black", width = 3),
    border.bottom = fp_border(color = "pink", width = 3)
  ) %>%
  #--- horizontal lines (inner) ---#  #--- horizontal lines (inner) ---#
  border_inner_h(border = fp_border(color = "black")) %>%
  #--- vertical lines (inner) ---#  #--- vertical lines (inner) ---#
  border_inner_v(border = fp_border(color = "black"))

country_name

region

y_1995

y_2005

Australia

Australasia

18,004,882

20,176,844

New Zealand

Australasia

3,673,400

4,133,900

Papua New Guinea

Melanesia

4,616,439

6,498,818

Solomon Islands

Melanesia

375,189

482,486

Vanuatu

Melanesia

170,612

217,632

New Caledonia

Melanesia

193,816

232,250

French Polynesia

Polynesia

231,446

271,060

Samoa

Polynesia

174,902

188,626

Tonga

Polynesia

99,977

105,633

Tuvalu

Polynesia

9,585

9,912

Demonstration: Borders

tab_data %>%
  flextable(
    col_keys = c("country_name", "region", "y_1995", "y_2005")
  ) %>%
#--- remove all borders ---#
  border_remove() %>%
#--- horizontal lines ---#
  hline(i = 3, j = 1:3, border = fp_border(color = "red")) %>%
#--- horizontal line at the bottom ---#
  hline_bottom(j = 3:4, border = fp_border(color = "green")) %>%
#--- horizontal line at the top ---#
  hline_top(j = 1:3, border = fp_border(color = "orange")) %>%
#--- vertical lines ---#
  vline(border = fp_border(color = "orange")) %>%
#--- vertical on the left edge  ---#
  vline_left(border = fp_border(color = "grey", width = 2)) %>%
#--- vertical on the right edge  ---#
  vline_right(border = fp_border(color = "red", width = 2)) %>%
#--- borders of individual cells ---#
  border(
    i = 4, j = 2,
    border.top = fp_border(color = "red", width = 3),
    border.left = fp_border(color = "green", width = 3),
    border.right = fp_border(color = "black", width = 3),
    border.bottom = fp_border(color = "pink", width = 3)
  ) %>%
  #--- horizontal lines (inner) ---#  #--- horizontal lines (inner) ---#
  border_inner_h(border = fp_border(color = "black")) %>%
  #--- vertical lines (inner) ---#  #--- vertical lines (inner) ---#
  border_inner_v(border = fp_border(color = "black")) %>%
  border_remove()

country_name

region

y_1995

y_2005

Australia

Australasia

18,004,882

20,176,844

New Zealand

Australasia

3,673,400

4,133,900

Papua New Guinea

Melanesia

4,616,439

6,498,818

Solomon Islands

Melanesia

375,189

482,486

Vanuatu

Melanesia

170,612

217,632

New Caledonia

Melanesia

193,816

232,250

French Polynesia

Polynesia

231,446

271,060

Samoa

Polynesia

174,902

188,626

Tonga

Polynesia

99,977

105,633

Tuvalu

Polynesia

9,585

9,912

Demonstration: Borders

tab_data %>%
  flextable(
    col_keys = c("country_name", "region", "y_1995", "y_2005")
  ) %>%
#--- remove all borders ---#
  border_remove() %>%
#--- horizontal lines ---#
  hline(i = 3, j = 1:3, border = fp_border(color = "red")) %>%
#--- horizontal line at the bottom ---#
  hline_bottom(j = 3:4, border = fp_border(color = "green")) %>%
#--- horizontal line at the top ---#
  hline_top(j = 1:3, border = fp_border(color = "orange")) %>%
#--- vertical lines ---#
  vline(border = fp_border(color = "orange")) %>%
#--- vertical on the left edge  ---#
  vline_left(border = fp_border(color = "grey", width = 2)) %>%
#--- vertical on the right edge  ---#
  vline_right(border = fp_border(color = "red", width = 2)) %>%
#--- borders of individual cells ---#
  border(
    i = 4, j = 2,
    border.top = fp_border(color = "red", width = 3),
    border.left = fp_border(color = "green", width = 3),
    border.right = fp_border(color = "black", width = 3),
    border.bottom = fp_border(color = "pink", width = 3)
  ) %>%
  #--- horizontal lines (inner) ---#  #--- horizontal lines (inner) ---#
  border_inner_h(border = fp_border(color = "black")) %>%
  #--- vertical lines (inner) ---#  #--- vertical lines (inner) ---#
  border_inner_v(border = fp_border(color = "black")) %>%
  border_remove() %>%
#--- the outer lines ---#
  border_outer(border = fp_border(color = "red", width = 4))

country_name

region

y_1995

y_2005

Australia

Australasia

18,004,882

20,176,844

New Zealand

Australasia

3,673,400

4,133,900

Papua New Guinea

Melanesia

4,616,439

6,498,818

Solomon Islands

Melanesia

375,189

482,486

Vanuatu

Melanesia

170,612

217,632

New Caledonia

Melanesia

193,816

232,250

French Polynesia

Polynesia

231,446

271,060

Samoa

Polynesia

174,902

188,626

Tonga

Polynesia

99,977

105,633

Tuvalu

Polynesia

9,585

9,912

Headers and footers

Transcript

Adding rows above or below the table, and the useful part is colwidths. You give it the values you want, then say how many columns each value spans, so three and one puts a label across the first three columns and another across the last. That is how you build the grouped headers you see in published tables. Then read the callout, because it points you somewhere better for footnotes. add footer row will put text at the bottom, but the footnote function does that and manages the reference symbols for you, which is almost always what you actually want. The star in add star row is a spoken placeholder for either header or footer. Values supplies the text entries, and colwidths supplies a matching span for each entry, so those widths should account for all four columns here. In the rendered example, ft receives the three-column and one-column header, then align centers every header paragraph. Autofit recalculates the dimensions after the longer labels are added. Finally, add footer row supplies one long value with colwidths equal to four, making that footer span the table’s full width. The callout points to the next tab because a spanning footer row is useful for general text, but a true footnote also needs managed reference marks.

You can use these functions to add a row to the top or the bottom of a table:

  • add_header_row()
  • add_footer_row()


Syntax

add_*_row(flextable,
  values = vector of characters,
  colwidths = vector of integers
)


Example

add_header_row(
  values = c("3-column label", "1-column label"),
  colwidths = c(3, 1)
)

This code would insert a row where “3-column label” spans for three columns and “1-column label” spans for one column.


Note

You might want to use footnote() to create footnotes instead of add_footer_row(), as it allows you to generate reference symbols at the same time.

ft %>%
  add_header_row(
    values = c("3-column label", "1-column label"),
    colwidths = c(3, 1)
  ) %>%
  align(align = "center", part = "header") %>%
  autofit() %>%
  add_footer_row(
    values = "4-column footnote, which is made longer to show it spans across the entire columns.",
    colwidths = 4
  )

3-column label

1-column label

country_name

region

y_1995

y_2005

Australia

Australasia

18,004,882

20,176,844

New Zealand

Australasia

3,673,400

4,133,900

Papua New Guinea

Melanesia

4,616,439

6,498,818

Solomon Islands

Melanesia

375,189

482,486

Vanuatu

Melanesia

170,612

217,632

New Caledonia

Melanesia

193,816

232,250

French Polynesia

Polynesia

231,446

271,060

Samoa

Polynesia

174,902

188,626

Tonga

Polynesia

99,977

105,633

Tuvalu

Polynesia

9,585

9,912

4-column footnote, which is made longer to show it spans across the entire columns.

Transcript

And here is that better way. footnote attaches a note to specific cells, and it places the reference symbol both at the cell and beside the note, so the linkage is maintained for you rather than being something you type by hand and then have to keep consistent. Read the two bullets at the bottom, because they are the fiddly parts. The nth value pairs with the nth reference symbol, so order matters. And the values must be wrapped in as paragraph, which is easy to forget and produces an error that does not obviously point at the cause. The example sets i equal to one, j equal to one colon two and part equal to header, so the references attach to the first two header cells rather than to body data. As paragraph wraps the two note strings in the rich paragraph form that flextable expects. The first note pairs with the spoken plus-plus symbol and the second with star-star because both vectors use the same order. Eval false keeps the call readable on the left, while echo false shows only the result on the right. Check both the header marks and the note list to see that footnote built the connection in both places.

Explanation

footnote() lets you add footnotes with reference symbols for each of them.


Syntax

ft %>%
  footnote(
    i = 1, j = 1:2, part = "header",
    value = as_paragraph(
      c(
        "This is footnote 1",
        "This is footnote 2"
      )
    ),
    ref_symbols = c("++", "**")
  )

country_name++

region**

y_1995

y_2005

Australia

Australasia

18,004,882

20,176,844

New Zealand

Australasia

3,673,400

4,133,900

Papua New Guinea

Melanesia

4,616,439

6,498,818

Solomon Islands

Melanesia

375,189

482,486

Vanuatu

Melanesia

170,612

217,632

New Caledonia

Melanesia

193,816

232,250

French Polynesia

Polynesia

231,446

271,060

Samoa

Polynesia

174,902

188,626

Tonga

Polynesia

99,977

105,633

Tuvalu

Polynesia

9,585

9,912

++This is footnote 1

**This is footnote 2

  • nth element in value is associated with nth value in ref_symbols
  • use as_paragraph(c()) for value
Transcript

Column headers default to your variable names, which are usually written for typing rather than for reading. This renames them. You pass a list where the name on the left is the existing column and the string on the right is what gets displayed. Note that this changes only what is shown. The underlying column keys stay the same, so any later formatting call still refers to country underscore name, not to Country Name. That trips people up when they rename first and then try to select by the new label. Rename late, or keep selecting by the original key. In the example’s named list, country underscore name becomes the displayed label Country Name and region becomes Region. Autofit follows the relabeling so widths are recalculated for the more readable text. Eval false makes the left side code-only, and echo false makes the right side result-only. Compare those labels with the unchanged data underneath, then remember that a later j formula would still use tilde country underscore name plus region. The display can be polished without coupling the rest of your formatting code to presentation wording.

set_header_labels() lets you re-label existing header labels using a named list.


Syntax

set_header_labels(
  values = list(
    existing name 1 = "new name 1",
    existing name 2 = "new name 2"
  )
)


Example

ft %>%
  set_header_labels(
    values = list(
      country_name = "Country Name",
      region = "Region"
    )
  ) %>%
  autofit()

Country Name

Region

y_1995

y_2005

Australia

Australasia

18,004,882

20,176,844

New Zealand

Australasia

3,673,400

4,133,900

Papua New Guinea

Melanesia

4,616,439

6,498,818

Solomon Islands

Melanesia

375,189

482,486

Vanuatu

Melanesia

170,612

217,632

New Caledonia

Melanesia

193,816

232,250

French Polynesia

Polynesia

231,446

271,060

Samoa

Polynesia

174,902

188,626

Tonga

Polynesia

99,977

105,633

Tuvalu

Polynesia

9,585

9,912

Transcript

Deleting the header entirely, which you want more often than you might think, particularly when a table is going into a document that supplies its own column labels. The default part is the header, so calling it with no arguments does exactly that. Then read the Note tab, because it makes the same point the previous tab did, from the other direction. Even with the header gone, you still select columns by their original names. The header was only ever a display layer. The keys underneath it are what the selectors use, and deleting the display does not remove them. The syntax shows that you can supply another part explicitly, but the bare delete part in How removes the header from ft. The code-only left chunk uses eval false, and the right chunk uses echo false to display the headerless result. In Note, tab data is rebuilt with four named col keys, the header is deleted, and hline still accepts j equal to tilde country underscore name plus region. I equal to three places a red, dotted, width-four line at row three across those two columns. That successful output demonstrates why column selectors use data keys rather than whatever labels happen to be visible.

Syntax

delete_part(flextable, part = "header")


The default is to delete the header.

Example

ft %>%
  delete_part()

Australia

Australasia

18,004,882

20,176,844

New Zealand

Australasia

3,673,400

4,133,900

Papua New Guinea

Melanesia

4,616,439

6,498,818

Solomon Islands

Melanesia

375,189

482,486

Vanuatu

Melanesia

170,612

217,632

New Caledonia

Melanesia

193,816

232,250

French Polynesia

Polynesia

231,446

271,060

Samoa

Polynesia

174,902

188,626

Tonga

Polynesia

99,977

105,633

Tuvalu

Polynesia

9,585

9,912

You can still (or have to) use the original variable names from the dataset for selectors even after you delete the header:

tab_data %>%
  flextable(
    col_keys = c("country_name", "region", "y_1995", "y_2005")
  ) %>%
  delete_part() %>%
  hline(
    i = 3,
    j = ~ country_name + region,
    border = fp_border(color = "red", style = "dotted", width = 4)
  )

Australia

Australasia

18,004,882

20,176,844

New Zealand

Australasia

3,673,400

4,133,900

Papua New Guinea

Melanesia

4,616,439

6,498,818

Solomon Islands

Melanesia

375,189

482,486

Vanuatu

Melanesia

170,612

217,632

New Caledonia

Melanesia

193,816

232,250

French Polynesia

Polynesia

231,446

271,060

Samoa

Polynesia

174,902

188,626

Tonga

Polynesia

99,977

105,633

Tuvalu

Polynesia

9,585

9,912

Layout

Transcript

Layout is about the geometry of a table rather than its appearance: which cells are merged, how wide columns are, how tall rows are. The full list is on screen, but we work through four, which are the four you will actually use. Merging vertically, autofitting, fitting to a maximum width, and setting an explicit width. Read the callout at the bottom too. Horizontal merging exists and is rarely wanted, and the honest admission that the instructor has never needed it is more useful to you than a complete tour of functions you will never reach for. The merge functions differ in scope. Merge at combines a selected block into one cell. Merge h joins cells across a row, merge h range limits that operation to a chosen run of columns, and merge v joins equal adjacent values down a column. Height and height all set row heights, while width sets column widths. Hrule controls the rule flextable uses to determine row height. Autofit derives dimensions from content; fit to width reduces the result until it falls below a maximum total width. As grouped data prepares grouped structure when your source data has grouping columns. All of these operate on the table object, and most reuse the selector grammar you already know. The callout explains why the worked tabs concentrate on the four operations you are most likely to need.

List of functions

Here is a list of functions you can use to change the layout of a table:

  • merge_at(): Merge flextable cells into a single one
  • merge_h(): Merge flextable cells horizontally
  • merge_h_range(): rowwise merge of a range of columns
  • merge_v(): Merge flextable cells vertically
  • height(), height_all(): Set flextable rows height
  • width(): Set flextable columns width
  • hrule(): Set flextable rule for rows heights
  • autofit(): Adjusts cell widths and heights
  • fit_to_width(): fit a flextable to a maximum width
  • as_grouped_data(): grouped data transformation

Use the selector syntax to specify where just like the other functions we have seen. We will look at merge_v(), autofit(), fit_to_width(), and width().


Note

I have not encountered cases where I need to merge cells horizontally. It works in a similar manner to the way merge_v() works except that it works on rows instead of columns.

Transcript

Vertical merging collapses adjacent cells in a column that hold the same value into one tall cell. Look at the before and after: the region column goes from repeating Australasia twice and Melanesia four times to a single merged cell for each group. That is exactly the convention published tables use for grouped rows, and it is one function call. Note the sentence about the i argument. merge v does not take one, because which cells merge is decided entirely by which adjacent values are equal. Which also means sorting your data first is what controls the grouping.

merge_v() merges vertically the adjacent cells with the same values. It does not accept i (rows) argument.

Before

ft

country_name

region

y_1995

y_2005

Australia

Australasia

18,004,882

20,176,844

New Zealand

Australasia

3,673,400

4,133,900

Papua New Guinea

Melanesia

4,616,439

6,498,818

Solomon Islands

Melanesia

375,189

482,486

Vanuatu

Melanesia

170,612

217,632

New Caledonia

Melanesia

193,816

232,250

French Polynesia

Polynesia

231,446

271,060

Samoa

Polynesia

174,902

188,626

Tonga

Polynesia

99,977

105,633

Tuvalu

Polynesia

9,585

9,912

After

ft %>% merge_v(j = ~region)

country_name

region

y_1995

y_2005

Australia

Australasia

18,004,882

20,176,844

New Zealand

3,673,400

4,133,900

Papua New Guinea

Melanesia

4,616,439

6,498,818

Solomon Islands

375,189

482,486

Vanuatu

170,612

217,632

New Caledonia

193,816

232,250

French Polynesia

Polynesia

231,446

271,060

Samoa

174,902

188,626

Tonga

99,977

105,633

Tuvalu

9,585

9,912

Transcript

Autofit adjusts column widths to suit the content. The example makes the point by putting an absurdly long country name into the first column and showing before and after. Before, the text wraps badly. After, the column has widened so more fits on a single line. Read the last sentence carefully though, because it corrects something this slide used to get wrong. Autofit does not stop the table from running off the page. It sizes each column to its content and lets the total go wherever it goes, so one long value can push the table far wider than the paper. The function that caps the total width is fit to width, and it is on the next tab. Both sides begin with tab data. Mutate uses ifelse to replace Australia with the deliberately overlong string while leaving every other country name unchanged. Flextable then keeps country name, region and the two year columns, and merge v groups adjacent region labels. The Before pipeline stops there. The After pipeline adds autofit, so its output isolates the effect of that one call. The warning is the key interpretation: more text fits in a row because the first column expands, not because autofit respects a page boundary. Carry that distinction directly into the fit to width comparison next.

autofit() adjusts the height and width of cells.

Before

tab_data %>%
  mutate(country_name = ifelse(country_name == "Australia", "super long country name .......... bluh bluh bluh bluh bluh bluh bluh bluh bluh bluh bluh bluh", country_name)) %>%
  flextable(
    col_keys = c("country_name", "region", "y_1995", "y_2005")
  ) %>%
  merge_v(j = ~region)

country_name

region

y_1995

y_2005

super long country name .......... bluh bluh bluh bluh bluh bluh bluh bluh bluh bluh bluh bluh

Australasia

18,004,882

20,176,844

New Zealand

3,673,400

4,133,900

Papua New Guinea

Melanesia

4,616,439

6,498,818

Solomon Islands

375,189

482,486

Vanuatu

170,612

217,632

New Caledonia

193,816

232,250

French Polynesia

Polynesia

231,446

271,060

Samoa

174,902

188,626

Tonga

99,977

105,633

Tuvalu

9,585

9,912

After

tab_data %>%
  mutate(country_name = ifelse(country_name == "Australia", "super long country name .......... bluh bluh bluh bluh bluh bluh bluh bluh bluh bluh bluh bluh", country_name)) %>%
  flextable(
    col_keys = c("country_name", "region", "y_1995", "y_2005")
  ) %>%
  merge_v(j = ~region) %>%
  autofit()

country_name

region

y_1995

y_2005

super long country name .......... bluh bluh bluh bluh bluh bluh bluh bluh bluh bluh bluh bluh

Australasia

18,004,882

20,176,844

New Zealand

3,673,400

4,133,900

Papua New Guinea

Melanesia

4,616,439

6,498,818

Solomon Islands

375,189

482,486

Vanuatu

170,612

217,632

New Caledonia

193,816

232,250

French Polynesia

Polynesia

231,446

271,060

Samoa

174,902

188,626

Tonga

99,977

105,633

Tuvalu

9,585

9,912

It adjusted the width of the 1st column so that more texts are displayed in a single row.

Warning

autofit() does not keep the table inside the page width. It sizes every column to fit its content and lets the total width go wherever that lands. Here the table ends up far wider than a page. Use fit_to_width() (next tab) when you need a ceiling.

Transcript

This is the one that does what people expect autofit to do. You give it a maximum width in inches and it reduces the font size one point at a time, running autofit again after each reduction until the table fits inside the limit. Same overlong country name as the previous tab, same autofit call, then a ceiling of six inches on top. The text stays on one line, but the type and recomputed column widths get smaller. Reach for this when a table is going into a document with a fixed page width and you would rather use smaller type than let the table run off the edge. The two columns deliberately repeat the same setup so the final function is the only difference. Mutate replaces just Australia with the long test label, and flextable retains country name, region and the two year columns. The left result stops after autofit and can remain wider than a page. The right pipes that result into fit to width with max width equal to six, meaning six inches. Compare the overall table and text size, not merely the wrapping. This function meets the ceiling by repeatedly shrinking type and recomputing widths, so it trades readability for fitting the requested limit.

fit_to_width() reduces the font size and recomputes the column widths until the table fits inside the maximum width you give it (in inches).

autofit() only

tab_data %>%
  mutate(country_name = ifelse(country_name == "Australia", "super long country name .......... bluh bluh bluh bluh bluh bluh bluh bluh bluh bluh bluh bluh", country_name)) %>%
  flextable(
    col_keys = c("country_name", "region", "y_1995", "y_2005")
  ) %>%
  autofit()

country_name

region

y_1995

y_2005

super long country name .......... bluh bluh bluh bluh bluh bluh bluh bluh bluh bluh bluh bluh

Australasia

18,004,882

20,176,844

New Zealand

Australasia

3,673,400

4,133,900

Papua New Guinea

Melanesia

4,616,439

6,498,818

Solomon Islands

Melanesia

375,189

482,486

Vanuatu

Melanesia

170,612

217,632

New Caledonia

Melanesia

193,816

232,250

French Polynesia

Polynesia

231,446

271,060

Samoa

Polynesia

174,902

188,626

Tonga

Polynesia

99,977

105,633

Tuvalu

Polynesia

9,585

9,912

autofit() then fit_to_width()

tab_data %>%
  mutate(country_name = ifelse(country_name == "Australia", "super long country name .......... bluh bluh bluh bluh bluh bluh bluh bluh bluh bluh bluh bluh", country_name)) %>%
  flextable(
    col_keys = c("country_name", "region", "y_1995", "y_2005")
  ) %>%
  autofit() %>%
  fit_to_width(max_width = 6)

country_name

region

y_1995

y_2005

super long country name .......... bluh bluh bluh bluh bluh bluh bluh bluh bluh bluh bluh bluh

Australasia

18,004,882

20,176,844

New Zealand

Australasia

3,673,400

4,133,900

Papua New Guinea

Melanesia

4,616,439

6,498,818

Solomon Islands

Melanesia

375,189

482,486

Vanuatu

Melanesia

170,612

217,632

New Caledonia

Melanesia

193,816

232,250

French Polynesia

Polynesia

231,446

271,060

Samoa

Polynesia

174,902

188,626

Tonga

Polynesia

99,977

105,633

Tuvalu

Polynesia

9,585

9,912

Transcript

When autofit does not give you what you want, set the width yourself. This sets one column to a specific width in inches. Notice the example calls autofit first and then overrides a single column, which is the practical pattern. Let the automatic layout do the bulk of the work, then correct the one or two columns it got wrong. Setting every width by hand is tedious and tends to break as soon as your content changes. Setting one, after autofit, usually fixes the specific problem you were actually looking at. The Before side is ft after autofit. The After side starts identically, then width uses j equal to tilde country underscore name to select that column and width equal to one to make it one inch wide. Compare the first column across the two outputs and watch the country text reflow into the narrower space while the other columns retain their automatically chosen widths. The selector is important: without j, you would be imposing that width more broadly instead of correcting the single problem column.

width() sets the width of columns to the length you specify.

Before

ft %>%
  autofit()

country_name

region

y_1995

y_2005

Australia

Australasia

18,004,882

20,176,844

New Zealand

Australasia

3,673,400

4,133,900

Papua New Guinea

Melanesia

4,616,439

6,498,818

Solomon Islands

Melanesia

375,189

482,486

Vanuatu

Melanesia

170,612

217,632

New Caledonia

Melanesia

193,816

232,250

French Polynesia

Polynesia

231,446

271,060

Samoa

Polynesia

174,902

188,626

Tonga

Polynesia

99,977

105,633

Tuvalu

Polynesia

9,585

9,912

After

ft %>%
  autofit() %>%
  width(j = ~country_name, width = 1)

country_name

region

y_1995

y_2005

Australia

Australasia

18,004,882

20,176,844

New Zealand

Australasia

3,673,400

4,133,900

Papua New Guinea

Melanesia

4,616,439

6,498,818

Solomon Islands

Melanesia

375,189

482,486

Vanuatu

Melanesia

170,612

217,632

New Caledonia

Melanesia

193,816

232,250

French Polynesia

Polynesia

231,446

271,060

Samoa

Polynesia

174,902

188,626

Tonga

Polynesia

99,977

105,633

Tuvalu

Polynesia

9,585

9,912

Output

Transcript

Everything so far produces a table object. This section is about getting it out of R and into whatever you are actually writing. Three destinations: Word, PowerPoint, and an image file. Word matters most for this audience, because a flextable saved to docx arrives as a real editable Word table rather than a picture, which means a coauthor can adjust it and a journal can typeset it. That is the main practical argument for building tables this way at all. The cell here just builds a plain table to demonstrate with. Those are the three destinations demonstrated in the following tabs. The list also shows save as html for a web page and save as r t f for Rich Text Format. For images, the supported file types shown here are P N G and S V G. The setup assigns table temp by piping tab data into flextable and retaining country name, region, y underscore nineteen ninety-five and y underscore two thousand five. Saving the same object several ways makes the output choice independent of all the formatting work that created it.

We can save the table in various formats.

  • save_as_docx(): docx (WORD)
  • save_as_pptx(): pptx (Power Point)
  • save_as_image(): image (png or svg only)
  • save_as_html(): html
  • save_as_rtf(): rtf

Let’s create a table for demonstration:

table_temp <-
  tab_data %>%
  flextable(col_keys = c("country_name", "region", "y_1995", "y_2005"))
Transcript

Two functions, one line each. Save as docx for Word, save as pptx for PowerPoint. There is little to say about the syntax, so let me say the important thing instead. What arrives at the other end is a native table, not an image. You can click into a cell in Word and edit the text. You can restyle it with Word’s own tools. That is the whole reason to build tables this way rather than exporting a picture, and it is what makes the workflow survive contact with a coauthor who does not use R. Each function receives table temp as the table to export and path as the destination filename. The Word call writes temp underscore table dot d o c x, and the PowerPoint call writes temp underscore table dot p p t x. Both chunks use eval false because rendering the lecture should not create files on the instructor’s machine every time. When you copy the code, choose a path you can find and keep the matching extension so the function writes the intended document type.

WORD

save_as_docx(table_temp, path = "temp_table.docx")


Power Point

save_as_pptx(table_temp, path = "temp_table.pptx")
Transcript

And saving as an image, for when you need a picture rather than an editable table, typically for slides or a preprint. This used to need the webshot2 package and a headless browser. It no longer does. Current flextable draws the image with R’s own graphics, so there is nothing extra to install. Two things to note. Only png and svg are accepted now, and asking for a pdf is an error rather than a fallback. And resolution is set with res rather than the old zoom argument, so res equals three hundred is what you want if the image is going anywhere near print.

No extra package to install. save_as_image() draws the table with R’s own graphics.

png

save_as_image(table_temp, path = "temp_table.png")


png, at print resolution

save_as_image(table_temp, path = "temp_table.png", res = 300)


svg (vector, so it stays sharp at any size)

save_as_image(table_temp, path = "temp_table.svg")


Note

path must end in .png or .svg. Asking for a .pdf or a .jpeg is an error, not a silent fallback. If you need a pdf, save the svg and convert it, or put the table straight into a document with save_as_docx().