You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Shiny技术问题:如何实现多页面输入内容的保存?

Solution for Multi-Page Text Rating with Batch CSV Saving in Shiny

Hey there! Since you already have the single-page rating submission working, expanding this to handle 100 texts with pagination and batch saving is totally doable. Let's break this down into key changes and walk through the updated code:

Key Concepts to Implement

  • Track Current Text & Ratings: Use reactiveValues() to store the current page index and all collected ratings (so we don't lose data when switching pages).
  • Pagination Controls: Add "Previous" and "Next" buttons to navigate between texts, with checks to prevent going beyond the first/last text.
  • Batch Saving: Instead of writing to CSV after each submission, collect all ratings first, then let users save everything to a single CSV file once they're done.

Updated Shiny Code

Here's a complete, annotated version that builds on your single-page setup:

library(shiny)
library(readr)

# Sample 100 texts (replace this with your actual text dataset)
# Ideally, load from a file: texts_df <- read_csv("your_texts.csv")
texts_df <- data.frame(
  text_id = 1:100,
  content = paste("Text content for item", 1:100)
)

ui <- fluidPage(
  titlePanel("Text Rating Tool"),
  
  # Pagination controls
  fluidRow(
    column(4, actionButton("prev_btn", "Previous Text")),
    column(4, textOutput("current_page")),
    column(4, actionButton("next_btn", "Next Text"))
  ),
  
  hr(),
  
  # Current text display
  h4("Text to Rate:"),
  verbatimTextOutput("current_text"),
  
  # Rating input
  selectInput("rating", "Your Rating:", choices = 1:5),
  
  # Buttons for submission and saving
  actionButton("submit_rating", "Submit Rating for This Text"),
  actionButton("save_all", "Save All Ratings to CSV"),
  
  # Status messages
  textOutput("status_msg")
)

server <- function(input, output, session) {
  # Initialize reactive values to track state
  rv <- reactiveValues(
    current_index = 1,
    ratings_data = data.frame(text_id = integer(), rating = integer())
  )
  
  # Display current page number
  output$current_page <- renderText({
    paste("Text", rv$current_index, "of", nrow(texts_df))
  })
  
  # Display current text content
  output$current_text <- renderPrint({
    texts_df$content[rv$current_index]
  })
  
  # Handle Previous button click
  observeEvent(input$prev_btn, {
    if (rv$current_index > 1) {
      rv$current_index <- rv$current_index - 1
      # Reset status message when switching pages
      output$status_msg <- renderText("")
    }
  })
  
  # Handle Next button click
  observeEvent(input$next_btn, {
    if (rv$current_index < nrow(texts_df)) {
      rv$current_index <- rv$current_index + 1
      output$status_msg <- renderText("")
    }
  })
  
  # Handle rating submission
  observeEvent(input$submit_rating, {
    current_text_id <- texts_df$text_id[rv$current_index]
    
    # Check if this text already has a rating
    if (!current_text_id %in% rv$ratings_data$text_id) {
      # Add new rating to our dataset
      new_rating <- data.frame(
        text_id = current_text_id,
        rating = as.integer(input$rating)
      )
      rv$ratings_data <- rbind(rv$ratings_data, new_rating)
      
      output$status_msg <- renderText(paste("Rating saved for Text", current_text_id))
    } else {
      output$status_msg <- renderText(paste("Text", current_text_id, "already has a rating!"))
    }
  })
  
  # Handle saving all ratings to CSV
  observeEvent(input$save_all, {
    if (nrow(rv$ratings_data) > 0) {
      # Merge with original text data (optional, to include text content in CSV)
      final_data <- merge(texts_df, rv$ratings_data, by = "text_id")
      
      # Save to CSV (you can adjust the file path/name)
      write_csv(final_data, "all_ratings.csv")
      
      output$status_msg <- renderText(paste("Successfully saved", nrow(final_data), "ratings to all_ratings.csv"))
    } else {
      output$status_msg <- renderText("No ratings to save yet!")
    }
  })
}

shinyApp(ui, server)

Key Changes Explained

  • Reactive State Management: rv$current_index keeps track of which text we're viewing, and rv$ratings_data stores all submitted ratings in a data frame.
  • Pagination Logic: The "Previous"/"Next" buttons check if we're at the first/last text before updating the index.
  • Duplicate Prevention: We check if a text already has a rating before adding it to the dataset, so users don't accidentally submit twice.
  • Batch Saving: The final CSV includes both the text content and ratings (you can remove the merge if you only need text IDs and ratings).

Customization Tips

  • Replace the sample texts_df with your actual 100 texts (load from a CSV using read_csv()).
  • Adjust the rating choices (e.g., 1-10, or descriptive labels like "Poor" to "Excellent").
  • Add a progress bar to show how many texts have been rated.
  • Auto-save ratings periodically if you want extra safety (but the batch save is simpler for your use case).

内容的提问来源于stack exchange,提问作者Dietrich R-D

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:31:55