I was wondering if anyone had any thoughts on how to create dynamic parameters in a R Markdown Report. Currently I have a report with eight parameters that are all hard coded. I would like the values of these parameters to be dynamically derived (based off a query and therefore a data frame) and would like the value in an upper level parameter to drive the selection subset of a lower level parameter.
---
title: My Document
output: html_document
params:
system:
label: "Select System:"
value: A
input: select
choices: [A, B]
fig_num:
label: "Starting Figure Number:"
value: 1
min: 1
max: 100
input: numeric
attach_let:
label: "Attachment Letter:"
value: "A"
input: text
Program:
label: "Select Program:"
value: 1A
input: select
choices: [1A, 1B, 2A, 2B]
ProgramRisk:
label: "Select Sample Program Risk:"
value: 1
input: select
choices: [1, 2, 3]
---
```{r setup, include=FALSE}
# set this option in the first code chunk in the document
knitr::opts_chunk$set(echo = params$printcode)
```
Ideally, I would like the values for System parameter to come directly from a SQL query (e.g - SELECT DISTINCT System from A.Table). The user would then select a value and say in the Program parameter - these values were derived from another query (e.g. SELECT DISTINCT Program FROM B.Table where System = [Param$System]. This would thereby prevent the user inputting a value in the program that did not exist for that System.
I have seen that you can use !r to use R code directly in the YAML header, but this seems limited to basic calls (as.Date..., etc.). Does anyone have any ideas how I could get this information to the parameters and allow the parameters to be filtered by another (earlier) parameter?
Any help would be appreciated! Thank you in advance!
OK, so it looks like I can run true Shiny interactive elements in an HTML document that could act as an interface. I do appreciate that Shiny is at the core of RMarkdown, i guess I was being a bit single focused. Although not as simple as the RMarkdown parameter, if offers much more flexibility as I can run code initially, allowing me to populate my parameters and control the filtering
https://rmarkdown.rstudio.com/authoring_shiny
The workflow would then be:
1) Someone runs the Shiny code
2) Selects parameter values
3) Click 'OK'
4) These values are used to render the underlying reports
5) Reports are saved to as pdf.
#divibisan - thanks for your help! Got me thinking a bit differently.
Related
I am applying for junior data analyst positions and have come to the realization that I will be sending out a lot of cover letters.
To (somewhat) ease the pain and suffering that this will entail, I want to automate the parts of the cover letter that is suited for automation and will be using R Markdown to (hopefully) achieve this.
For the purposes of this question, let's say that the parts I am looking to automate is the position applied for and the company looking to hire someone for that position, to be used in the header of the cover letter.
These are the steps I envision in my mind's eye:
Gather the positions of interest and corresponding company in an Excel spreadsheet. This gives and Excel sheet with two columns with the variables position and company, respectively.
Read the Excel file into the R Markdown as a data frame/tibble (let's call this jobs).
Define two parameters in the YAML header of the .Rmd file to look something like this:
---
output: pdf_document
params:
position: jobs$position[i]
company: jobs$company[i]
---
The heading of the cover letter would then look something like this:
"Application for the position as r params$position at r params$company"
To summarize: In order to not have to change the values of the parameters manually for each cover letter, I would like to read an Excel file with the position titles and company names, loop these through the parameters in the YAML header, and then have R Markdown output a PDF for each pair of position and company (and ideally have the name of each PDF include the position title and company name for easier identification when sending the letters out). Is that possible? (Note: the title of the position and the company name does not necessarily have to be stored in an Excel file, that's just how I've collected them.)
Hopefully, the above makes clear what I am trying to achieve.
Any nudges in the right direction is greatly appreciated!
EDIT (11 July 2021):
I have partly arrived at an answer to this.
The trick is to define a function that includes the rmarkdown::render function. This function can then be included in a nested for-loop to produce the desired PDF files.
Again, assuming that I want to automate the position and the company, I defined the rendering function as follows (in a script separate from the "main" .Rmd file containing the text [named "loop_test.Rmd" here]):
render_function <- function(position, company){
rmarkdown::render(
# Name of the 'main' .Rmd file
'loop_test.Rmd',
# What should the output PDF files be called?
output_file = paste0(position, '-', company, '.pdf'),
# Define the parameters that are used in the 'main' .Rmd file
params = list(position = position, company = company),
evir = parent.frame()
)
}
Then, use the function in a for-loop:
for (position in positions$position) {
for (company in positions$company) {
render_function(position, company)
}
}
Where the Excel file containing the relevant positions is called positions with two variables called position and company.
I tested this method using 3 "observations" for a position and a company, respectively ("Company 1", "Company 2" and "Company 3" and "Position 1", "Position 2" and "Position 3"). One problem with the above method is that it produces 3^2 = 9 reports. For example, Position 1 is used in letters for Company 1, Company 2 and Company 3. I obviously only want to match outputs for Company 1 and Position 1. Does anyone have any idea on how to achieve this? This is quite unproblematic for two variables with only three observations, but my intent is to use several additional parameters. The number of companies (i.e. "observations") is, unfortunately, also highly likely to be quite numerous before I can end my search... With, say, 5-6 parameters and 20 companies, the number of reports output will obviously become ridiculous.
As said, I am almost there, but any nudges in the right direction for how to restrict the output to only "match" the company with the position would be highly appreciated.
You can iterate over by row like below.
for(i in 1:nrow(positions)) {
render_function(positions$position[i], positions$company[i])
}
I'm wondering if anyone can help me with a dilemma I'm having.
I have a dataset of around 300 individuals that contains some basic information about them (e.g. age, gender). I want to knit a separate R markdown report for each individual that details this basic information, in Word format. And then I want to save each report with their unique name.
The actual code which sits behind the report doesn't change, only the details of each individual. For example:
Report 1: "Sally is a female who is 34 years old". (Which I would want to save as Sally.doc)
Report 2: "Mike is a male who is 21 years old." (Saved as Mike.doc)
Etc, etc.
Is there a way I can do this without manually filtering the data, re-kniting the document, and then saving manually with unique names?
Thanks a lot!
Use the render function and pass a list of names to the function:
renderMyDocument <- function(name) {
rmarkdown::render("./printing_procedures/dagr_parent.Rmd",
params = list(names = name),
output_file = paste("~/document_", name, '.doc', sep = '')
)
}
lapply(names, renderMyDocument)
Then just make sure your RMD file can take the params argument via the YAML:
---
params:
names:
---
RStudio documentation on parameterized reports here: https://rmarkdown.rstudio.com/developer_parameterized_reports.html
I am currently trying to utilize parameterized reports to allow users to input a dataset (and a few more variables of interest) that will then be fed into an R script that performs and outputs a variety of analyses. These datasets will have information on multiple subjects, and the goal is to produce one report for each subject within the dataset. Thus, I utilize a for loop that loops through the Usernames within the dataset (called map). I then input a .Rmd file which is responsible for the bulk of the analysis. The for loop essentially refers to this .Rmd file for the 50 or so subjects, and outputs the 50 or so reports.
for (id in unique(map$UserName)){
# bunch of code for processing
render(input = "../lib/scripthtml.Rmd",output_file = paste0('report.',
id, '.html'),"html_document",
output_dir = "Script_output", params = "ask") }
What I am currently trying to do is I am trying to utilize parameterized reports in Shiny to allow for the user to input their own dataset (map). Thus, I specified a parameter and utilized params = ask in the render step. The main issue lies here:
Since the render step is under the for loop, it is basically run for each subject. As a result, the params ask interface loads up 50 times, asking for the user to provide their dataset each time.
Is there anyway I can avoid this? How can I get a user to supply their dataset file as a parameter, then utilize it for all 50 reports?
All your variables may be passed through in your render command, I do this for thousands of reports currently.
YAML of .Rmd template
This may include default values for certain parameters depending on your requirements, for illustrative purposes I have left them as empty strings here.
---
params:
var1: ""
var2: ""
var3: ""
---
Loading data set
In shiny, you can have the file input once and re-use for each report. Passing elements of the data frame to the render command in the next section.
Pseudo code for render in for loop
for (i in 1:n) {
rmarkdown::render(
"template.Rmd",
params = list(
var1 = df$var1[i],
var2 = df$var2[i],
var3 = df$var3[i]
),
output_file = out_file
)
}
Note: within a shiny app, you will need to use df()$var1 assuming the file input will become a reactive function.
You can then use the parameters throughout your template using the params$var1 convention.
I am brand new to markdown language.
I am using bookdown to generate reports. I have two questions:
If I have one stacked dataset with one column being a factor...
Is it possible to run separate reports by each factor level (note: I know how to do this analysis in R, I want to know if I can export separate results by each factor as separate reports. Any tips to do this are appreciated.
Can you reference this level in the TEXT section of the report?
I want one report titled, "Results for A" with stats=1234 and another report titled "Results for B with stats=567" where A and B are the levels of a factor.
Does that make sense? All help is appreciated.
I want one report titled, "Results for A" with mode = 2 and another report titled "Results for B with mode = 3".
Does that make sense? All help is appreciated.
You can pass a parameter to the report. The parameter has to be defined in the yaml header
Example:
in example.rmd:
---
output: html_document
params:
stats: NA # default value
---
Results for stats = `r params$stats`
And pass the parameter as such:
rmarkdown::render("example.rmd", params = list(stats = 123))
I am using DT::datatable() to visualize tables in a R markdown file.
# R markdown file
library(DT)
```{r viewdata}
# this is an example but my actual dataset has 10000 rows and 100 columns
var.df <- data.frame(x = rnorm(1:10000), y = rnorm(1:10000),...)
DT::datatable(data = var.df)
```
When I run this code, I get a warning and the resulting HTML is very slow to load:
DT::datatable(var.df)
Warning message:
In instance$preRenderHook(instance) :
It seems your data is too big for client-side DataTables. You may consider server-side processing: http://rstudio.github.io/DT/server.html
I know that there is a server = TRUE/FALSE option in DT::renderDataTable(), but I don't see any server option in DT::datatable.
How do I use serverside processing using DT::datatable()?
The warning message says:
It seems your data is too big for client-side DataTables. You may consider server-side processing: http://rstudio.github.io/DT/server.html
On the documentation website, it shows a Shiny example, which uses DT::renderDataTable(). To use the server-side processing mode, you must have a "server" in the first place. DT::datatable() only produces a static HTML widget, and there is no server behind it. All data live in and is processed by your web browser.
Shiny is not the only possible server for DT, but probably the most convenient one (unless you really understand the technical details behind server-side processing). To use Shiny with R Markdown, see Chapter 19 of the R Markdown book. Here is an example:
---
title: "The server-side processing mode for DT in R Markdown"
runtime: shiny
output: html_document
---
```{r}
DT::renderDT(ggplot2::diamonds)
```