- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试保存在 shiny
应用程序中创建的 ggplot2
对象。基本上,此代码允许上传 .xlsx
文件,并在从某些选项中进行选择后创建绘图。然后我添加了一个下载按钮,以便用户可以下载他们创建的绘图。我正在使用 downloadHandler()
和 grDevices::png()
。按下按钮确实会下载 .png
文件,但当我打开它时,它只是一个空白的白色方 block 。我是如此接近!任何帮助将非常感激。谢谢。
#initialize
library(shiny)
library(ggplot2)
library(purrr)
library(dplyr)
library(plotly)
#example data
data(iris)
#make some factors
#easier to let ggplot2 control plotting (color, fill) based on type
data(mtcars)
uvals<-sapply(mtcars,function(x){length(unique(x))})
mtcars<-map_if(mtcars,uvals<4,as.factor) %>%
as.data.frame()
#plotting theme for ggplot2
.theme<- theme(
axis.line = element_line(colour = 'gray', size = .75),
panel.background = element_blank(),
plot.background = element_blank()
)
# UI for app
ui<-(pageWithSidebar(
# title
headerPanel("Select Options"),
#input
sidebarPanel
(
# Input: Select a file ----
fileInput("file1", "Choose xlsx File",
multiple = TRUE,
accept = c(".xlsx")),
# Horizontal line ----
tags$hr(),
#download button
fluidPage(downloadButton('down')),
# Input: Select what to display
selectInput("dataset","Data:",
choices =list(iris = "iris", mtcars = "mtcars",
uploaded_file = "inFile"), selected=NULL),
selectInput("xaxis","X axis:", choices = NULL),
selectInput("yaxis","Y axis:", choices = NULL),
selectInput("fill","Fill:", choices = NULL),
selectInput("group","Group:", choices = NULL),
selectInput("plot.type","Plot Type:",
list(boxplot = "boxplot", histogram = "histogram", density = "density", bar = "bar")
),
checkboxInput("show.points", "show points", TRUE)
),
# output
mainPanel(
h3(textOutput("caption")),
#h3(htmlOutput("caption")),
uiOutput("plot") # depends on input
)
))
# shiny server side code for each call
server<-function(input, output, session){
#update group and
#variables based on the data
observe({
#browser()
if(!exists(input$dataset)) return() #make sure upload exists
var.opts<-colnames(get(input$dataset))
updateSelectInput(session, "xaxis", choices = var.opts)
updateSelectInput(session, "yaxis", choices = var.opts)
updateSelectInput(session, "fill", choices = var.opts)
updateSelectInput(session, "group", choices = var.opts)
})
output$caption<-renderText({
switch(input$plot.type,
"boxplot" = "Boxplot",
"histogram" = "Histogram",
"density" = "Density plot",
"bar" = "Bar graph")
})
output$plot <- renderUI({
plotOutput("p")
})
#get data object
get_data<-reactive({
if(!exists(input$dataset)) return() # if no upload
check<-function(x){is.null(x) || x==""}
if(check(input$dataset)) return()
obj<-list(data=get(input$dataset),
yaxis=input$yaxis,
xaxis=input$xaxis,
fill=input$fill,
group=input$group
)
#require all to be set to proceed
if(any(sapply(obj,check))) return()
#make sure choices had a chance to update
check<-function(obj){
!all(c(obj$yaxis,obj$xaxis, obj$fill,obj$group) %in% colnames(obj$data))
}
if(check(obj)) return()
obj
})
#plotting function using ggplot2
output$p <- renderPlot({
plot.obj<-get_data()
#conditions for plotting
if(is.null(plot.obj)) return()
#make sure variable and group have loaded
if(plot.obj$yaxis == "" | plot.obj$xaxis =="" | plot.obj$fill ==""| plot.obj$group =="") return()
#plot types
plot.type<-switch(input$plot.type,
"boxplot" = geom_boxplot(),
"histogram" = geom_histogram(alpha=0.5,position="identity"),
"density" = geom_density(alpha=.75),
"bar" = geom_bar(position="dodge")
)
if(input$plot.type=="boxplot") { #control for 1D or 2D graphs
p<-ggplot(plot.obj$data,
aes_string(
x = plot.obj$xaxis,
y = plot.obj$yaxis,
fill = plot.obj$fill,# let type determine plotting
group = plot.obj$group
)
) + plot.type
if(input$show.points==TRUE)
{
p<-p+ geom_point(color='black',alpha=0.5, position = 'jitter')
}
} else {
p<-ggplot(plot.obj$data,
aes_string(
x = plot.obj$xaxis,
fill = plot.obj$fill,
group = plot.obj$group
#color = as.factor(plot.obj$group)
)
) + plot.type
}
p<-p+labs(
fill = input$fill,
x = "",
y = input$yaxis
) +
.theme
print(p)
})
# set uploaded file
upload_data<-reactive({
inFile <- input$file1
if (is.null(inFile))
return(NULL)
#could also store in a reactiveValues
read_excel(inFile$datapath)
})
observeEvent(input$file1,{
inFile<<-upload_data()
})
# downloadHandler contains 2 arguments as functions, namely filename, content
output$down <- downloadHandler(
filename = function() {
paste(input$dataset,"png" , sep=".")
},
# content is a function with argument file. content writes the plot to the device
content = function(file) {
png(file) # open the png device
p # for GGPLOT
dev.off() # turn the device off
}
)
}
# Create Shiny app ----
shinyApp(ui, server)
最佳答案
我以评论的形式回复,但我意识到这有点难以理解,因此我将发布完整的修改后的代码以使其更清晰。
我通常建议不要在 render*()
调用中执行过多操作。相反,在单独的 reactive()
对象中设置您要创建的对象,然后在 renderPlot()
中引用该对象。在下面的代码中,我将创建绘图的所有代码移动到名为 p
的 reactive
对象中,然后我可以在 ggsave()< 中引用它
用于下载。
#initialize
library(shiny)
library(ggplot2)
library(purrr)
library(dplyr)
library(plotly)
#example data
data(iris)
#make some factors
#easier to let ggplot2 control plotting (color, fill) based on type
data(mtcars)
uvals<-sapply(mtcars,function(x){length(unique(x))})
mtcars<-map_if(mtcars,uvals<4,as.factor) %>%
as.data.frame()
#plotting theme for ggplot2
.theme<- theme(
axis.line = element_line(colour = 'gray', size = .75),
panel.background = element_blank(),
plot.background = element_blank()
)
# UI for app
ui<-(pageWithSidebar(
# title
headerPanel("Select Options"),
#input
sidebarPanel
(
# Input: Select a file ----
fileInput("file1", "Choose xlsx File",
multiple = TRUE,
accept = c(".xlsx")),
# Horizontal line ----
tags$hr(),
#download button
fluidPage(downloadButton('down')),
# Input: Select what to display
selectInput("dataset","Data:",
choices =list(iris = "iris", mtcars = "mtcars",
uploaded_file = "inFile"), selected=NULL),
selectInput("xaxis","X axis:", choices = NULL),
selectInput("yaxis","Y axis:", choices = NULL),
selectInput("fill","Fill:", choices = NULL),
selectInput("group","Group:", choices = NULL),
selectInput("plot.type","Plot Type:",
list(boxplot = "boxplot", histogram = "histogram", density = "density", bar = "bar")
),
checkboxInput("show.points", "show points", TRUE)
),
# output
mainPanel(
h3(textOutput("caption")),
#h3(htmlOutput("caption")),
uiOutput("plot") # depends on input
)
))
# shiny server side code for each call
server<-function(input, output, session){
#update group and
#variables based on the data
observe({
#browser()
if(!exists(input$dataset)) return() #make sure upload exists
var.opts<-colnames(get(input$dataset))
updateSelectInput(session, "xaxis", choices = var.opts)
updateSelectInput(session, "yaxis", choices = var.opts)
updateSelectInput(session, "fill", choices = var.opts)
updateSelectInput(session, "group", choices = var.opts)
})
output$caption<-renderText({
switch(input$plot.type,
"boxplot" = "Boxplot",
"histogram" = "Histogram",
"density" = "Density plot",
"bar" = "Bar graph")
})
output$plot <- renderUI({
plotOutput("p")
})
#get data object
get_data<-reactive({
if(!exists(input$dataset)) return() # if no upload
check<-function(x){is.null(x) || x==""}
if(check(input$dataset)) return()
obj<-list(data=get(input$dataset),
yaxis=input$yaxis,
xaxis=input$xaxis,
fill=input$fill,
group=input$group
)
#require all to be set to proceed
if(any(sapply(obj,check))) return()
#make sure choices had a chance to update
check<-function(obj){
!all(c(obj$yaxis,obj$xaxis, obj$fill,obj$group) %in% colnames(obj$data))
}
if(check(obj)) return()
obj
})
p <- reactive({
plot.obj<-get_data()
#conditions for plotting
if(is.null(plot.obj)) return()
#make sure variable and group have loaded
if(plot.obj$yaxis == "" | plot.obj$xaxis =="" | plot.obj$fill ==""| plot.obj$group =="") return()
#plot types
plot.type<-switch(input$plot.type,
"boxplot" = geom_boxplot(),
"histogram" = geom_histogram(alpha=0.5,position="identity"),
"density" = geom_density(alpha=.75),
"bar" = geom_bar(position="dodge")
)
if(input$plot.type=="boxplot") { #control for 1D or 2D graphs
p<-ggplot(plot.obj$data,
aes_string(
x = plot.obj$xaxis,
y = plot.obj$yaxis,
fill = plot.obj$fill,# let type determine plotting
group = plot.obj$group
)
) + plot.type
if(input$show.points==TRUE)
{
p<-p+ geom_point(color='black',alpha=0.5, position = 'jitter')
}
} else {
p<-ggplot(plot.obj$data,
aes_string(
x = plot.obj$xaxis,
fill = plot.obj$fill,
group = plot.obj$group
#color = as.factor(plot.obj$group)
)
) + plot.type
}
p<-p+labs(
fill = input$fill,
x = "",
y = input$yaxis
) +
.theme
print(p)
})
#plotting function using ggplot2
output$p <- renderPlot({
p()
})
# set uploaded file
upload_data<-reactive({
inFile <- input$file1
if (is.null(inFile))
return(NULL)
#could also store in a reactiveValues
read_excel(inFile$datapath)
})
observeEvent(input$file1,{
inFile<<-upload_data()
})
# downloadHandler contains 2 arguments as functions, namely filename, content
output$down <- downloadHandler(
filename = function() {
paste(input$dataset,"png" , sep=".")
},
# content is a function with argument file. content writes the plot to the device
content = function(file) {
ggsave(file, p())
}
)
}
# Create Shiny app ----
shinyApp(ui, server)
关于r - 从 Shiny 保存 ggplot 会给出空白 png 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52528499/
我正在寻找一种经济合理的解决方案来长时间存储图片。我读到 PNG 文件格式,它与 JPEG 相比具有优越的特性,即在这些类别中: 无专利、无许可、无版税 无质量损失 尚未压缩 我有很多来自 Photo
关闭。这个问题是off-topic .它目前不接受答案。 想改善这个问题吗? Update the question所以它是 on-topic对于堆栈溢出。 9年前关闭。 Improve this q
我怎么能用 FFMEG 做到这一点? 输入 : 背景图片:background.png 图片帧列表:image_001.png,image_002.png ...(每张图片为一帧) 输出:所有帧都有背
$ cat png.ll ./packages/apps/Mms/res/mipmap-hdpi/ic_launcher_smsmms.png ./packages/apps/Mms/res/draw
这个问题在这里已经有了答案: Natural Sort Order in C# (18 个答案) 关闭 7 年前。 这是我的代码: private void Method1() { int
我一直在考虑用 Webp 图像替换我的 Android 应用程序中的 png 文件以减小 APK 大小。 虽然结果不错,但我想知道我是否使用了一些 png 转换器/压缩器,并且能够将尺寸减小到比我为
在 gnuplot-4.2.6 中,我可以使用 set term png medium x000000 xffffff set output 'file.png' plot x 这将生成一个带有黑色背
背景: 我正在努力使一堆 PNG 尽可能小。我正在使用诸如 PngOut、PngCrush 和 OptiPng 之类的工具。 问题: 我遇到了一个大小为 1434 KB 但只有 230 x 230 像
我正在使用 ImageMagick 调整图像大小。如果我传递 -resize WxH 选项,它会按预期运行。但是如果我通过 -resize WxH! (在调整大小时忽略纵横比),一些图像,尤其是 PN
如何访问/删除 PNG 元数据? 我正在寻找 Mac 应用程序或 PHP 代码段。 最佳答案 抱歉发布了一个 Windows 软件,但如果你没有找到任何对 MAC 有用的东西,那就是 TweakPNG
到目前为止似乎没有任何效果。我看到了 pnginfo以下消息: concept_Sjet_dream6.png... Image Width: 200 Image Length: 240 Bi
我有一个带有 Alpha channel (即透明度)的 PNG 图像,我需要创建将图像层合成到白色背景上的版本。我想使用可编写脚本的命令,使用 CLI 工具(例如 Image Magick)将 PN
我是初学者。我昨天问了一个类似的问题,但不知何故被否决了。所以这次我尽量简化问题。 带有 alpha png 的 24 位与 32 位 png 相同吗? 非常感谢您的一些提示。 最佳答案 没有“24
我有这个带点的荷兰 pdf 图像: pdf image of the netherlands with dots 当我尝试将此 pdf 转换为 png 图像时,使用 pdftools和 png像这样:
我在我的启动图像通用项目中添加了“Default.png,Default-568h@2x.png,Default@2x.png”这三个文件,我有三个不同的图像,分辨率与苹果中提到的完全相同文档,适用于
我在 Python 中使用 google app engine 并有几个静态 .png 图像文件,但它们都以“image/x-png”内容类型提供。这是一个问题,当我使用像 chrome 这样的浏览器
我做了一个 python 脚本,该脚本设法根据特定模式解散乱序(png)图像,该 python 脚本使用 ffmpeg 并进行 12 次编码来解乱它(通过裁剪特定部分并将其粘贴到现有图片上)。 因此,
我有一个 PNG 图像文件。我想将其转换为 GeoTiff。我安装了 QGIS 软件,但无法使用它,也不知道如何对图像进行地理配准。请帮我。有没有在线软件? 最佳答案 这是一个非常好的教程,其中包含有
我有一堆使用我编写的 Java 图表工具创建的图表 - 它们主要是黑白图表,带有浅绿色的块,偶尔还有其他颜色。它们当前被保存为 JPG 文件,我想将它们插入到我准备按需打印的书中。 这本书是一个 Op
关闭。这个问题不满足Stack Overflow guidelines .它目前不接受答案。 想改善这个问题吗?更新问题,使其成为 on-topic对于堆栈溢出。 7年前关闭。 Improve thi
我是一名优秀的程序员,十分优秀!