Closed ldecicco-USGS closed 8 years ago
I have the same problem. Couldn't find a solution so far. :( Help is highly appreciated.
@ldecicco-USGS @kkrismer For some reason you can only generate one datatable per chunk. To workaround that limitation you should dynamically create one chunk per datable that you want to display. Dynamically creating rmarkdown chunks was solved on stackoverflow (http://stackoverflow.com/questions/21729415/generate-dynamic-r-markdown-blocks).
Here is a gist that I think achieves your desired result: https://gist.github.com/ReportMort/9ccb544a337fd1778179
To test the datatable functionality for searching, pagelength, paging, etc still works I created another gist that splits the iris dataset into 3 parts (one for each species). The code generates 3 chunks to display a datatable for each part of the data set. Those datatable options seem to work fine, so I think this solution will work. https://gist.github.com/ReportMort/e54ec050d97d79996189
Thanks for the solution. That is certainly one way to go. I have another solution proposed at https://github.com/ramnathv/htmlwidgets/pull/110 I'll let you know once the proposal is accepted.
My work around. Haven't tested with datatable but works with another htmlWidget, DiagrammeR.
Say you have a data frame called grfDf
with DiagrammeR graph objects in the column graph
. The following is all you need to plot all the graphs in Rmd : r require(DiagrammeR); renderHtmlWidgetList(grfDf$graph, render_graph)
. See the code for caveats.
require(knitr)
r renderHtmlWidgetList(...)
;r require(DiagrammeR); renderHtmlWidgetList(grfDf$graph, render_graph)
renderHtmlWidgetList <- function(widgetList, renderFunction){
stopifnot(is.list(widgetList))
if(is.function(renderFunction)) {
renderFunction <- deparse(substitute(renderFunction))
} stopifnot(is.character(renderFunction) & length(renderFunction)==1) stopifnot(exists(renderFunction, mode = "function"))
gVarName<- paste0("renderHtmlWidgetList", sample(1:10000, 1)) while (exists(gVarName)) { gVarName<- paste0("renderHtmlWidgetList", sample(1:10000, 1)) }
assign(gVarName, widgetList, envir = .GlobalEnv)
out <- NULL
knitPrefix <- "\n{r results='asis', cache=FALSE, echo=FALSE}\n\n" knitSuffix <- "\n\n
"
for (i in 1:length(widgetList)) {
knit_expanded <- paste0(knitPrefix, renderFunction, "(", gVarName, "[[", i, "]])")
out = c(out, knit_expanded)
}
paste(knitr::knit(text = out), collapse = '\n') }
Turns out that the solution is fairly simple -- just use tagList()
. An example:
```{r}
library(DT)
# split iris by Species and generate a datatable for each species
htmltools::tagList(
lapply(split(iris, iris[, 5]), datatable)
)
@yihui that works, but only in the simple case of printing several datatable
's alone. If you have more complicated requirements, it does not seem to work. For example:
```{r, results='asis'}
library("VennDiagram")
library("DT")
# set up data
car_list <- list()
for(i in seq_along(unique(mtcars[["gear"]]))){
gears <- as.character(unique(mtcars[["gear"]])[i])
car_list[[gears]] <- list()
gears_df <- mtcars[mtcars[["gear"]] == gears , ]
car_list[[gears]][["data"]] <- gears_df
carb_2 <- rownames(gears_df[gears_df[["carb"]] == 2 , ])
carb_4 <- rownames(gears_df[gears_df[["carb"]] == 4 , ])
carb_list <- list("carb_2" = carb_2, "carb_4" = carb_4)
venn_plot <- venn.diagram(x = carb_list, filename = NULL, main = gears) # grid.draw(venn_plot)
car_list[[gears]][["venn"]] <- venn_plot
}
# print to HTML
cat("# Results \n \n ")
for(i in seq_along(names(car_list))){
name <- names(car_list)[i]
cat("\n \n")
cat(sprintf("## Gears: %s {.tabset .tabset-pills} \n \n", name))
cat("### Table \n \n")
print(htmltools::tagList(datatable(car_list[[i]][["data"]])))
cat("\n \n")
cat("### Venn \n \n")
grid.draw(car_list[[i]][["venn"]])
cat("\n \n")
}
Output looks like this. If you check the source HTML and intermediary Markdown, you can see the HTML for the datatable
s are present, but are not displaying correctly:
Any news on that one? I am running into exactly the same problem as @stevekm does: trying to programmatically create sections using for loop and results='asis'. htmlwidgets just do not render, whereas it works using e.g. ggplot2 plots. @yihui: is there a solution yet?
htmltools::tagList()
has to be at the top level: https://yihui.name/en/2017/06/top-level-r-expressions/
Instead of ##
headers, you could use, for example, htmltools::tags$h2()
in tagList()
.
Unfortunately this workaround does not seem to work when e.g. creating an ioslide presentation. htmltools::tags$h2()
is creating the headers, htmlwidgets can be included, but there is no slide break (seems like those are not triggered when using tags?).
The solution will most likely be super simple, can you give me a hint?
Can you be sure that you have set the results='asis'
in your R chunk?
```{r, results='asis'}
# your code
Hm. I thought the following should work as part of an ioslide presentation (minimum example):
---
title: "aaa"
author: "aaaaa"
date: "2018/10/2"
output: html_document
---
# Test
```{r test}
library("htmltools")
library("DT")
createDT <- function(variable){
return(list(tags$h2(names(cars[variable])), datatable(cars[variable])))
}
htmltools::tagList(lapply(as.list(1:2), function(x) createDT(x)))
Spoiler: it does not work
This "solution" is mainly based on that SO question and answer: https://stackoverflow.com/questions/43792783/combine-leaflet-and-markdown-in-loop
I tried a lot of things, including a combination of `results='asis'` and `cat("\n---\n")`, but all of them failed...
The code you provided works on my computer.
BTW, please preview your comment before submitting (I've cleaned last comment for you). Code with the bad format is difficult for people to read.
It certainly works for regular markdown documents. However, it does not work for ioslide presentations as stated above. Switching to the next slide is not happening by using tags$h2()
.
@RomanBi This certainly works for you.
---
title: "loop DT in ioslides"
author: "shrektan"
date: "2018/10/2"
output: ioslides_presentation
---
# Test
```{r, echo=FALSE,include = FALSE}
# You need this code to conduct the magic dependences attaching...
DT::datatable(matrix())
for (i in 1:3) {
nm <- colnames(iris)[i]
cat(sprintf("\n\n## %s\n\n", nm))
cat("\n\n")
cat(knitr::knit_print(DT::datatable(iris, width = "100%")))
cat("\n\n")
}
<img width="816" alt="image" src="https://user-images.githubusercontent.com/8368933/46360900-f6a5e600-c69e-11e8-8821-7b6cc326eb41.png">
Thank you very much, @shrektan! Works like a charm. How could I miss that? ;)
@shrektan 's solution worked perfectly. For all of 5 minutes. Since then all I did was install plotly
and now knit_print()
always wants to make a screenshot of my datatable and complains that phantom.js is not installed.
Any ideas anyone?
A minimal example will help...
Just the exact code from above. It leads to knit_print() calling webshot::webshot(). Before installing plotly it simply printed the datatable into the knitted htm.
Am Do., 17. Jan. 2019, 16:00 hat Xianying Tan notifications@github.com geschrieben:
A minimal example will help...
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/rstudio/DT/issues/67#issuecomment-455201987, or mute the thread https://github.com/notifications/unsubscribe-auth/AmjZSzvFltmp3Ta2IFoH3upajzyp_-FLks5vEJABgaJpZM4ERnBP .
It works on my computer after plotly being installed.
The workaround
DT::matrix()
+cat(knitr::knit_print(DT::datatable()))
seems to be less responsive than DT::datatable()
In the case of a datatable smaller than 10 lines, it includes a lot of blank space after the table. In the case of displaying more than 10 entries, it can disrupts the content of the rest of the page.
Any solutions to avoid this ? Thanks in advance !
EDIT: Solved adding height = "100%", width = "100%" parameters to datatable()
example:
cat(knitr::knit_print(DT::datatable(head(iris,3), height = "100%", width = "100%")))
# You need this code to conduct the magic dependences attaching...
DT::datatable(matrix())
Thank you @shrektan, that was the missing part for me,.
I'm trying to generate a set of datatables from a loop within an rmarkdown file. Something like:
While the straight R produces 2 tables, no tables show up in the 'Knit' html document.
So, this works for 1 table:
But I can't loop through and make several tables. Is there a
print
-like function I'm missing? Thanks for the awesome package!