I'm running a shiny app using flexdashboard but having trouble adding images to the app. The folder containing the images is not being recognized. Here is my folder structure -
Root_Project
-- \app
--- \app_R
---- app.Rmd
---- \bike_img
----- \product_id_37417.jpg
Inside my project, I have a folder called app
Inside app, I have another folder called app_R.
Inside app_R I have a app.Rmd file (which contains the code for the app) and another folder called bike_img (which contains a .jpg file)
In the app.Rmd, I have the following code chunk (after the hashtag is just a comment explaining what the code is doing) -
renderPrint ({
id = "37420" #an id string
dir_files <- fs::dir_ls("bike_img/") #list all files in the bike_img directory
dir_res <- dir_files %>% str_detect(detect_product_id) #detect any file containing the id string
dir_files[dir_res] #return the file containing the id string
})
When I run this in the console, I get the required result which is bike_img/product_id_37420.jpg. However when I run the app, I get the following error
Error: [ENOENT] Failed to search directory 'bike_img': no such file or directory
There seems to be an issue detecting the bike_img folder. Not sure if this is an issue with my code or the {fs} package.
Can anyone see what I may be doing wrong??
Related
I would like to programmatically specify the location of my exports when using write.dta. I have my working directory set to a parent folder and my script is in a child folder called "Script". I want the export to be in a child folder called "Data".
setwd("~/Dropbox/Files")
file_output <- "survey"
path_out <- "./Data"
write_dta(df, paste0(file_output,".dta"), path = path_out, version = 12)
However, I keep getting an error message when R is trying to write. It says it's trying to write to the "Script" folder (where my script file is located in) rather than the desired "Data" folder.
Error: Failed to open '/Users/VancityPlanner/Dropbox/Files/Scripts' for writing
If I put the full path, I still get the same error message, whether it's a child folder or the parent folder (working directory) itself, so I don't think write permissions are an issue.
If I try not specifying the filepath, I have no error messages but it saves it to my working directory, which is not where I want it.
write_dta(df, paste0(file_output,".dta"), version = 12)
Below I show where my working directory is pointing and then I change the path of where I want to save the document in the path statement. Note it has the file path G:/ and the dataset name appended all together. I have a PC but no reason why this shouldn't work on a mac.
library(haven)
getwd()
#"C:/Users/myname/Documents"
write_dta(data = mtcars, path = "G:/mtcars.dta", version = 12)
Streamlit has a function that allows convenient upload of multiple files.
files = st.file_uploader('File upload', type=['txt'],accept_multiple_files=True)
Then files contains a list of UploadedFile objects which are ByteIO like. Though it is not clear how to get the filenames of the original files and write the file to a temporary directory. It is also not clear if that approach would conflict with the way streamlit operates. It basically reruns the underlying script every time an action is performed.
I am using some tools that read files based on their path given as a string. They are expected to be read from the hard drive.
You can access the name of the file with files[i].name and its content with files[i].read().
It looks like this in the end:
import os
import streamlit as st
files = st.file_uploader("File upload", type=["txt"], accept_multiple_files=True)
if len(files) == 0:
st.error("No file were uploaded")
for i in range(len(files)):
bytes_data = files[i].read() # read the content of the file in binary
print(files[i].name, bytes_data)
with open(os.path.join("/tmp", files[i].name), "wb") as f:
f.write(bytes_data) # write this content elsewhere
Is there a better way for programmers within a group, looking to share a common style for shiny apps or rmarkdown docs, to access a css file from a single location rather than manually copying the desired file into the subcontents of each app or document?
The ideal outcome would be to place the file(s) on a github repo, then attach it to any shiny app or rmarkdown file with its web link, is this possible?
Thanks.
It might be easier to include your stylesheets in an R package. This would eliminate the need for external request each time your app loads or doc is opened. Place your css files in a folder in inst and write a single R function that sets the resource paths to your css and loads files accordingly.
Let's say your package has the following structure. (For this example, I'm naming the package mypkg)
mypkg/
R/
use_stylesheets.R
inst/
stylesheets/
styles.min.css
...
...
In use_stylesheets.R, create a function that loads the stylesheets into the head of the document (tags$head) using tags$link.
use_stylesheets <- function() {
shiny::addResourcePath(
"styles",
system.file("stylesheets", package = "mypkg")
)
shiny::tags$head(
shiny::tags$link(rel = "stylesheet", href = "styles.min.css")
)
}
Then in your app or Rmarkdown document, you can load the files into your app using: mypkg::use_stylesheets()
After some tinkering I was able to have success (waiting on coworkers to test on their machines) using these structures for adding css or html from a package into both Shiny Apps and Rmarkdown documents.
# For attaching a css file to an Rmarkdown file
use_package_style_rmd <- function(css_file = "my_css.css"){
# css file
file_name <- paste0("/", css_file)
file_path <- paste0(system.file("stylesheets", package = "my_pkg"), file_name)
shiny::includeCSS(path = file_path)
}
# For placing an HTML headers/footers in place
use_package_header <- function(html_file = "my_header.html"){
# HTML Header
file_name <- paste0("/", html_file)
file_path <- paste0(system.file("stylesheets", package = "my_pkg"), file_name)
shiny::includeHTML(path = file_path)
}
# For attaching css to a shiny app via resourcePath
use_package_style_shiny <- function(stylesheet = "my_css.css"){
# Add Resource Path
shiny::addResourcePath(
prefix = "styles",
directoryPath = system.file("stylesheets", package = "my_pkg"))
# Link to App
shiny::tags$head(
shiny::tags$link(rel = "stylesheet",
href = paste0("styles/", stylesheet)))
}
The use_package_style_rmd function can be placed in any code chunk, whereas the header function will add the html in-place where the function is run.
For the Shiny app use-case the function should be run to establish the resource path to the folder, then in the UI under fluidpage the theme option can be set to the css file using the prefix for the Resource Path styles/my_css.css.
One issue I am still having which may be a separate question, is where to place a supporting image file, and how to add the relative path such that the image can be placed in the header or footer.
My app allows a user to input a date range, a division, a pdf file, and an excel file. The program pulls numbers from the pdf, calculates total points, and adds it to the ranks pulled from the existing excel file. It is supposed to write and save the excel file. Without Shiny, my program works fine. Within Shiny, It is running and the data is correct, but it does not add the data to the excel file. I have added print prompts at various stages to test this. I have tried running this externally as well with the same results. It does not throw an error, it just not add the data to the excel file.
Server function
server<-function(input,output){
output$horse_div <- renderText({
paste("You have chosen",input$division)
})
output$qualifying<-renderText({
paste("Qualifying Period from",input$date[1],"to",input$date[2])
})
output$pdf<-renderText({
req(input$horsereport)
req(input$excelfile)
ponyoutput<-horseRecord(input$horsereport$datapath,input$date[1],input$date[2],input$division,input$excelfile$datapath)
paste("mylist",ponyoutput[1])
})
}
Snippet of horseRecord function
#Set up sheet and excel file
wsheetrank<-paste(div,"RANK")
wsheetpoints<-paste(div,"POINTS")
#load workbook
wb<-loadWorkbook(file=excelfile)
#add pony to ranked list
rank<-read.xlsx(excelfile,wsheetrank)
rank<-rank[,2:3]
rank<-rank %>% mutate(Points=as.numeric(Points))
dat<-rank
dat<-dat%>% add_row(Pony=horse,Points=points) %>% arrange(desc(Points))
#remove duplicates
dat<-dat[!duplicated(dat$Pony),]
rownames(dat)<-seq(from=1,to=nrow(dat),by=1)
#find rank
rank<-grep(horse,dat$Pony)
#Write to excel file
writeData(wb,sheet=wsheetrank,x=dat,colNames=TRUE,rowNames = TRUE,borders="all")
saveWorkbook(wb,excelfile,overwrite=TRUE)
This should add the totaled points pulled from the PDF file to the ranked list, resort, and write to the ranked worksheet. The full code and files can be found here: https://github.com/chealy21/horsePoints
The excel file that you upload gets saved in a temporary file on the shiny server. It is not the excel file that is on disk, even if you run your app locally.
If you add a browser() before writing the data in the workbook (line 138 of horsereportfunction.R), you will get a console prompt when the app reaches that line and you will be able to see it for yourself.
This is what is in the excelfile variable (on a linux machine. Windows temp file are somewhere else but they are still just tmp files):
excelfile
# [1] "/tmp/RtmpFllCQq/5709c4b043babf5b85bd29b4/0.xlsx"
This temporary file on the shiny server does get updated:
readxl::read_excel("/tmp/RtmpFllCQq/5709c4b043babf5b85bd29b4/0.xlsx") %>% filter(Pony == "BIT OF LAUGHTER")
# # A tibble: 1 x 3
# ..1 Pony Points
# <chr> <chr> <dbl>
# 1 30 BIT OF LAUGHTER 1503.
This is in line with the documentation for fileInput:
Whenever a file upload completes, the corresponding input variable is set to a dataframe. This dataframe contains one row for each selected file, and the following columns:
name:
The filename provided by the web browser. This is not the path to read to get at the actual data that was uploaded (see datapath column).
size:
The size of the uploaded data, in bytes.
type:
The MIME type reported by the browser (for example, text/plain), or empty string if the browser didn't know.
datapath:
The path to a temp file that contains the data that was uploaded. This file may be deleted if the user performs another upload operation.
Maybe you could let the user download the updated report (from datapath) after updating it?
If you never intend to publish your app and will always use it locally, you could hardcode the excel file directory. Your app would then copy the workbook at the hardcoded location from datapath.
I was using this package called SNPRelate. This package uses plinkhapmap.bed, plinkhapmap.fam and plinkhapmap.bim files that can be downloded here. My problem is: when I run the code below, it creates test1.gds file and when I delete the test1.gds file and want to re-run the code it generates this error Error in createfn.gds(out.gdsfn) :
The file 'mypath/Dropbox/Public/SNPRelate/test2.gds' has been created or opened.
When I change the file name test1.gds to test2.gds or some new name for output file, I don't get this error. How do I close this file completely so I can re-run the code and get the output file (keeping the same file name) again?
library("SNPRelate")
bed.fn <- "plinkhapmap.bed"
fam.fn <- "plinkhapmap.fam"
bim.fn <- "plinkhapmap.bim"
snpgdsBED2GDS(bed.fn, fam.fn, bim.fn, "test1.gds")
snpgdsSummary("test1.gds")
genofile <- snpgdsOpen("test1.gds")
snpset <- snpgdsLDpruning(genofile, ld.threshold=0.2)
snpset.id <- unlist(snpset)