来自 Google Big Query 的闪亮反应对象中的问题

Problem in Shiny reactive objects from Google Big Query

我只想下载并绘制由 selectInput 在 Shiny 中选择的 state 几何图形。但是当我尝试在大查询的反应对象中使用 st_as_sf 时 table (stands_sel()) 不起作用并且输出是:

Listening on http://127.0.0.1:5221
Warning: Error in $: $ operator is invalid for atomic vectors
  186: unique
  185: <reactive:stands_sel> [C:/Users/fores/Downloads/teste_sf.R#60]
  183: .func
  180: contextFunc
  179: env$runWith
  172: ctx$run
  171: self$.updateValue
  169: stands_sel
  167: renderPlot [C:/Users/fores/Downloads/teste_sf.R#71]
  165: func
  125: drawPlot
  111: <reactive:plotObj>
   95: drawReactive
   82: renderFunc
   81: output$myplot
    1: runApp

在我的例子中我做了:

library(shinythemes)
library(dplyr)
library(ggplot2)
library(bigrquery)
library(DBI)
library(sf)
library(glue)

# Open a public BigQuery dataset eg. "geo_us_boundaries"
bq_con <- dbConnect(
  bigrquery::bigquery(),
  project = "bigquery-public-data",
  dataset = "geo_us_boundaries",
  billing = "my-project"
)
bigrquery::dbListTables(bq_con) # List all the tables in BigQuery data set


# Take the table
dataset <- dplyr::tbl(bq_con, 
                      "states") # connects to a table


# Enumerate the states
dataset_vars <- dataset %>% dplyr::distinct(geo_id, state, state_name)%>% 
  collect() 
str(dataset_vars)


# Create the shiny dash
ui <- fluidPage(
  theme = shinytheme("cosmo"),
  titlePanel(title="States Dashboard"),  
  sidebarLayout(
    sidebarPanel(
      selectInput(inputId = "selectedvariable0",
                  label = "Geo ID", 
                  choices = c(unique(dataset_vars$geo_id)),selected = TRUE ), 
      selectInput(inputId = "selectedvariable1",
                  label = "State", 
                  choices = c(unique(dataset_vars$state)),selected = TRUE ), 
      selectInput(inputId = "selectedvariable2",
                  label = "State name", 
                  choices = c(unique(dataset_vars$state_name)),selected = TRUE )
    ),
    mainPanel(
      textOutput("idSaida"),
      fluidRow(
        splitLayout(plotOutput("myplot")))
    )
  )
)
server <- function(input, output){
  
  
  # # Selection of variables for plots constructions
      currentvariable1 <- reactive({input$selectedvariable1})
  
    stands_sel <- reactive({ 
      var0 <- unique(currentvariable1()$state)
      sqlInput <- glue::glue_sql("SELECT * FROM states WHERE state = {var0}", .con=bq_con)
      dbGetQuery(bq_con, as.character(sqlInput), stringsAsFactors = T)
      })
  
   
  observe({

       output$myplot <- renderPlot({
         
         #Create the plot
         stands_sel <- st_as_sf(stands_sel(), wkt = "state_geom", crs = 4326)
         ggplot() +
           geom_sf(data=stands_sel) 
       })
   }) #end of observe function.
}
shinyApp(ui, server)
#

请问有什么解决办法吗?

出现此错误是因为“$”运算符不是为访问向量元素而设计的。如果我们使用“$”运算符访问向量元素,那么 R 不理解它并认为它无效;因此,我们必须非常小心在何处使用“$”运算符。当我们为我们的元素命名并开始认为我们可以将它们视为数据框列时,就会发生这种情况,这是一种错误的方法。要访问矢量元素,我们应该使用单个方括号。

可以顺序访问原子向量的各个元素。例如,位置 1、位置 2 等。表示法为 vect[1]、vect[2]、vect[3]。

您还可以将其以不同的格式表示为变量,以包含在迭代循环中。 但是,在访问原子向量的各个部分时,您必须小心。如果向量的某些部分访问不当或访问顺序不正确,您可能会看到“$ operator is invalid for atomic vectors”错误消息。

您可以通过将“$”运算符转换为括号引用来修复这些错误。您还可以使用 getElement() 函数。

你可以检查一下你的代码,你在哪一部分使用了“$”符号。

> testlist <- c(1,2,3) 
> testlist$s
Error in testlist$s : $ operator is invalid for atomic vectors
> testlist[1]
[1] 1
> getElement(testlist,1)
[1] 1

如您所见,我们通过使用“$”运算符尝试不正确地访问原子向量(我们的数组)成功触发了此示例中的错误。通过使用括号或getElement(),我们得到了想要的结果。

你可以看到更多documentation

你可以看到这个向量的例子。

> set.seed(1)
> x1<-sample(1:10,20,replace=TRUE)
> x1
[1] 9 4 7 1 2 7 2 3 1 5 5 10 6 10 7 9 5 5 9 9
> names(x1)<-LETTERS[1:20]
> x1
A B C D E F G H I J K L M N O P Q R S T
9 4 7 1 2 7 2 3 1 5 5 10 6 10 7 9 5 5 9 9
> x1$K
Error in x1$K : $ operator is invalid for atomic vectors

在这里,我们收到“$ operator is invalid for atomic vectors”的错误。现在我们应该使用单个方括号访问向量 x1 的元素,如下所示 -

> x1["K"]
K
5
> x1["T"]
T
9
> x1["A"]
A
9
> x1[1]
A
9

您可以在 this link 中查看更多信息。

函数glue_sql不接受使用glue::glue_sql("SELECT * FROM states WHERE state = {var0}", .con=bq_con)的反应对象,但glue_sql调用需要移动到反应表达式(glue::glue_sql("SELECT * FROM states WHERE state = {x}", x = input$selectedvariable1, .con=bq_con))。

解决代码:

library(shinythemes)
library(dplyr)
library(ggplot2)
library(bigrquery)
library(DBI)
library(sf)
library(glue)

# Open a public BigQuery dataset eg. "geo_us_boundaries"
bq_con <- dbConnect(
  bigrquery::bigquery(),
  project = "bigquery-public-data",
  dataset = "geo_us_boundaries",
  billing = "my-project"
)
bigrquery::dbListTables(bq_con) # List all the tables in BigQuery data set


# Take the table
dataset <- dplyr::tbl(bq_con, 
                      "states") # connects to a table


# Enumerate the states
dataset_vars <- dataset %>% dplyr::distinct(geo_id, state, state_name)%>% 
  collect() 
str(dataset_vars)


# Create the shiny dash
ui <- fluidPage(
  theme = shinytheme("cosmo"),
  titlePanel(title="States Dashboard"),  
  sidebarLayout(
    sidebarPanel(
      selectInput(inputId = "selectedvariable0",
                  label = "Geo ID", 
                  choices = c(unique(dataset_vars$geo_id)),selected = TRUE ), 
      selectInput(inputId = "selectedvariable1",
                  label = "State", 
                  choices = c(unique(dataset_vars$state)),selected = TRUE ), 
      selectInput(inputId = "selectedvariable2",
                  label = "State name", 
                  choices = c(unique(dataset_vars$state_name)),selected = TRUE )
    ),
    mainPanel(
        fluidRow(
          splitLayout(plotOutput("myplot")))
      
    )
  )
)
server <- function(input, output){
  
  # # Selection of variables for plots constructions
  
  sqlInput <- reactive({
    glue::glue_sql("SELECT * FROM states WHERE state = {x}", x = input$selectedvariable1, .con=bq_con)
  })
  stands_sel <- function() dbGetQuery(bq_con, as.character(sqlInput()), stringsAsFactors = T)

  print(sqlInput)
  
  observe({

  output$myplot <- renderPlot({

  #Create the plot 
    stands_sel_sf <- st_as_sf(stands_sel(), wkt = "state_geom", crs = 4326) 
    ggplot() + geom_sf(data=stands_sel_sf) }) 
  }) #end of observe function.
}
shinyApp(ui, server)
#