Reputation: 55
I am using the flextable-function in R to create a nice looking flat contingency table. My flat contingency table has column headers in two rows. I tried to change these using the set_header_labels
-function in the flextable-package but failed.
The steps below represent the process that I went through. The first five steps went fine. I failed to arrive at my desired result in the final step where I want to change column header names from "A" to "aa" and from "B" to "bb". Please be advised that changing "A" to "aa" etc. at the very start is not solving my problem. I really need to make the changes I want, at the very end, not at the beginning!
t <- tibble(ID = 1:10,
header1 = c("A", "A", "A", "A", "A", "B", "B", "B", "B", "B"),
header2 = c("No", "No", "No", "Yes", "Yes", "Yes", "Yes", "No", "Yes", "No"),
q1 = c(1, 3, 2, 2, 3, 1, 2, 1, 1, 3))
ft <- (t %>% ftable(row.vars = c("q1"), col.vars = c("header1", "header2")))
ftable_to_flextable <- function( x ){
row.vars = attr( x, "row.vars" )
col.vars = attr( x, "col.vars" )
rows <- rev(expand.grid( rev(row.vars), stringsAsFactors = FALSE ))
cols <- rev(expand.grid( rev(col.vars), stringsAsFactors = FALSE ))
xmat <- as.matrix(x)
cols$col_keys = dimnames(xmat)[[2]]
xdata <- cbind(
data.frame(rows, stringsAsFactors = FALSE),
data.frame(xmat, stringsAsFactors = FALSE)
)
names(xdata) <- c(names(row.vars), cols$col_keys)
ft <- regulartable(xdata)
ft <- set_header_df(ft, cols)
ft <- theme_booktabs(ft)
ft <- merge_v(ft, j = names(row.vars))
ft
}
flext <- ftable_to_flextable(ft)
flext <- merge_at(flext, i = 1, j = 2:3, part = "header")
flext <- merge_at(flext, i = 1, j = 4:5, part = "header")
Running flext
now returns:
set_header_labels(flext, A = "aa", B = "bb")
I get the following error message:
Error in `[<-`(`*tmp*`, i, j, value = value) : subscript out of bounds
Upvotes: 2
Views: 5264
Reputation: 10675
this should do the job with your code
# flext <- flextable::compose(flext, i = 1, j = 2, part = "header", value = as_paragraph("aa"))
# flext <- flextable::compose(flext, i = 1, j = 4, part = "header", value = as_paragraph("bb"))
If that helps, this is how I would implement it using generic as_flextable
:
library(flextable)
dat <- data.frame(
ID = 1:10,
header1 = c("A", "A", "A", "A", "A", "B", "B", "B", "B", "B"),
header2 = c("No", "No", "No", "Yes", "Yes", "Yes", "Yes", "No", "Yes", "No"),
q1 = c(1, 3, 2, 2, 3, 1, 2, 1, 1, 3),
stringsAsFactors = FALSE
)
dat$header1 <- factor(dat$header1, levels = c("A", "B"), labels = c("aa", "bb"))
dat$header2 <- factor(dat$header2, levels = c("No", "Yes"), labels = c("nope", "ok"))
ft <- ftable(dat,
row.vars = c("q1"),
col.vars = c("header1", "header2")
)
as_flextable.ftable <- function(x, ...) {
row.vars <- attr(x, "row.vars")
col.vars <- attr(x, "col.vars")
rows <- rev(expand.grid(rev(row.vars), stringsAsFactors = FALSE))
cols <- rev(expand.grid(rev(col.vars), stringsAsFactors = FALSE))
xmat <- as.matrix(x)
cols$col_keys <- dimnames(xmat)[[2]]
xdata <- cbind(
data.frame(rows, stringsAsFactors = FALSE),
data.frame(xmat, stringsAsFactors = FALSE)
)
names(xdata) <- c(names(row.vars), cols$col_keys)
ft <- flextable(xdata)
ft <- set_header_df(ft, cols)
ft <- theme_booktabs(ft)
ft <- merge_h(ft, i = seq_len(ncol(rows)), part = "header")
ft
}
as_flextable(ft)
This may need additional work but not that much
Upvotes: 2