如何根据RShiny中的反应值下载数据?

时间:2019-09-10 19:36:13

标签: r shiny reactive

我是RShiny的新手。我在R中创建了一个模型,并希望使用RShiny使其易于使用。

它绘制了一些直方图和移动平均图(当前有效),但是当我单击“模拟”按钮并触发反应性值时,我还希望能够下载我的模拟。

由于我正在使用reactValues(),并且使用一些单独的信​​息进行绘图,因此,我每次点击“模拟按钮”时都会从获得的反应值中创建“ my.download”。但是可下载的.csv文件为我提供了两列(我使用具有5个向量的cbind),并且绝对是奇数。如果我模拟1000个案例,它将给我5000行。如果是2000例,10000行等。

这是我的代码的一部分,与要转换数据的.csv文件有关。

library(data.table)
library(shiny)
library(ggplot2)
### My functions ###

claims.frequency = function(iterations, dist, lambda, size, prob){
  freq = rep(NA,iterations)
  if(dist == "Poisson"){freq_dt = data.table(i=1:iterations)[,list(freq=rpois(n=1,lambda=lambda)),by=i]}
  else if(dist == "Negative Binomial"){freq_dt = data.table(i=1:iterations)[,list(freq=rnbinom(n=1,size=size,prob=prob)),by=i]}
  return(freq_dt$freq)
}

claims.severity <- function(frequency,dist,meanlog,sdlog,shape,scale,rate,percentile){
  sever = rep(NA,length(frequency))
  moving_average = rep(NA,length(frequency))
  moving_percentile = rep(NA,length(frequency))
  df = rep(NA,length(frequency))
  if(dist=="Lognormal"){sever_dt=data.table(i=1:length(frequency))[,list(sever=sum(rlnorm(n=frequency[i],meanlog=meanlog,sdlog=sdlog))),by=i]}
  else if(dist=="Gamma"){sever_dt=data.table(i=1:length(frequency))[,list(sever=sum(rgamma(n=frequency[i],shape=shape,rate=rate))),by=i]}
  else if(dist=="Exponential"){sever_dt=data.table(i=1:length(frequency))[,list(sever=sum(rexp(n=frequency[i],rate=1/rate))),by=i]}
  else if(dist=="Weibull"){sever_dt=data.table(i=1:length(frequency))[,list(sever=sum(rweibull(n=frequency[i],shape=shape,scale=scale))),by=i]}

  moving_average_dt = data.table(i=1:length(frequency))[,list(moving_average=mean(sever_dt$sever[1:i])),by=i]
  moving_percentile_dt = data.table(i=1:length(frequency))[,list(moving_percentile=quantile(sever_dt$sever[1:i],probs=percentile)),by=i]

  df = cbind(frequency,sever_dt$sever,moving_average_dt$moving_average,moving_percentile_dt$moving_percentile)
  colnames(df) = c("# Claims","Aggregate Claims Value","Moving Average","Moving Percentile")
  return(as.data.frame(df))
}

### UI ###

ui <- fluidPage(
  titlePanel('Simulator'),
  sidebarPanel(
    sliderInput(inputId="n", "Iterations", value = 250500, min = 1000, max = 500000, step = 500, round = TRUE, ticks = TRUE),
    radioButtons("freq.dist", "Frequency Distributions:",
                 c("Poisson (\\(\\lambda\\))" = "P",
                   "Negative Binomial (n, p)" = "B")),
    numericInput("paramfreq1","\\(\\lambda\\), if Poisson; or n, if Negative Binomial",0),
    numericInput("paramfreq2","p",0),
    radioButtons("sever.dist", "Severity Distributions:",
                 c("Lognormal (\\(\\mu\\ ,  \\sigma\\))" = "L",
                   "Gamma (\\(\\alpha\\ ,  \\beta\\))" = "G",
                   "Exponential (\\(\\lambda\\))" = "E",
                   "Weibull (\\(\\alpha\\ ,  \\beta\\))" = "W")),
    numericInput("paramsever1","\\(\\mu\\), if Lognormal; \\(\\alpha\\), if Gamma or Weibull; or \\(\\lambda\\), if Exponential",0),
    numericInput("paramsever2","\\(\\sigma\\), if Lognormal; or \\(\\beta\\), if Gamma or Weibull",0),
    actionButton("simulate","Simulate"),
    downloadButton('downloadData', 'Download')
  )
)

### SERVER ###

server <- function(input, output) {

  rv <- reactiveValues(my.freq = 0,
                       my.total.claims = 0,
                       my.moving.average = 0,
                       my.moving.percentile = 0,
                       my.download = 0)

  observeEvent(input$simulate,
               {
                 my.freq <- switch(input$freq.dist,
                                   "P" = claims.frequency(iterations = input$n,
                                                          dist = "Poisson",
                                                          lambda = input$paramfreq1),
                                   "B" = claims.frequency(iterations = input$n,
                                                          dist = "Negative Binomial",
                                                          size = input$paramfreq1,
                                                          prob = input$paramfreq2))

                 my.sever <- switch(input$sever.dist,
                                    "L" = claims.severity(frequency = my.freq,
                                                          dist = "Lognormal",
                                                          meanlog = input$paramsever1,
                                                          sdlog = input$paramsever2,
                                                          percentile = .995),
                                    "G" = claims.severity(frequency = my.freq,
                                                          dist = "Gamma",
                                                          shape = input$paramsever1,
                                                          rate = input$paramsever2,
                                                          percentile = .995),
                                    "E" = claims.severity(frequency = my.freq,
                                                          dist = "Exponential",
                                                          rate = input$paramsever1,
                                                          percentile = .995),
                                    "W" = claims.severity(frequency = my.freq,
                                                          dist = "Weibull",
                                                          shape = input$paramsever1,
                                                          scale = input$paramsever2,
                                                          percentile = .995))

                 rv$my.freq <- as.numeric(my.freq)
                 rv$my.total.claims <- as.numeric(my.sever$`Aggregate Claims Value`)
                 rv$my.moving.average <- as.numeric(my.sever$`Moving Average`)
                 rv$my.moving.percentile <- as.numeric(my.sever$`Moving Percentile`)
                 rv$my.download <- (as.numeric(cbind(1:length(my.freq), my.sever$`# Claims`,my.sever$`Aggregate Claims Value`,my.sever$`Moving Average`,my.sever$`Moving Percentile`))) ### PROBLEM HERE ###
               }
  )

  output$downloadData <- downloadHandler(
    filename = function(){
      paste('simulation-', Sys.time(), '.csv', sep='')
    },
    content = function(file){
      write.table(x = rv$my.download, file, dec = "," , sep = ";")
    })
}

我希望输出具有正确的列(也包括colnames,但是当我尝试添加它时,它会返回以下错误):

Warning: Error in colnames<-: attempt to set 'colnames' on an object with less than two dimensions

但是我的.csv文件类似于:https://i.imgur.com/zRKLetW.png

预期输出为:https://i.imgur.com/7PJNBny.png

如何解决?

1 个答案:

答案 0 :(得分:0)

我不确定这是否是整个问题,但我认为部分问题是您将对cbind()中的as.numeric()的调用包装了起来

例如     as.numeric(cbind(1:3, 4:6)) 返回数字矢量,其中     cbind(1:3, 4:6)返回一个矩阵。您还可以使用data.frame(col_name1 = vector1, col_name2 = vector2...)来确保rv $ mydownload的导出格式正确。