首页 > 解决方案 > 尝试学习 RShiny 非常糟糕(inputDate、actionButton、eventReactive、datetable)

问题描述

我尝试学习 RShiny,尽管观看了几个 youtube 视频和阅读文档,但显然我缺少一些关于闪亮操作的基本概念,需要一些帮助来简化它。这也是我第一次发帖,所以尽量不要笑太多!

主要目标:创建一个应用程序,用户在其中指定日期并单击操作按钮以获取存储的数据文件并执行一系列自动数据清理程序,最后将更新的文件保存回提取文件的原始文件夹。稍后我将添加更多更复杂的任务,但尝试从简单开始。

这是日期选择的预期示例

我没有看到如何上传 excel 文件附件,所以希望这可以显示数据。基本上有 5 行初始的垃圾要删除。然后是各种事情,例如重命名列中的值、删除列、子集数据等。

Junk                                    
that                                    
I                                   
must                                    
remove                                  
Task ID Center  Facility    Money   P   C   S   CC  FC  U
1   C   Bad Name2   1400    2   3   1   2   1   3
2   C   N   1400    2   3   2   4   1   3
3   B   XYZ 2700    2   5   3   3   1   2
4   A   U   150 1   1   1   3   1   1
5   B   XYZ 2000    1   5   5   4   1   4
6   A   U   1500    1   3   1   2   1   3
7   C   D   75  1   1   1   2   1   1
8   B   Ten 60  5   1   4   4   1   1
9   B   XYZ 450 3   2   1   2   1   2
10  B   XYZ 80  2   1   1   1   1   1
11  B   XYZ 65  3   1   1   2   1   2
12  B   Ten 60  2   1   1   2   1   1
13  B   Ten 35  3   1   1   2   1   1
14  C   Bad Name    20  1   1   1   1   1   1

我有两组要上传的 R 代码,第一组具有我将在其中运行的普通 R 脚本,我手动定义 date<-"2021-07-15" 此代码运行良好。我在这个示例 R 脚本中包含了我会做的各种清洁类型的简单示例。

require(openxlsx)
require(readxl)

# set run date #
date<-c("2021-07-15")

mon<-month.abb[as.numeric(substr(date, 6, 7))]

# set directory #
setwd(paste("C:\\Users\\Desktop\\Test\\",mon,sep=""))


wb<-createWorkbook(paste("testdata",date,sep = " "))
df<-read_excel(paste("testdata ",date,".xlsx",sep=""),sheet = "test", skip = 5)

# Remove FC
df<-df[,-9]

# Fix Names 
df$Facility[df$Facility=="XYZ"]<-"ZYX"
df$Facility[df$Facility=="Bad Name2"]<-"Good Name2"

df$Facility<-as.factor(df$Facility)
df$P<-as.numeric(df$P)

# subset tasks worth less than 1000 #
small<-df[which(df$Money < 1000),]

# data entry check
for(i in 1:nrow(small))
{
  if(small$Money[i]< 100)
  { small$C[i] = 1}
  if(small$Money[i]>= 100 && small$Money[i] < 200)
  { small$C[i] = 2}
}

# subset tasks worth more than 1000
big<-df[which(df$Money >= 1000),]

# create worksheets to save data #
addWorksheet(wb,"small")
addWorksheet(wb,"big")

writeData(wb,"small",small)
writeData(wb,"big",big)

file<-paste("testdata",date,"Edited.xlsx",sep=" ")

saveWorkbook(wb,file,overwrite = TRUE)

下面是我尝试创建一个 Rshiny 应用程序的尝试,该应用程序可能以十几种不同的方式出错。

require(shiny)
require(readxl)
require(openxlsx)
require(DT)

ui <- fluidPage(
  dateInput("datePull", "Date:", format = "yyyy-mm-dd", value = Sys.Date()),
  actionButton(inputId = "button", label = "Update Date"),
  textOutput("test"),
  dataTableOutput("mytable")
)
  
server <- function(input, output){
  
  # is date even saving correctly? if I run date() in the console I always get something like 
  # "Fri Jul 16 11:13:12 2021"
  # despite specifying a different starting value or a specified format
  date<-eventReactive(input$button, {input$datePull[1]})

  # Everything I have tried to create "mon" without using eventReactive throws an error; 
  # repetitve use of eventReactive to me screams this is the wrong way to do this
  mon<-eventReactive(input$button,{month.abb[as.numeric(substr(date(), 6, 7))]})         
  
  # at this point it is just a repetative problem because any line that calls date() or mon() 
  # errors with a statement along the lines of "this must be reactive..."
  dir<-eventReactive(input$button,{setwd(paste("C:\\Users\\Desktop\\Test\\",mon(),sep=""))})
  
  wb<-eventReactive(input$button,{createWorkbook(paste("testdata",date,sep = " "))})
  df<-eventReactive(input$button,{read_excel(paste("testdata ",date,".xlsx",sep=""),sheet = "test", skip = 5)})
  
  # trying to remove column 
  df<-eventReactive(input$button,{df[,-9]})
          
  output$test <- renderText({paste("Pull mon is ",mon())})

  # Warning: Error in $: object of type 'closure' is not subsettable
  output$mytable = renderDataTable({df()})

}
shinyApp(ui, server)

感谢任何帮助解释如何正确使用 eventReactive 函数及其输出,如 date()

标签: rshinyaction-button

解决方案


由于我们无权访问您的桌面,因此您的代码不可重现。另外,恕我直言,我认为您对 Shiny(或可能是 R 本身)的工作方式存在根本性的误解。在继续之前,请学习并理解一些在线教程(RStudio 网站是一个很好的起点)。

这是一个显示随机生成的数据集的 MWE,当且仅当单击操作按钮时,该数据集才会更新。我假设您希望立即显示一些数据,但如果您希望actionButton在第一次按下之前有一个空白的 GUI,那么可以这样做。

正如我在评论中所写,关键是使用reactive(),而不是eventReactive().

# Use library to load packages, not require
library(shiny)
library(tidyverse)

ui <- fluidPage(
    dateInput("datePull", "Date:", format = "yyyy-mm-dd", value = Sys.Date()),
    actionButton(inputId = "button", label = "Update Date"),
    textOutput("test"),
    dataTableOutput("mytable")
)

server <- function(input, output) {
  # It's bad practice to use a built-in as a variable name, so I have changed the variable name
  selectedDate <- reactive({
      # Introduce a dependency on the actionButton
      input$button
      # Use isolate to ensure that updates occur only when button is clicked
      isolate({ input$datePull[1] })
 })
    
  # Using lubridate would be more robust and result in more intuitive code
  mon <- reactive({
    x <- month.abb[as.numeric(substr(selectedDate(), 6, 7))]
  })         
    
  output$test <- renderText({
    req(mon())
        
    paste("Pull mon is ",mon())
  })
  
  # Only dependency here is on selectedDate, so updates occur only when selectedDate
  # changes.  That is, when the actionButton is clicked
  df <- reactive ({
      # Replace this random data with the contents of your date-dependent CSV.
      tibble(
          SelectedDate= seq(selectedDate(), length.out=10, by=1),
          Value=rnorm(10),
          UnwantedValue=rnorm(10)
      ) %>% 
      select(-UnwantedValue)
  })
  
  output$mytable = renderDataTable({df()})
}

shinyApp(ui = ui, server = server)

推荐阅读