Generate formattable widgets in a loop in an R markdown document

为君一笑 提交于 2019-12-06 04:37:39

Try this (there's a small wrapper for the table output and it's the code from the formattable site as it was easier to read :-)

RPubs Preview

---
title: "formattable example loop"
output: html_document
---

```{r setup}
library(formattable)
library(htmltools)

df <- data.frame(
  id = 1:10,
  name = c("Bob", "Ashley", "James", "David", "Jenny", 
    "Hans", "Leo", "John", "Emily", "Lee"), 
  age = c(28, 27, 30, 28, 29, 29, 27, 27, 31, 30),
  grade = c("C", "A", "A", "C", "B", "B", "B", "A", "C", "C"),
  test1_score = c(8.9, 9.5, 9.6, 8.9, 9.1, 9.3, 9.3, 9.9, 8.5, 8.6),
  test2_score = c(9.1, 9.1, 9.2, 9.1, 8.9, 8.5, 9.2, 9.3, 9.1, 8.8),
  final_score = c(9, 9.3, 9.4, 9, 9, 8.9, 9.25, 9.6, 8.8, 8.7),
  registered = c(TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE),
  stringsAsFactors = FALSE)

show_plot <- function(plot_object) {
  div(style="margin:auto;text-align:center", plot_object)
}
```

```{r}
do.call(div, lapply(1:10, function(i) {

show_plot(print(formattable(df, list(
  age = color_tile("white", "orange"),
  grade = formatter("span",
    style = x ~ ifelse(x == "A", style(color = "green", font.weight = "bold"), NA)),
  test1_score = color_bar("pink", 0.2),
  test2_score = color_bar("pink", 0.2),
  final_score = formatter("span",
    style = x ~ style(color = ifelse(rank(-x) <= 3, "green", "gray")),
    x ~ sprintf("%.2f (rank: %02d)", x, rank(-x))),
  registered = formatter("span", 
    style = x ~ style(color = ifelse(x, "green", "red")),
    x ~ icontext(ifelse(x, "ok", "remove"), ifelse(x, "Yes", "No")))
))))

}))
```

Solution:

Here's an approach that relies on knitr's knit_child function.

1. Create all your formattable widgets and store them in a list

table_list <- lapply(X = list('First_Table' = df_1,
                              'Second_Table' = df_2),
                     FUN = formattable)

2. For each widget, create a temporary, bare-bones RMD file with a chunk that prints the widget

rmd_paths <- c("TEMP_First_Table.rmd", "TEMP_Second_Table.rmd")
names(rmd_paths) <- c("First_Table", "Second_Table")

for (table_name in c("First_Table", "Second_Table")) {
    sink(file = rmd_paths[table_name])
    cat("  \n",
        "```{r, echo = FALSE}",
            "table_list[[table_name]]"
        "```",
        sep = "  \n")
    sink()
}

3. In a new chunk, use knitr::knit_child() to knit the RMD files and include the results in your document.

```{r, results='asis'}
    for (table_name in c("First_Table", "Second_Table") {
        cat(knitr::knit_child(rmd_paths[[table_name]],
                              quiet= TRUE))
        file.remove(rmd_paths[[table_name]]
}
```


Full RMD Example:

Here's a full example that splits the iris data into three separate dataframes (one per species) and creates one formattable for each of the separate dataframes.

---
title: "Example"
output: html_document
---


```{r create_tables}
library(formattable)

df_list <- split(x = iris,
                 f = iris$Species)

table_list <- lapply(df_list, formattable)
```

```{r create_temp_rmd_files, echo=FALSE}

dir.create(path = "temp_rmd")

temp_rmd_list <- list()

for (table_name in names(table_list)) {

  temp_rmd_path <- paste0("temp_rmd/", table_name, ".rmd")
  temp_rmd_list[[table_name]] <- temp_rmd_path


  sink(file = temp_rmd_path)
  cat("  \n",
        "### ", table_name, "  \n",
        "```{r, echo=FALSE}", "  \n",
        'table_list[[table_name]]',
        "  \n",
        "```",
      "  \n",
      sep = "")
  sink()
}
```

```{r knit_temp_rmd_files, echo=FALSE, results='asis'}

for (table_name in names(table_list)) {

  # Knit the temporary RMD file
  cat(knitr::knit_child(temp_rmd_list[[table_name]],
                        quiet = TRUE))

  # Delete the temporary RMD file
  file.remove(temp_rmd_list[[table_name]])
}

```
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!