从闪亮保存ggplot给出空白png文件

时间:2018-09-27 02:24:35

标签: r ggplot2 shiny png

我正在尝试保存在 shiny 应用程序中创建的 ggplot2 对象。基本上,此代码允许上传 .xlsx 文件,并从某些选项中进行选择后创建图。然后,我添加了一个下载按钮,以便用户可以下载他们创建的图。我正在使用 downloadHandler() grDevices :: png()。按下按钮确实会导致下载 .png 文件,但是当我打开它时,它只是一个空白的白色正方形。我好亲密!任何帮助将非常感激。谢谢。

  #initialize
图书馆(闪亮)
库(ggplot2)
图书馆(purrr)
图书馆(dplyr)
图书馆(密谋)


#示例数据
数据(虹膜)

#制定一些因素
#easier让ggplot2根据类型控制绘图(颜色,填充)
数据(mtcars)
uvals <-sapply(mtcars,function(x){length(unique(x))})
mtcars <-map_if(mtcars,uvals <4,as.factor)%>%
  as.data.frame()


#gggglot2主题
.theme <-主题(
  axis.line = element_line(colour ='gray',size = .75),
  panel.background = element_blank(),
  plot.background = element_blank()
)


#应用界面
ui <-(pageWithSidebar(
  #标题
  headerPanel(“选择选项”),

  #input
  sidebarPanel
  (
    #输入:选择一个文件----

    fileInput(“ file1”,“选择xlsx文件”,
              多个= TRUE,
              接受= c(“。xlsx”)),


    #水平线----
    标签$ hr(),


    #download按钮
     fluidPage(downloadButton('down')),

    #输入:选择要显示的内容
    selectInput(“ dataset”,“ Data:”,
                选择= list(iris =“ iris”,mtcars =“ mtcars”,
                              upload_file =“ inFile”),selected = NULL),
    selectInput(“ xaxis”,“ X轴:”,options = NULL),
    selectInput(“ yaxis”,“ Y轴:”,options = NULL),
    selectInput(“ fill”,“ Fill:”,options = NULL),
    selectInput(“ group”,“ Group:”,options = NULL),
    selectInput(“ plot.type”,“绘图类型:”,
                list(boxplot =“ boxplot”,直方图=“ histogram”,密度=“密度”,bar =“ bar”)
    ),
    checkboxInput(“ show.points”,“显示点”,TRUE)
  ),

  #输出
  mainPanel(
    h3(textOutput(“ caption”)),
    #h3(htmlOutput(“ caption”)),
    uiOutput(“ plot”)#取决于输入
  )
))


#每个呼叫的闪亮服务器端代码
服务器<功能(输入,输出,会话){

  #update组和
  #基于数据的变量
  观察({
    #browser()
    if(!exists(input $ dataset))return()#确保上传存在
    var.opts <-colnames(get(input $ dataset))
    updateSelectInput(session,“ xaxis”,options = var.opts)
    updateSelectInput(session,“ yaxis”,options = var.opts)
    updateSelectInput(session,“ fill”,options = var.opts)
    updateSelectInput(session,“ group”,options = var.opts)
  })

  输出$标题<-renderText({
    开关(input $ plot.type,
           “ boxplot” =“ Boxplot”,
           “ histogram” =“直方图”,
           “密度” =“密度图”,
           “ bar” =“条形图”)
  })


  output $ plot <-renderUI({
    plotOutput(“ p”)
  })

  #获取数据对象
  get_data <-reactive({

    if(!exists(input $ dataset))return()#如果没有上传

    check <-function(x){is.null(x)|| x ==“”}
    if(check(input $ dataset))return()

    obj <-list(data = get(input $ dataset),
              yaxis = input $ yaxis,
              xaxis = input $ xaxis,
              填充=输入$填充,
              组=输入$组
    )

    #require全部设为继续
    if(任何(sapply(obj,check)))return()
    #确保选择有机会更新
    检查<功能(obj){
      !all(c(obj $ yaxis,obj $ xaxis,obj $ fill,obj $ group)%in%名称(obj $ data))
    }

    if(check(obj))return()


    对象

  })

  #使用ggplot2进行绘图
  输出$ p <-renderPlot({

    plot.obj <-get_data()

    #绘图条件
    if(is.null(plot.obj))return()

    #确保变量和组已加载
    if(plot.obj $ yaxis ==“” | plot.obj $ xaxis ==“” | plot.obj $ fill ==“” | plot.obj $ group ==“”)return()

    #图类型
    plot.type <-switch(input $ plot.type,
                      “ boxplot” = geom_boxplot(),
                      “直方图” = geom_histogram(alpha = 0.5,position =“ identity”),
                      “密度” = geom_density(alpha = .75),
                      “ bar” = geom_bar(position =“ dodge”)
    )


    if(input $ plot.type ==“ boxplot”){#控制一维或二维图形
      p <-ggplot(plot.obj $ data,
                aes_string(
                  x = plot.obj $ xaxis,
                  y = plot.obj $ yaxis,
                  fill = plot.obj $ fill,#让类型确定绘图
                  组= plot.obj $ group
                )
      )+ plot.type

      如果(input $ show.points == TRUE)
      {
        p <-p + geom_point(颜色='黑色',alpha = 0.5,位置='抖动')
      }

    }其他{

      p <-ggplot(plot.obj $ data,
                aes_string(
                  x = plot.obj $ xaxis,
                  填充= plot.obj $填充,
                  组= plot.obj $ group
                  #color = as.factor(plot.obj $ group)
                )
      )+ plot.type
    }

    p <-p + labs(
      填充=输入$填充,
      x =“”,
      y =输入$ yaxis
    )+
      。主题
    打印(p)
  })

  #设置上传文件
  upload_data <-active({

    inFile <-输入$ file1

    如果(is.null(inFile))
      返回(NULL)

    #也可以存储在reactValues中
    read_excel(inFile $ datapath)
  })

  watchEvent(input $ file1,{
    inFile <<-upload_data()
  })

  #downloadHandler包含2个参数作为函数,即文件名,内容
  output $ down <-downloadHandler(
    文件名= function(){
      paste(input $ dataset,“ png”,sep =“。”)
    },
    #content是带有参数文件的函数。内容将情节写入设备
    内容=函数(文件){
      png(file)#打开png设备
      GGPLOT的p#
      dev.off()#关闭设备

    }
  )

}

#创建闪亮的应用程序----
ShinyApp(用户界面,服务器)
 

1 个答案:

答案 0 :(得分:4)

我以评论的形式回应,但我知道这样做有些困难,因此我将发布完整的修订代码以使其更加清晰。

我通常建议在render*()调用中不要做太多事情。而是在单独的reactive()对象中设置要创建的对象,并仅在renderPlot()中引用该对象。在下面的代码中,我将创建情节的所有代码移到名为reactive的{​​{1}}对象中,然后可以在p中引用它进行下载。

ggsave()