I want to start with translation in R Shiny. At the very beginning, I am creating the simplest app in Shiny and trying to translate it. But I get the following error:
Warning in load_local_config(translation_csv_config) :
You didn't specify config translation yaml file. Default settings are used.
Error in multmerge(all_files, sep) :
Key translation is not the same in all files.
Even when I comment all the app, just running the first line for defining the translation gives me this error.
I have created a csv file for translation.
The code is:
library(shiny)
library(shiny.i18n)
i18n <- Translator$new(translation_csvs_path = "translation_no.csv")
i18n$set_translation_language("en")
ui <- fluidPage(p(i18n$t("Hello")))
server <- function(input, output) {}
shinyApp(ui, server)
I have saved the csv file in the same directory as my working directory. The csv file is:
en,no
Hello,Hei
Related
I wrote a shiny app that includes generating an rmd file and then rendering it into html report.
As shown in the simple example below, there is a variable created inside the server function of shinyapp, then the created rmd file should have access to this variable while rendering into html.
according to other posts and articles, it seems that we have to copy the rmd file into a temporary folder to work and that's what I tried to do below.
the app is not working.
when I try locally, I get this error:
Quitting from lines 8-9 (x3.Rmd)
Warning: Error in print: object 'xz' not found
so it seems that shiny was able to find the generated rmd, started rendering it but did not have access to the xz variable generated in shiny. I did some reading, and it seems to be related to the render environment (ie it renders in a new session) but I do not know how to fix that. (in the real app I am working on, the render process should have access to a dataframe not just a string variable, but I believe the concept is the same for illustration purpose).
when I tested on shinyapps.io, it says Failed-server problem when I click on the download button. Surprisingly, there is nothing in the application log, it says currently no logs.
when I test the original app I am writing (not this simple example), I get this error in shinyapp.io logs:
2022-04-10T18:01:45.357461+00:00 shinyapps[6055802]: Warning in normalizePath(path, winslash = winslash, mustWork = mustWork) :
2022-04-10T18:01:45.357710+00:00 shinyapps[6055802]: [No stack trace available]
2022-04-10T18:01:45.357627+00:00 shinyapps[6055802]: Warning: Error in abs_path: The file '/tmp/Rtmp27RVU8/x3.Rmd' does not exist.
2022-04-10T18:01:45.357543+00:00 shinyapps[6055802]: path[1]="/tmp/Rtmp27RVU8/x3.Rmd": No such file or directory
My goal is to make this work from shinyapp.io. Any suggestions on where to go from there, I believe there are two issues:
1- make sure the rmd render will have access to the variables generated in shiny
2- save the rmd file in a place that is "convenient" for shiny to find and render.
library(shiny)
ui <- fluidPage(
downloadButton("report", "Download sample report.")
)
server <- function(input, output, session) {
#create content and export it into rmd
observe({
xz= "hello there"
x3 = '---
title: sample
output: html_document
---
``` {r}
print(xz)
```
';write(x3, file="x3.rmd", append = FALSE)
})
#Render the report and pass it to download handler
output$report <- downloadHandler(
filename = "sample.html",
content = function(file) {
tempReport <- file.path(tempdir(), "x3.Rmd")
file.copy("x3.Rmd", tempReport, overwrite = TRUE)
output <- rmarkdown::render(
input = tempReport
)
file.copy(output, file)
})
}
shinyApp(ui, server)
These are the resources I used (but still unable to make it work). All deal with parameterized reports of a user uploaded .rmd, which won't work in my case:
https://shiny.rstudio.com/articles/generating-reports.html
https://community.rstudio.com/t/where-do-i-save-the-rmd-file-i-am-generating-with-a-shiny-r-app/65987/3
https://community.rstudio.com/t/generating-downloadable-reports/39701
https://mastering-shiny.org/action-transfer.html#downloading-reports
I have done this with Shiny App but on a shiny server (in my work place) and can share only the approach here. Currently the access to exact code will take time but this shall give you idea. No idea how it works with shinyapps.io but will try that sometime.
Within UI of shiny provide for a "Generate Report" Button.
In server, with
observeEvent(input$btn_Id,{
#Code to render the html in rmarkdown and then also `downloadHandler()`
})
Please check this also :
Use the downloandHanlder() referring this documentation.
This one gives idea to download data
Solution to passing variables is not special. Just ensure data is already present when you are calling render()
like this:
rmarkdown::render(input = "D:/YourWorkingDirectly/Letters.rmd")
If this doesn't help you , please let me know and will delete the answer.
I have come up with a python function that I have confirmed works just fine. I am trying to put this into a Shiny app using Shiny's reticulate. I am not super familiar with Shiny but need to use it anyhow.
To give a bit of background on what I am doing, I've written some python code that takes takes multiple files and matches strings based on one common list of strings. This code works fine when I run the python files on my machine.
I need to make this available to others using a shiny app, where they can upload their files, then have the app run the underlying python code.
So far, I have set up the shiny app so that it can take in multiple files. I am having a hard time thinking about how I can use reactive to make a list of the file path names to then send to my python code (which includes a step to open and read the file) so it can do its thing.
This is the code that I have for my app thus far:
library(shiny)
library(shinyFiles)
# define UI
ui <- fluidPage(
titlePanel('Counter of Gendered Language'),
fileInput("upload", "Choose a folder",
multiple = TRUE,
accept = c('text')),
tableOutput('text'),
downloadButton('output', 'Download Count File .csv'))
# define server behavior
server <- function(input, output){
# Setup
#* Load libraries
library(reticulate)
#* Use virtual environment for python dependencies
use_virtualenv('file/path/py_venv', required = TRUE)
#* Source code
source_python('code/counting_gendered_words.py')
#* Load list of words to match raw text against
dictionary <- read.csv('data/word_rating.csv')
text <- reactive(
list <- list.files(path = input$upload[['name']])
)
output$counted <- gendered_word_counter(dictionary, text())
output$downloadData <- downloadHandler(
filename = function(){
paste0(input$upload, ".csv")
},
content = function(file){
vroom::vroom_write(text$counted, file)
}
)
}
# Run the application
shinyApp(ui = ui, server = server)
What it tells me when I run this app is that:
Error : Operation not allowed without an active reactive context.
You tried to do something that can only be done from inside a reactive consumer.
So what I am wanting to do is basically just pass each file name that someone uploads to the app and pass that file's name into my gendered_word_counter() python function.
How would I go about this?
I'm super confident that I just am being a newbie and it is probably a super simple fix. Any help from those who are more comfortable with Shiny would be much appreciated!
Edit: I notice that my code is only calling the names of the files which is meaningless for me without the contents of the uploaded files! Would it be better if I read the files in the shiny app instead of in my .py file?
I can't reproduce the app without the python code, but i can see that this line:
output$counted <- gendered_word_counter(dictionary, text())
has a reactive object (text()) being called with no reactive context. It should be wrapped in observe or observeEvent.
observe({
output$counted <- gendered_word_counter(dictionary, text())
})
Also let's add the parenthesis here:
content = function(file){
vroom::vroom_write(text()$counted, file)
}
I have a very large fixed width file I need to read in using my Shiny application. The way my program is currently structured is the ui.R contains a fileInput allowing the user to locate the file using the browser.
On the server side, I only capture the path to the file such as the following:
path2file <- reactive({
infile <- input$path2file
if (is.null(infile)) return(NULL)
infile$datapath
})
A subsequent function takes that path as input and the proceeds to read in the file according to its layout specifications. This all works just fine; however when dealing with extremely large fwf files my program slows down tremendously and takes hours to get the path name of the file read in using fileInput
My suspicion is that fileInput is actually reading in the entire file and then my function only returns the datapath even though I am not explicitly reading in any file format type within the function.
My aim is to continue using the program as I have it structured now and obtain only the path to this file using my fileInput. I have found this topic on SO, and see it is a possible option.
Getting file path from Shiny UI (Not just directory) using browse button without uploading the file
However, I also aim to minimize the number of package dependencies I have; this has become a big issue and so if I MUST use an additional package I will, but I'd like to avoid that at all costs.
I experimented with this cheap trick:
path2file <- reactive({
infile <- input$path2file
if (is.null(infile)) return(NULL)
scan(infile$datapath, n = 1)
infile$datapath
})
Thinking that it would be a fast workaround, but it too is extremely slow so I suspect it too is not reading in only n = 1. So, my question is can anyone identify a way to use fileInput to allow a user to locate a file and have the server side function capture only the path and NOT read in the file or try and parse it in any way? More importantly, can this be done using functions in base R and Shiny alone without having to grab functions from other extended packages?
The above is the relevant portion of code in the server.R file and the relevant portion of code in the ui.R file is
fileInput('path2dor', 'Choose the DOR .txt file to format',
accept=c('text/csv',
'text/comma-separated-values,text/plain', '.csv')),
Thank you for you advice.
This functionality is not possible with fileInput. The reason is because 'fileInput' do not provide local path information to the server for security reasons.
With fileInput the user navigates through the browser on his local machine, the resulting file on the server side is the uploaded copy of the selected local once.
As an alternative you can use the shinyFiles package, which do navigate through the server side. This means, that you get all the paths on your local machine.
A second alternative could be a simple text input, which lets the user add a path by hand (make sure to check the path on the server side to not run into any troubles).
As pointed by others, due to security concerns shiny creates a tmp folder with all files loaded called with fileinput
Accordingly, you need to select all the files of interest in your folder and then call this tmp file with ...$datapath
Note however that each element of datapath will include both the directory information and the corresponding file name. Accordingly, you need to trim those paths to only account for the tmp directory. This can be achieved as follows...
Assume you will create an object called phu which will only contain the first file in the folder (using input$upload$datapath[1]) you called with fileInput("upload", NULL, buttonLabel = "Upload...", multiple = TRUE)
phu<-as.character(input$upload$datapath[1])
phu<-substr(phu,1,nchar(phu)-5)
The second line removes the last five characters in the string. These characters are 0.txt or whatever other extension you called in your input. The code provided only works with .txt files and requires the tm package. You can now use the object phu as the input directory of interest.
Finally, you need to call this output with an output object and print it in your ui this is shown with textOutput("Pdiretory") below.
The following example shows the entire process. Note that there are no security concerns because this temporary file and its content will be deleted at closing. Once more, the input files are .txt files.
library(shiny)
library(tm)
ui <- fluidPage(
fileInput("upload", NULL, buttonLabel = "Upload...", multiple = TRUE),
textOutput("Pdiretory")
)
server <- function(input, output, session) {
listdir <- eventReactive(input$upload, {
phu<-as.character(input$upload$datapath[1])
phu<-substr(phu,1,nchar(phu)-5)
txt<-Corpus(DirSource(phu),readerControl = list(language = "en"))
print(txt)
})
output$Pdiretory <- renderPrint ({
listdir()
})
}
shinyApp(ui = ui, server = server)
I am using combination of Shiny and knitr to create PDF documents.
Currently I want to add feature that will allow user to upload picture that will be placed within the created document. However, I am really stuck because I am unable to get the path of the input picture. Could anyone help me with that?
Simple example:
Application:
library(knitr)
library(shiny)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
fileInput("picture", label = 'Picture'),
downloadButton('report', label = 'Download PDF')
),
mainPanel()
)
)
server <- function(input,output){
picture <- reactive({
input$picture[,4]
})
output$report = downloadHandler(
filename = "test.pdf",
content = function(file){
picture = picture()
out = knit2pdf(input = 'test.Rnw', compiler = 'xelatex', clean = TRUE)
file.rename(out, file)
},
contentType = 'application/pdf'
)
}
shinyApp(ui = ui, server = server)
and the .Rnw document:
\documentclass{article}
\begin{document}
Put picture here:
<<echo = FALSE , message = F, results='asis'>>=
cat(paste('\\includegraphics[height=3in]{', picture,'}'))
#
\end{document}
Part '\includegraphics[height=3in]{', picture,'} is obviously causing the problem, because I do not know the picture path only temporary one.
You said you were working with Shiny Server, then you should be okay with the full path of the picture, even if it is in a temporary directory (because currently Shiny Server only works on Linux, and LaTeX should be okay with Linux file paths like /tmp/...../yourfile.png). The problem is perhaps the datapath (i.e. input$picture[, 4]) does not have the file extension, so LaTeX could not recognize it. You may try to retrieve the filename extension of the original file, and copy the uploaded picture to a temp file with the same extension, e.g.
picture <- reactive({
path1 <- input$picture$datapath
path2 <- tempfile(fileext = gsub('^(.*)([.].+)$', '\\2', input$picture$name))
file.copy(path1, path2, overwrite = TRUE)
path2
})
i see a solution in two ways:
1) copy the temporary file to a folder of your choice and use that image:
observe({
if (is.null(input$picture)) return()
picture<-"your/final/path/to/disk/uploadImage.jpg" # OR do a PASTE with the PATH and the upload file name
file.copy(input$picture$datapath, picture)
if(file.exists(picture)){
# PROCESS THE IMAGE IF NEEDED
}
picture<<-picture # sometimes needed to R to see the variable outside the observe scope
})
2) if you (in this case the R session) are not allowed to write to disk you can turn the image into a base64 variable and include that into your Knitr document (or save it to a database as a string). This takes the Knitr/HTML route if you are willing to take that detour. (R studio running from a server almost always has a lot of restrictions in reading/writing that you can only handle as an ADMIN. And the server runs the shiny session as RStudio and not you so Rstudio must have the read/write permissions needed if you run the Shiny app as an automatic Rstudio Shiny session and not run it directly form RStudio using RUN)
Make sure the base64 is readable by R ouside the 'observe' or 'if' scope again by using '<<-' together with '<-'. Scoping is quite something special with R so be sure to test it properly.
You should dive into this (base64) with sites like:
https://github.com/yihui/knitr/issues/944
https://github.com/yihui/knitr/blob/master/R/utils-base64.R
I have a list of 4 large dataframes (size 5.9MB compressed) in an Rdata file (dtall.RData) that I am trying to read into my server.R function using the code provided below, but get "ERROR: [on_request_read] connection reset by peer" error message" and the file is read as a single character "dtall"
When I separately load the dtall.RData into r global environment the app runs locally. But as soon as I clear the dtall.RDdata file from the global environment and try to get the app to load it and run I get the error message above.
I have tried using readRDS, but that does not work either, I get error message:
"Error in readRDS("data/dtall.RData") : unknown input format
The file dtall.RData loads correctly outside the shiny scripts by using function load("data/dtall.RData"
Below is the code of my server.R function
server.R
predictor <-source("predictor.R")
dtall <- load("data/dtall.RData")
shinyServer(function(input, output) {
wordPrediction <- reactive({
text <- input$input
wordPrediction <- predictor(text)})
output$Prediction <- renderPrint(wordPrediction())
})
Thank you in advance for your help!