【发布时间】:2020-01-12 14:10:15
【问题描述】:
我是 RShiny 的新手。我在 R 中创建了一个模型,并希望使用 RShiny 使其用户友好。
它绘制了一些直方图和移动平均图(目前正在工作),但我也希望能够在单击“模拟”按钮并触发反应值时下载我的模拟。
由于我使用了 reactiveValues(),并且我使用了一些单独的信息进行绘图,因此我从每次点击“模拟按钮”时获得的反应值创建了“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 = ";")
})
}
我希望输出具有正确的列(以及列名,但是当我尝试添加它时,它会返回以下错误):
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
如何解决?
【问题讨论】:
-
更新:代码现在可以工作了。我只是在 my.download 的每个向量中单独使用 as.numeric()。然后我在 write.table 中将 row.names 设置为 FALSE。