在R Shiny图上选择不同的彩色线

时间:2019-02-03 16:33:12

标签: r shiny

我正在尝试创建一个闪亮的应用程序,该应用程序最多显示2条不同的彩色线条,具体取决于用户选择查看的颜色。但是,我一直收到“意外字符”错误。

我认为问题出在以下代码的selectInput(inputId = "z", label = "Source", choices = c("social_media", "google_ads"), selected = c("social_media", "google_ads"), multiple = TRUE)行中,因为当我将choicesselected替换为source时,图形似乎可以正常工作(尽管不允许用户选择和查看其他选项。

df是一个看起来像这样的数据框:

av_purchase_count     days_since_first_use    source
2                     1                       social_media
5                     2                       social_media
4                     1                       google_ads
6                     2                       google_ads

...这是我尝试过的代码:

library(shiny)
library(ggplot2)
df <- read_xlsx("~/df.xlsx")

ui <- fluidPage(

   titlePanel("df"),

   sidebarLayout(
      sidebarPanel(
         selectInput(inputId = "x", label = "Days since first use", choices = "days_since_first_use", selected = "days_since_first_use"),
         selectInput(inputId = "y", label = "Average Purchase Count", choices = "av_purchase_count", selected = "av_purchase_count"),
         selectInput(inputId = "z", label = "Source", choices = c("social_media", "google_ads"), selected = c("social_media", "google_ads"), multiple = TRUE)
      ),

      mainPanel(
         plotOutput("scatterplot")
      )
   )
)

server <- function(input, output) {

   output$scatterplot <- renderPlot({
      # generate bins based on input$bins from ui.R
     ggplot(data = df, aes_string(x = input$x, y = input$y, colour = input$z)) +
       geom_point()
      })
}

shinyApp(ui = ui, server = server)

我希望最终图形允许用户选择是否要查看google_adssocial_media或两者(默认情况下都是)的结果。

非常感谢,希望这有道理。

1 个答案:

答案 0 :(得分:1)

您可以通过实现

class SomeButton: UIButton {
    var titleFont: UIFont! = nil
    var textSize: CGFloat = 0
    let imageWidth: CGFloat = 20
    let buttonHeight: CGFloat = 30

    override init(frame: CGRect) {
        super.init(frame: frame)
        self.titleFont = titleLabel!.font
        self.setTitle("here", for: .normal)
        self.setTitleColor(UIColor.red, for: .normal)
        self.setImage(UIImage(named: "hand"), for: .normal)
        self.backgroundColor = UIColor.green
    }

    override func titleRect(forContentRect contentRect: CGRect) -> CGRect {
        if let string = self.title(for: .normal) {
            textSize = string.widthOfString(usingFont: self.titleFont)
            //30 because imageWidth + 10 padding
            return CGRect(origin: CGPoint(x: 30, y: 0), size: CGSize(width: textSize + 30, height: buttonHeight))
        }
        return CGRect.zero
    }

    override func imageRect(forContentRect contentRect: CGRect) -> CGRect {
        return CGRect(origin: CGPoint(x: 0, y: 0), size: CGSize(width: imageWidth, height: buttonHeight))
    }
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    override var intrinsicContentSize: CGSize {
        //60 because you need eauql padding on both side 30 + 30 = 60
        return CGSize(width: textSize + 60, height: buttonHeight)
    }
}

extension String {

    func widthOfString(usingFont font: UIFont) -> CGFloat {
        let fontAttributes = [NSAttributedString.Key.font: font]
        let size = self.size(withAttributes: fontAttributes)
        return size.width
    }
}

变量output$scatterplot <- renderPlot({ ggplot( data = df %>% filter(source %in% input$z), aes_string(x = input$x, y = input$y) ) + geom_point(aes(colour = source)) }) 反映了用户选择显示的内容(google_ads或social_media或两者)。它是一个反应性矢量,每次更改时都会触发绘图重绘。每次更改时,都对数据框进行过滤,以仅保留用户希望通过input$z查看的内容。需要注意的另一件事是基于“源”为点着色,您需要使用df %>% filter(source %in% input$z)而不是aes(color = source),因为您不想将源评估为变量。

请记住要安装和加载库(tidyverse),ggplot2也是tidyverse的一部分,因此您可以将aes_string替换为library(ggplot2)。如果您真的不想使用tidyverse,则只需使用library(tidyverse)来过滤数据