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
)
)
)
)
谢谢!!
预先: 是您需要修复的第一件事。以下不会导致 那个错误,但出于其他原因我仍然建议进行更改。
在您的 rows
和 cols
函数中,您正在直接访问 input$
。这是错误的至少有两个原因:
(一般函数式编程)您的函数超出范围,接触到未明确传递的内容。这 可能 与编程风格有关,但使用未显式传递给它的变量的函数可能很难排除故障。
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 是一个 TRUE
,dplyr::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”类型的对象是一个函数)。
我正在使用以下代码,但我总是会收到此子集错误,除非我 运行 行
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
)
)
)
)
谢谢!!
预先:
在您的 rows
和 cols
函数中,您正在直接访问 input$
。这是错误的至少有两个原因:
(一般函数式编程)您的函数超出范围,接触到未明确传递的内容。这 可能 与编程风格有关,但使用未显式传递给它的变量的函数可能很难排除故障。
做任何事情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 是一个 TRUE
,dplyr::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”类型的对象是一个函数)。