我完全不知道如何构建一个显示图形和表格数据的 R Shiny 应用程序。目标是 1. 废弃 USGS 数据,2. 构建流量数据的绘图面板,3. 拥有一个包含数据表的选项卡。下面是抓取 USGS 数据并成功构建绘图面板的工作脚本。我需要将表格和绘图的数据框架开发(相同的数据,只是以不同的方式显示)移至绘图构建服务器循环之外的反应函数,但我一直无法弄清楚。
library(shiny)
library(shinythemes)
library(dplyr)
library(dataRetrieval)
library(plotly)
library(lubridate)
library(DT)
C_site_numbers <- list("10308200", "10309000")
C_site_names <- list("Markleeville (cfs)", "Gardnerville (cfs)")
ui <- fluidPage(theme = shinytheme("yeti"),
titlePanel("USGS Streamflow Data"),
fluidRow(
column(4,
wellPanel(dateInput("start_date", "Start Date:", value = Sys.Date() - 7), width = 10)),
column(4,
wellPanel(dateInput("end_date", "End Date:", value = Sys.Date()), width = 10)),
mainPanel(
tabsetPanel(
tabPanel("Carson Basin", plotlyOutput("C_plot_panel", width = "100%", height = ceiling(length(C_site_numbers)) * 400)),
tabPanel("Carson Tablular", dataTableOutput("Data_Tables", width = "100%", height = ceiling(length(C_site_numbers)) * 400))
)
)
))
server <- function(input, output) {
# Define a reactive expression for the data frame
df <- reactive({
start_date <- ymd(input$start_date)
end_date <- ymd(input$end_date)
df <- data.frame(seq(from = start_date, to = end_date, by = 0.0069444444444444)) ##by value is equal to 5 mins intervals
colnames(df)[1] <- 'dateTime'
# Loop through each site number and download/streamflow data
for (C_site_number in C_site_numbers) {
n <- which(C_site_numbers == C_site_number)
plot_n <- unlist(C_site_names[n])
para_code = if (plot_n == 'Lahontan (acre-ft)') {'00054'} else {'00060'}
streamflow <- readNWISuv(siteNumbers = C_site_number, parameterCd = para_code,
startDate = start_date, endDate = end_date)
attr(streamflow$dateTime, 'tzone') <- "America/Los_Angeles"
# Prepare data for merging
streamflow_df <- data.frame(
dateTime = as.POSIXct(streamflow$dateTime, format = "%Y-%m-%d %H:%M"),
Flow = if (plot_n == 'Lahontan (acre-ft)') {streamflow$X_00054_00000} else {streamflow$X_00060_00000}
)
# Merge data frames
df <- merge(x = df, y = streamflow_df, by = 'dateTime', all.x = TRUE, all.y = FALSE)
}
df
})
# Carson Plot Panel
output$C_plot_panel <- renderPlotly({
# Create an empty list to store the individual plots
C_plots <- list()
# Loop through each site number and download/streamflow data
for (C_site_number in C_site_numbers) {
n <- which(C_site_numbers == C_site_number)
plot_n <- unlist(C_site_names[n])
streamflow_df <- df()
# Create the plot using plotly
plot <- plot_ly(data = streamflow_df, x = ~dateTime, y = ~Flow, type = "scatter", mode = "lines") %>%
layout(yaxis = list(title = plot_n)) %>%
layout(hovermode = "x unified", plot_bgcolor = 'rgb(212,213,214)', showlegend = FALSE)
C_plots[[C_site_number]] <- plot
}
C_plot_panel <- subplot(C_plots, nrows = ceiling(length(C_site_numbers)), titleY = TRUE, margin = 0.07)
})
# Carson Tabular
output$Data_Tables <- renderDataTable({
streamflow_df <- df()
streamflow_df
})
}
shinyApp(ui = ui, server = server)
提前非常感谢!在询问之前我已经尝试了所有资源(深入的SO搜索者、chatGPT、朋友)。自学 R Shiny 并不容易。
一种方法是
library(shiny)
library(shinythemes)
library(dplyr)
library(dataRetrieval)
library(plotly)
library(lubridate)
library(DT)
C_site_numbers <- list("10308200", "10309000")
C_site_names <- list("Markleeville (cfs)", "Gardnerville (cfs)")
ui <- fluidPage(theme = shinytheme("yeti"),
titlePanel("USGS Streamflow Data"),
fluidRow(
column(4,
wellPanel(dateInput("start_date", "Start Date:", value = Sys.Date() - 7), width = 10)),
column(4,
wellPanel(dateInput("end_date", "End Date:", value = Sys.Date()), width = 10)),
mainPanel(
tabsetPanel(
tabPanel("Carson Basin", plotlyOutput("C_plot_panel", width = "100%", height = ceiling(length(C_site_numbers)) * 400)),
tabPanel("Carson Tablular", dataTableOutput("Data_Tables", width = "100%", height = ceiling(length(C_site_numbers)) * 400))
)
)
))
server <- function(input, output) {
# Define a reactive expression for the data frame & plots
df <- reactive({
start_date <- ymd(input$start_date)
end_date <- ymd(input$end_date)
dateTime=format( seq.POSIXt(as.POSIXct(start_date), as.POSIXct(end_date), by = "5 min"),
"%Y-%m-%d %H:%M", tz="America/Los_Angeles") ##
df <- data.frame(dateTime=as.POSIXct(dateTime))
# Create an empty list to store the individual plots
# df <- data.frame(seq(from = start_date, to = end_date, by = 0.0069444444444444)) ##by value is equal to 5 mins intervals
# colnames(df)[1] <- 'dateTime'
df1 <- data.frame(dateTime=as.POSIXct(start_date), Flow=NA, site=1)
for (C_site_number in C_site_numbers) {
n <- which(C_site_numbers == C_site_number)
plot_n <- unlist(C_site_names[n])
para_code = if (plot_n == 'Lahontan (acre-ft)') {'00054'} else {'00060'}
streamflow <- readNWISuv(siteNumbers = C_site_number, parameterCd = para_code,
startDate = start_date, endDate = end_date)
attr(streamflow$dateTime, 'tzone') <- "America/Los_Angeles"
# Prepare data for merging
streamflow_df <- data.frame( # site = C_site_names[n],
dateTime = as.POSIXct(streamflow$dateTime, format = "%Y-%m-%d %H:%M"),
Flow = if (plot_n == 'Lahontan (acre-ft)') {streamflow$X_00054_00000} else {streamflow$X_00060_00000},
site = n
)
print(n)
# Merge data frames
dfa <- merge(x = df, y = streamflow_df, by = 'dateTime', all.x = TRUE, all.y = FALSE)
df1 <- rbind(df1,dfa)
}
df2 <- df1[complete.cases(df1),] ## remove NAs for Flow
C_plots <- list()
# Loop through each site number and download/streamflow data
lapply(C_site_numbers, function(C_site_number){
n <- which(C_site_numbers == C_site_number)
plot_n <- unlist(C_site_names[n])
# Create the plot using plotly
plot <- plot_ly(data = df2[df2$site==n,], x = ~dateTime, y = ~Flow, type = "scatter", mode = "lines") %>%
layout(yaxis = list(title = plot_n)) %>%
layout(hovermode = "x unified", plot_bgcolor = 'rgb(212,213,214)', showlegend = FALSE)
C_plots[[C_site_number]] <<- plot
})
return(list(data = df2, plots = C_plots))
})
# Carson Plot Panel
output$C_plot_panel <- renderPlotly({
C_plots <- df()[[2]]
C_plot_panel <- subplot(C_plots, nrows = ceiling(length(C_site_numbers)), titleY = TRUE, margin = 0.07)
})
# Carson Tabular
output$Data_Tables <- renderDataTable({
mydf <- df()[[1]]
mydf %>% select(-site)
})
}
shinyApp(ui = ui, server = server)