R Shiny Error: Warning: Error in $: object of type 'closure' is not subsettable

R Shiny Error: Warning: Error in $: object of type 'closure' is not subsettable

我正在使用以下代码,但我总是会收到此子集错误,除非我 运行 行

df <- read.csv("./world-happiness-report-cleaned.csv") 在 运行 应用程序之前手动。我在细分什么,我哪里错了?我似乎找不到错误,而且我是 Shiny 的新手,所以我以前从来没有处理过这个问题。非常感谢!!

这个 link 是一个文件箱,其中包含我使用的 csv:https://filebin.net/wjctohctz1sxm16y

server.R

# Elit Jasmine Dogu, ejd5mm
# Project One DS 3002
library(dplyr)
library(countrycode)
library(shiny)
df <- read.csv("./world-happiness-report-cleaned.csv")

    #saveRDS(df, "./df.RDS")
server <- function(input, output) {
    #reading in the data and basic data cleaning 
    #df<- read.csv("world-happiness-report-cleaned.csv")
    #df <<- readRDS("./df.RDS")
    #df <- read.csv("./world-happiness-report-cleaned.csv")
    
    # Filter data based on user selections
    output$table <- DT::renderDataTable(DT::datatable({
        data <- df %>%
            filter(
                if(input$year != "All") {
                    Year ==input$year
                } else {TRUE}
            ) %>%
            filter(
                if(input$country != "All") {
                    Country ==input$country
                } else {TRUE}
            ) %>%
            filter(
                if(input$continent != "All") {
                    Continent ==input$continent
                } else {TRUE}
            )
        
        return(data)
        
    }))
        # Generate a summary of the dataset (on the left panel)
        output$summary <- renderPrint({
            data <- df %>%
                filter(
                    if(input$year != "All") {
                        Year ==input$year
                    } else {TRUE}
                ) %>%
                filter(
                    if(input$country != "All") {
                        Country ==input$country
                    } else {TRUE}
                ) %>%
                filter(
                    if(input$continent != "All") {
                        Continent ==input$continent
                    } else {TRUE}
                )
            
            return(summary(data))
            
        })
    
       #Generate a function to show the number of rows w/ any given dataframe selection/restriction
    rows = function() {
        data <- df %>%
            filter(
                if(input$year != "All") {
                    Year ==input$year
                } else {TRUE}
            ) %>%
            filter(
                if(input$country != "All") {
                    Country ==input$country
                } else {TRUE}
            ) %>%
            filter(
                if(input$continent != "All") {
                    Continent ==input$continent
                } else {TRUE}
            )
        
        return(nrow(data)) #returns number of rows of the data
    }
    
    #Generate a function to show the number of columns w/ any given dataframe selection/restriction
    cols = function() {
        data <- df %>%
            filter(
                if(input$year != "All") {
                    Year ==input$year
                } else {TRUE}
            ) %>%
            filter(
                if(input$country != "All") {
                    Country ==input$country
                } else {TRUE}
            ) %>%
            filter(
                if(input$continent != "All") {
                    Continent ==input$continent
                } else {TRUE}
            )
        
        return(ncol(data)) #returns the number of columns of the data
    }

    #Using the functions created above
        output$columns  <- renderText({
            paste("Number of Columns:" , cols() ) #text to display the number of columns
        })
        output$rows  <- renderText({
            paste("Number of Rows (Records):" , rows() ) #text to display the number of rows 
        })

        output$data_ex  <- renderText({
            paste("Please see README.md file for information regarding the dataset.") #text to display where to find more information
        })
 

        # Downloadable csv of selected dataset 
        output$downloadData <- downloadHandler(
            filename = function() {
                selected <-c() #this assists with the name of the file
                if (input$year != "All") { 
                    selected <-c(selected, input$year)
                }
                if (input$country != "All") {
                    selected <-c(selected, input$country)
                }
                if (input$continent != "All") {
                    selected <-c(selected, input$continent)
                }
                if (length(selected) == 0) {
                    selected <- c("AllData")
                }
                
                paste0(paste(selected, collapse="-"), ".csv")
            },
            content = function(con) {
                data <- df %>%
                    filter(
                        if(input$year != "All") {
                            Year ==input$year
                        } else {TRUE}
                    ) %>%
                    filter(
                        if(input$country != "All") {
                            Country ==input$country
                        } else {TRUE}
                    ) %>%
                    filter(
                        if(input$continent != "All") {
                            Continent ==input$continent
                        } else {TRUE}
                    )
                write.csv(data, con, row.names = TRUE) #saves the filtered data
            }
        )
}

ui.R

# Elit Jasmine Dogu, ejd5mm
# Project One DS 3002
library(shiny)
library(shinyWidgets)

ui <- fluidPage(
    #text with project name and my information
    titlePanel("World Happiness Report"),
    tags$h3("DS 3002- Project One"),
    tags$h4("Elit Dogu, ejd5mm 3rd Year UVA"),
    # use a gradient in background, setting background color to blue
    setBackgroundColor(  
        #https://rdrr.io/cran/shinyWidgets/man/setBackgroundColor.html used this website for help on background color
        color = c("#F7FBFF", "#2171B5"),
        gradient = "radial",
        direction = c("top", "left")
    ),
    # Sidebar layout with input and output definitions ----
    sidebarLayout(
        
        # Sidebar panel for inputs ----
        sidebarPanel(
            
            # Output: Header + summary of distribution ----
            h4("Summary"),
            verbatimTextOutput("summary"),
            
            # Download button
            downloadButton("downloadData", "Download")
        ),
    # Create a new Row in the UI for selectInputs
    # Main panel for displaying outputs ----
    mainPanel(

    fluidRow(  #manipulates the original dataframe given user selection
        column(4,
               selectInput("year",  #selection for the year variable
                           "Year:",
                           c("All",
                             unique(as.numeric(df$Year))))
        ),
        column(4,
               selectInput("country",  #selection for the country variable
                           "Country:",
                           c("All",
                             unique(as.character(df$Country))))
        ),
        column(4,
               selectInput("continent",  #selection for the continent variable
                           "Continent:",
                           c("All",
                             unique(as.character(df$Continent))))
        )
    ),
    # Create a new row for the table
    DT::dataTableOutput("table"),
    
    # Create a new column for the text to be displayed
    column(12,
           verbatimTextOutput("columns") #column to display col count
    ),
    column(12,
           verbatimTextOutput("rows") #column to display row count
    ),

    column(12,
           verbatimTextOutput("data_ex") #column to display more information text
            )
        )
    )
)

谢谢!!

预先 是您需要修复的第一件事。以下不会导致 那个错误,但出于其他原因我仍然建议进行更改。


在您的 rowscols 函数中,您正在直接访问 input$。这是错误的至少有两个原因:

  1. (一般函数式编程)您的函数超出范围,接触到未明确传递的内容。这 可能 与编程风格有关,但使用未显式传递给它的变量的函数可能很难排除故障。

  2. input$ 只能从 reactive*observe*render* 中访问 块(即闪亮反应的东西)。这些之外的任何东西都不应尝试使用 input$output$.

    做任何事情

作为解决方法,通过使功能独立且正常工作,使功能不可知以闪亮 scalars/vectors。 (我也会稍微减少逻辑。)

  #Generate a function to show the number of rows w/ any given dataframe selection/restriction
  rows = function(year, country, continent) {
    data <- df %>%
      filter(
        year == "All" | year == Year,
        country == "All" | country == Country,
        continent == "All" | continent == Continent
      )
    return(nrow(data)) #returns number of rows of the data
  }

  # ...

  output$rows  <- renderText({
    paste("Number of Rows (Records):" , rows(input$year, input$country, input$continent) )
  })

老实说,你的cols函数有点奇怪……你整天都可以改变一个框架的行数,但列数不会改变。除非你 dplyr::select 一些列,否则它应该总是恰好 ncol(df).

至于逻辑的减少,你的 if 语句嵌入你的 dplyr::filter 链中并没有错,但我认为我已经采用了更符合 R 惯用的方式来做到这一点建议。在您的情况下,如果变量是 "All",那么它 returns 是一个 TRUEdplyr::filter 适用于所有行。如果不是,则它 returns 一个 logical 向量(每行 1 个)指示帧的变量是否与所选输入匹配。

在我的版本中,我做了非常相似的事情:第一个 year == "All" 仍将解析为单个逻辑(假设 year,来自 input$year),但右侧-side 将与行数一样长。你可以测试它是什么样子的:

TRUE | c(T,F,T,F)
# [1] TRUE TRUE TRUE TRUE
FALSE | c(T,F,T,F)
# [1]  TRUE FALSE  TRUE FALSE

问题是您在 UI 中使用了 df$......。如果在 server 函数中定义了 df,则在 UI 中没有定义。所以你得到这个错误是因为 R 将 df 识别为 'stats' 包提供的函数(“closure”类型的对象是一个函数)。