R语言 如何将同一组相关过滤器用于两个数据集以生成至少两个输出?

gjmwrych  于 2023-05-26  发布在  其他
关注(0)|答案(1)|浏览(174)

我是一个初创的非营利组织的志愿者,该组织向私人特许权使用费 * 所有者 * 征集矿产利益。然后将贡献的权益汇总并出售,所得收益作为赠款奖励,以促进应对气候变化的技术开发。
为了扩大我们的筹款努力,我们想为可能成为潜在捐赠者的 * 所有者 * 建立一个闪亮的网络应用程序。这些 * 所有者 * 可以搜索我们的数据库,找到他们的兴趣,并了解他们通过向我们的非营利组织捐款可以获得的减税额(第一个目标,基于“Sample_Tax_Data”,请参阅:(https://docs.google.com/spreadsheets/d/1wKe9VR_Cs2V_CJGNipbuCaUFR21eTHE0/edit?usp=share_link&ouid=118028955904508148375&rtpof=true&sd=trueto))。

library(readxl)
library(shiny)
library(tidyverse)

TaxData <- Sample_Tax_Data

shinyApp(
  ui = pageWithSidebar(
    headerPanel("Find My Royalty Interest"),
    sidebarPanel(
      selectizeInput(inputId = "County",
                     label = "Select County",
                     choices = NULL,
                     options = list(placeholder = 'select')
                     ),
      
      selectizeInput(inputId = "Operator",
                     label = "Select Operator",
                     choices = NULL,
                     options = list(placeholder = 'select',
                                    onInitialize = I('function() { this.setValue(""); }')
                     )),
      
      selectizeInput(inputId = "Lease",
                     label = "Select Lease",
                     choices = NULL,
                     options = list(placeholder = 'select',
                                    onInitialize = I('function() { this.setValue(""); }')
                     )),
      
      selectizeInput(inputId = "Owner",
                     label = "Select Owner",
                     choices = NULL,
                     options = list(placeholder = 'select',
                                    onInitialize = I('function() { this.setValue(""); }')
                     )),
      
       ),
    
    mainPanel(
      tableOutput("TaxTable")
    )
  ),
  
  server = function(input, output, session) {
    
    TaxFil <- reactive({
      
      TaxData %>%
        filter(County == input$County) %>%
        filter(Operator == input$Operator) %>%
        filter(Lease == input$Lease) %>%
        filter(Owner == input$Owner) 
      
   })
    
    updateSelectizeInput(
      session = session,
      inputId = "County",
      choices = sort(unique(as.character(TaxData$County))),
      selected = "",
      options = list(placeholder = 'select'),
      server = TRUE
    )
    
    observeEvent(input$County,{
      choice_Operator <- sort(unique(as.character(TaxData$Operator[which(TaxData$County==input$County)])))
      
      updateSelectizeInput(
        session = session,
        inputId = "Operator",
        choices = choice_Operator
      )
    })
    
    observeEvent(input$Operator,{
      choice_Lease <- sort(unique(as.character(TaxData$Lease[which(TaxData$County==input$County &
                                                                     TaxData$Operator==input$Operator)])))
      
      updateSelectizeInput(
        session = session,
        inputId = "Lease",
        choices = choice_Lease
      )
    })
    
    observeEvent(input$Lease,{
      choice_Owner <- sort(unique(as.character(TaxData$Owner[which(TaxData$County==input$County &
                                                                     TaxData$Operator==input$Operator &
                                                                     TaxData$Lease==input$Lease)])))
      
      updateSelectizeInput(
        session = session,
        inputId = "Owner",
        choices = choice_Owner
      )
    })
    
    output$TaxTable <- renderTable({TaxFil()})
    
  },
  
  options = list(height = 500)
  
)

**在第二个目标的情况下:**我无法编写代码来支持使用同一系列的相关过滤器及其结果,以使 * 所有者 * 能够访问与其利益相关的替代估值。

我考虑的第一个选择是重用支持第一个目标的过滤器(参见上面的代码)。在这种情况下,过滤器将用于识别 * 所有者 *(和分配的“税收价值”-第一目标)以及租赁(和从中生产的“石油”和“天然气”,以预测附加价值-第二目标)。这似乎是最合乎逻辑的方法来过滤两个目标,但我不能让它工作。
我尝试的下一件事是重新创建过滤器,并将其单独用于第二个目标(原始过滤器仅用于选择 * 所有者 *)。我也无法使其工作,而且它似乎也不是一个非常经济的编码选项。
我最后尝试的是两个数据库的合并。但是,由于许多租约每月的生产历史超过30年,在某些情况下有数千名业主,合并后的文件至少要大20倍,而且很难处理。
总之,我正在寻找帮助编码一组过滤器,可以应用于至少两个不同的数据库,至少两个不同的输出。我已经回顾了以前的问题/答案,发现有几个本质上很接近,比如Nice回答的问题,但由于我有限的经验,我无法推断出我的特定目标。我显然是新来的,真的很感激你的支持。

b5buobof

b5buobof1#

若要重用同一组筛选器,应首先从公共筛选列的并集中确定有效值集:

library(readr)
library(dplyr) # union.data.frame

TaxData <- read_tsv("https://pastebin.com/raw/eiFFTmuh", show_col_types = FALSE)
ProdData <- read_tsv("https://pastebin.com/raw/kCWZ9bd5", show_col_types = FALSE)
ProdData$Date <- lubridate::mdy(ProdData$Date)

cols <- c("County", "Operator", "Lease")
Leases <- union(TaxData[cols], ProdData[cols])
Leases
#> # A tibble: 5 × 3
#>   County   Operator Lease
#>   <chr>    <chr>    <chr>
#> 1 Goliad   BP       G1   
#> 2 Goliad   Shell    G2   
#> 3 Live Oak Tex      L1   
#> 4 Live Oak Conoco   L4   
#> 5 Shell    Shell    G2

然后,要根据以前的选择更新每个筛选器的选项集,请尽可能地筛选此共享集。当您遇到只存在于其中一个数据集中的列时,交换用于更新选项的数据(如此处的Owner)。
这是一个演示应用程序,我将如何把它付诸行动。首先,我对UI进行了一点精简:

library(shiny)

ui <- pageWithSidebar(
  headerPanel("Find My Royalty Interest"),
  sidebarPanel(
    lapply(c("County", "Operator", "Lease", "Owner"), function(field) {
      selectizeInput(
        inputId = field,
        label = paste("Select ", field),
        choices = NULL,
        options = list(placeholder = "Select")
      )
    })
  ),
  mainPanel(
    tableOutput("TaxTable"),
    plotOutput("ProdGraph")
  )
)

接下来,介绍几个用于常见服务器任务的helper函数:

get_inputs <- function(..., session = getDefaultReactiveDomain()) {
  lapply(setNames(nm = c(...)), function(id) session$input[[id]])
}

update_choices <- function(id, data, ..., session = getDefaultReactiveDomain()) {
  choices <- sort(unique(data[[id]]))
  updateSelectizeInput(session, id, choices = choices, selected = "", ...)
}

最后是服务器的改进。在这里,我们自由地使用merge()来进行过滤,而不是显式地写出所有==比较。

server <- function(input, output, session) {
  update_choices("County", Leases, server = TRUE)

  observeEvent(input$County, {
    update_choices("Operator", merge(Leases, get_inputs("County")))
  })

  observeEvent(input$Operator, {
    update_choices("Lease", merge(Leases, get_inputs("County", "Operator")))
  })

  observeEvent(input$Lease, {
    update_choices("Owner", merge(TaxData, get_inputs("County", "Operator", "Lease")))
  })

  output$TaxTable <- renderTable({
    merge(TaxData, Filter(nzchar, get_inputs("County", "Operator", "Lease", "Owner")))
  })

  output$ProdGraph <- renderPlot({
    ProdFil <- merge(ProdData, get_inputs("County", "Operator", "Lease"))
    ProdFil <- ProdFil[order(ProdFil$Date), ]
    req(nrow(ProdFil) > 0) # Only plot if we have some matching rows
    plot(`Oil/bbl` ~ Date, ProdFil, type = "b")
  })
}

shinyApp(ui, server)

在使用这个方法时,我发现在应用不同的过滤器时显示增量过滤的数据更直观。如果真实的数据太大,无法在完全过滤之前发送,则可以删除Filter s。或者显示一个截断的预览,仍然给予用户一个事情发生的印象。

相关问题