kableExtra: How does the add_header_above function work? - r

I want to add a row explaining the columns of my table. But the add_header_above function is a bit confusing. How do you use it? This is the built-in example:
x = kable(head(mtcars), "html")
# Add a row of header with 3 columns on the top of the table. The column span for the 2nd and 3rd one are 5 & 6.
add_header_above(x, header = c(" ", "Group 1" = 5, "Group 2" = 6))

You have to create a named vector corresponding to the header row you want, e.g. c("Group 1" = 5)
Each header item consists of the text and its "span"
"span" is a single number specifying how many columns the item spans in the header row.
These spans cumulate and have to sum to the total number of column in the table.
So, if you have a 7 column table, and wanted a header spanning the whole table, you could say:
add_header_above(myKe, header = c("Big title" = 7))`
If you wanted an empty header over an initial column of rownames, followed by a header spanning columns 2:3, another spanning 3:4, and the last 2 cells blank in your 7-column table, you would say:
add_header_above(myKe, header = c(" " = 1, "header1" = 2, "header2" = 2, " " = 2))
note: A header can't be blank, so you need to use a white space " " in "blank" cells.
Important Caveat: This construction of c("my header" = 7) won't work if your headers are constructed on the fly because tmp= "X"; c(tmp = 7) is interpreted as c("tmp" = 7)
Instead, you would have to say something like:
header = 7
names(header) = "X"
myKe = add_header_above(myKe, header = header)

Related

is it possible to hide the footnote number reference in flextable footer section and replace with own text

I have a flextable:
df = data.frame(col1 = c(123,234,54,5), col2 = c(NA,1,2,3), col3 = 5:8)
df %>%
flextable() %>%
footnote(i = 1, j = 1,
value = as_paragraph('this is a footnote'),
ref_symbols = "1",
part = "body") %>%
footnote(i = 1, j = 1,
value = as_paragraph(as_b("Note (2):"),"This is another foonote"),
ref_symbols = "2",
part = "body")
that shows
What I would like to do is keep the flextable and footnotes, but remove the little 1 and 2 that appear in the footer section.
You can use add_footer_lines() to add any content in a new line and append_chunks() to append any content in existing cells/rows/columns (prepend_chunks() can sometimes be useful)
library(flextable)
df <- data.frame(col1 = c(123,234,54,5), col2 = c(NA,1,2,3), col3 = 5:8)
df |>
flextable() |>
add_footer_lines("Here is a foonote") |>
add_footer_lines(as_paragraph(as_b("Note (2):"),"This is another foonote")) |>
append_chunks(i = 1, j = 1, as_sup("12")) |>
append_chunks(i = 2, j = 1, as_sup("‡"))
The David Gohel's previous answer is fine for not getting this behavior of adding the symbol in the cell and in the footnote, but this previous answer will not add "1" or "2" in the cells of the table. In this case, you have to add these symbols by yourself in the cells, since the footnote func' require a "value" parameter (or you get Error in mapply(function(x, y) { : argument "value" is missing, with no default).
In order to add ¹, ², etc. in the cells of the table, I suggest to use a superscript generator (e.g., here), and a paste0 func' to modify the cells and add the symbol ¹ to the data; then use the add_footer_lines func' to create the footnote that you want, without the symbol at the beginning of the footnote (see David Gohel's previous answer).
PS: for a good readability of the "ref_symbols", I prefer to use letters when the symbol appears next to a number (e.g., I use "† ", "‡ ", "A" or "B") and I add number-footnote-symbol when it come next to a text (e.g., ¹ or ²).

Flextable: change cell value if it meets a condition and formatting

I have a dataset (called example) like the following one.
mic <- rep(c("One", "Two", "Tree", "Four"), each = 3)
pap <- rep(c("1", "2", "3", "4"), each = 3)
ref <- rep(c("Trial 1", "Trial 2", "Trial 3", "Trial 4"), each = 3)
prob <- c(rep(NA,4), "Nogood", NA, "Bad", "Nogood", "Norel", NA, "Bad", "Nogood")
example <- data.frame(Micro = mic, Paper = pap, Reference = ref, Problem = prob)
example
Example
I would like to merge cells vertically when consecutive cells have identical
values so I use flextable merge_v() function.
ft_example <- example %>%
flextable() %>%
merge_v(j = ~ Micro + Paper + Reference + Problem) %>%
theme_vanilla()
ft_example
I obtain the following table when knitting in Word:
Table obtained
Is there a way to:
Insert a posteriori the value "None identified" in the empty
cells in the "Problem" field that are merged together; and
Remove the inappropriate horizontal lines in the "Problem" field when
there is one (or more) not empty cells and some empty cells so that
there is one horizontal line clearly separating each combination of
Micro, Paper, Reference and horizontal lines separating only non
empty cells in the Problem field?
You can see the desired result here below:
Table desired

Incrementing to new row with gs_edit_cells once previous row is populated

I'm making a shiny app that acts as a visitor counter. It takes user input from action buttons then updates a Googlesheet with a table of values (date,semester,game,count). I can populate the first value of the of the input, however I'm not quite sure how to "increment" gs_edit_cells() as it only lets me specify one specific anchor cell.
I've tried using gs_add_row(), however it doesn't agree with the dimensions of the input, as its say it needs to be of value 0? I've scoured here, as this seems like it should be a trivial issue to fix.
Server:
the variable data is of the form
data <- c("date","semester","games","num")
saveData <- function(data) {
# Grab the google sheet
table <- gs_title("Game_Table")
show(data)
gs_edit_cells(ss = table,
ws = 1,
input = data,
anchor = "A1",
byrow = TRUE,
col_names = FALSE,
trim = TRUE)
}
The first cell of the table updates as expected:
17905 Fall Table Tennis 7
but when I run it again, it overwrites the old data.
You can add new rows with either gs_add_row() or gs_edit_cells(), but in both cases you previously must have added at least one row and the header (for example, with gs_edit_cells()). In your case, they didn't work for different reasons:
1. gs_add_row
The documentation of the function specifies that:
At the moment, this function will only work in a sheet that has a proper header row of variable or column names and at least one pre-existing data row.
In your case, it didn't work probably because your spreadsheets didn't have a header. A solution is to create the first row and header information with gs_edit_cells() before you use gs_add_row().
2. gs_edit_cells
You used anchor = "A1" in gs_edit_cells(), so every time the spreadsheets was updated from the cell A1 (consequently, overwriting your previous content). The solution is to read the current content of the spreadsheets to know the number of rows and specify the cell where you need to start the update without overwriting past content (keep in mind that the header populates one row in the spreadsheets).
Example code (with both solutions):
data <- data.frame(date = 17905, semester = "Fall", games = "Table Tennis", num = 7)
new_data <- data.frame(date = 17905, semester = "Fall", games = "Table Tennis", num = 7)
# Grab the google sheet
table <- gs_title("Game_Table")
# save first row of data with header (run only one time)
gs_edit_cells(ss = table,
ws = 1,
input = data,
anchor = "A1",
byrow = TRUE,
trim = TRUE)
# solution 1: add new rows with gs_add_rows
table <- gs_title("Game_Table")
gs_add_row(ss = table, input = new_data)
# solution 2: add new rows with gs_edit_cells
table <- gs_title("Game_Table")
last_row <- nrow(gs_read(table))
gs_edit_cells(ss = table,
ws = 1,
input = new_data,
anchor = paste0("A",last_row+2),
byrow = TRUE,
col_names = FALSE,
trim = TRUE)

Matching two names in same column in r

I am new to coding in R and was finding trouble matching two names in the same column.
To be more specific I have a table of multiples rows with a column called "fileName" that gives the name of persay different colors. This table was combined from two different tables so the first table's color names are called new_red and the second is referred to as old_red for example.
I want to be able to make a new column that says that if the set of characters match multiple times in the fileName column, then in the new column to write "Match" for the row that the color is placed in. If the new_ is a unique color where there is no old_ with that color, to write "No_new_match" and the same for the old where it would write "No_old_match".
I believe there is a line of code that references a certain number of numbers/characters after a name i.e it would look for 3 characters for new_xxx. I tried doing it that way where it was like "new\d{3}" but it didn't work the way I intended to.
Here is an example of what I am referring to
fileName
new_red
new-blue
new_green
old_red
old_purple
Match
No_new_match
No_new_match
Match
No-old_match
Any help would be appreciated, I new how to create a new column and such for the table I want to make but I am having trouble with this part. Again, thank you!
Here's a way with dplyr -
df <- data.frame(fileName = c("new_red", "new_blue", "new_green", "old_red", "old_purple"),
stringsAsFactors = F)
df %>%
mutate(
Match = sapply(strsplit(fileName, "_"), "[", 2),
Match = duplicated(Match) | duplicated(Match, fromLast = T)
)
fileName Match
1 new_red TRUE
2 new_blue FALSE
3 new_green FALSE
4 old_red TRUE
5 old_purple FALSE
You can make cosmetic changes to the Match column as per your needs.
Here's a way using regular expressions:
fileName <- c("new_red", "new_blue", "new_green", "old_red", "old_purple")
color <- gsub("(new_)|(old_)", "", fileName)
color.freq <- table(color)
df <- data.frame(
fileName = fileName,
color = color,
match = ifelse(
color.freq[color] == 2,
"Match",
ifelse(
grepl("new", fileName),
"No_new_match",
"No_old_match"
)
)
)
fileName color match
1 new_red red Match
2 new_blue blue No_new_match
3 new_green green No_new_match
4 old_red red Match
5 old_purple purple No_old_match

R Kable: Rotating Text in Column Grouping

I would like to wrap and rotate column HEADER headings in a kable-latex table. I can control the width of the column using column spec, but I need to group columns in my table with a header, and it is the names in the header that I want to rotate and wrap. A very basic example of my table is below.
example <- data.frame(name="testname", score1=3, score2=2, score3=0)
table <- kable(example, format="latex", escape = F) %>%
column_spec(1:4, width = "5em") %>%
add_header_above(c(" " = 1, "Rhyme Product" = 2, "Sound ID Middle" = 1)) %>% add_header_above(c(" " = 1, "Exploring Words" = 2, "Early Skills" = 1), bold = T)
I would like to flip the first set of column groupings (Rhyme Product and Sound ID Middle) on their side (angle = -45) and wrap the text on two separate lines taking up a lot less space. Is this possible?
This one is a pretty simple fix. I'm surprised no one has answered it over the years. One possibility is that the setting did not exist when this question was answered.
To add the line breaks, add a \n to the column names where you would like the breaks to be. To rotate, add angle = "-45" to the add_header_above line you would like to modify. See the code below.
library(tidyverse)
library(kableExtra)
example <- data.frame(name="testname", score1=3, score2=2, score3=0)
table <- kable(example, format="latex", escape = F) %>%
column_spec(1:4, width = "5em") %>%
add_header_above(c(" " = 1, "Rhyme \nProduct" = 2, "Sound ID \nMiddle" = 1), angle = "-45") %>%
add_header_above(c(" " = 1, "Exploring Words" = 2, "Early Skills" = 1), bold = T)
table
Table output
Interestingly enough, the align argument accepts a vector of angles (i.e align = c("-45", "90")) to apply to each column. This is also true for row_spec. I have not seen anyone talking about this, nor is it anywhere in the documentation. It is really useful, however.

Resources