cjerzak commited on
Commit
cf877eb
·
verified ·
1 Parent(s): b292837

Update app.R

Browse files
Files changed (1) hide show
  1. app.R +97 -42
app.R CHANGED
@@ -44,6 +44,18 @@ plot_factor <- function(pi_star_list, pi_star_se_list, factor_name, zStar = 1.96
44
  ui <- fluidPage(
45
  titlePanel("Exploring strategize with the candidate choice conjoint data"),
46
 
 
 
 
 
 
 
 
 
 
 
 
 
47
  sidebarLayout(
48
  sidebarPanel(
49
  h4("Analysis Options"),
@@ -56,10 +68,12 @@ ui <- fluidPage(
56
  choices = c("All", "Democrat", "Independent", "Republican"),
57
  selected = "All")
58
  ),
59
- # Add a single numeric input for lambda
60
  numericInput("lambda_input", "Lambda (regularization):",
61
  value = 0.01, min = 1e-6, max = 10, step = 0.01),
62
  actionButton("compute", "Compute Results", class = "btn-primary"),
 
 
 
63
  hr(),
64
  h4("Visualization"),
65
  selectInput("factor", "Select Factor to Display:",
@@ -69,7 +83,8 @@ ui <- fluidPage(
69
  p("1. Select a case type and, for Average case, a respondent group."),
70
  p("2. Specify the single lambda to be used by strategize."),
71
  p("3. Click 'Compute Results' to generate optimal strategies."),
72
- p("4. Choose a factor to view its distribution.")
 
73
  ),
74
 
75
  mainPanel(
@@ -85,6 +100,11 @@ ui <- fluidPage(
85
  p("**Average Case**: Optimizes candidate characteristics for a selected respondent group."),
86
  p("**Adversarial Case**: Finds equilibrium strategies for Democrats and Republicans, identified by 'Pro-life' stance.")
87
  )
 
 
 
 
 
88
  )
89
  )
90
  )
@@ -96,7 +116,10 @@ server <- function(input, output, session) {
96
  load("Processed_OnoData.RData")
97
  Primary2016 <- read.csv("PrimaryCandidates2016 - Sheet1.csv")
98
 
99
- # Update factor choices dynamically
 
 
 
100
  observe({
101
  if (input$case_type == "Average") {
102
  factors <- colnames(FACTOR_MAT_FULL)[!colnames(FACTOR_MAT_FULL) %in% c("Office")]
@@ -106,13 +129,12 @@ server <- function(input, output, session) {
106
  updateSelectInput(session, "factor", choices = factors, selected = factors[1])
107
  })
108
 
109
- # Reactive computation triggered by button
110
- result <- eventReactive(input$compute, {
111
  withProgress(message = "Computing optimal strategies...", value = 0, {
112
- # Increment progress
113
  incProgress(0.2, detail = "Preparing data...")
114
 
115
- # Common hyperparameters (mirroring QRun_Apps.R)
116
  params <- list(
117
  nSGD = 1000L,
118
  batch_size = 50L,
@@ -128,17 +150,27 @@ server <- function(input, output, session) {
128
  # Grab the single user-chosen lambda
129
  my_lambda <- input$lambda_input
130
 
 
 
 
 
 
 
 
 
131
  if (input$case_type == "Average") {
132
  # Subset data for Average case
133
  if (input$respondent_group == "All") {
134
- indices <- which( my_data$Office == "President" )
135
  } else {
136
- indices <- which(my_data_FULL$R_Partisanship == input$respondent_group &
137
- my_data$Office == "President")
 
 
138
  }
139
 
140
  FACTOR_MAT <- FACTOR_MAT_FULL[indices,
141
- !colnames(FACTOR_MAT_FULL) %in% c("Office","Party.affiliation","Party.competition")]
142
  Yobs <- Yobs_FULL[indices]
143
  X <- X_FULL[indices, ]
144
  log_pr_w <- log_pr_w_FULL[indices]
@@ -147,7 +179,7 @@ server <- function(input, output, session) {
147
 
148
  incProgress(0.4, detail = "Running strategize...")
149
 
150
- # Compute with strategize using a single lambda
151
  Qoptimized <- strategize(
152
  Y = Yobs,
153
  W = FACTOR_MAT,
@@ -159,7 +191,7 @@ server <- function(input, output, session) {
159
  diff = TRUE,
160
  adversarial = FALSE,
161
  use_regularization = TRUE,
162
- K = 1L, # Base analysis
163
  nSGD = params$nSGD,
164
  penalty_type = params$penalty_type,
165
  folds = params$nFolds,
@@ -169,8 +201,10 @@ server <- function(input, output, session) {
169
  conda_env = params$conda_env,
170
  conda_env_required = params$conda_env_required
171
  )
172
- } else { # Adversarial case
173
- # Use full data, drop specific factors
 
 
174
  DROP_FACTORS <- c("Office", "Party.affiliation", "Party.competition")
175
  FACTOR_MAT <- FACTOR_MAT_FULL[, !colnames(FACTOR_MAT_FULL) %in% DROP_FACTORS]
176
  Yobs <- Yobs_FULL
@@ -178,8 +212,8 @@ server <- function(input, output, session) {
178
  log_pr_w <- log_pr_w_FULL
179
  assignmentProbList <- assignmentProbList_FULL[!names(assignmentProbList_FULL) %in% DROP_FACTORS]
180
 
181
- # Prepare slate_list (simplified from QRun_Apps.R)
182
  incProgress(0.3, detail = "Preparing slate data...")
 
183
  FactorOptions <- apply(FACTOR_MAT, 2, table)
184
  prior_alpha <- 10
185
  Primary_D <- Primary2016[Primary2016$Party == "Democratic", colnames(FACTOR_MAT)]
@@ -205,33 +239,31 @@ server <- function(input, output, session) {
205
 
206
  slate_list <- list("Democratic" = Primary_D_slate, "Republican" = Primary_R_slate)
207
 
208
- # subset data
209
- indices <- which( my_data$R_Partisanship %in% c("Republican","Democrat") &
210
- my_data$Office == "President" )
 
211
  FACTOR_MAT <- FACTOR_MAT_FULL[indices,
212
- !colnames(FACTOR_MAT_FULL) %in% c("Office",
213
- "Party.competition",
214
- "Party.affiliation")]
215
  Yobs <- Yobs_FULL[indices]
216
  my_data_red <- my_data_FULL[indices,]
217
  pair_id <- pair_id_FULL[indices]
218
- cluster_var <- cluster_var_FULL[ indices ]
219
- my_data_red$Party.affiliation_clean <- ifelse(my_data_red$Party.affiliation == "Republican Party",
220
- yes = "Republican", no = ifelse(my_data_red$Party.affiliation == "Democratic Party",
221
- yes = "Democrat",no = "Independent"))
 
 
222
 
223
- # subset cols
224
  assignmentProbList <- assignmentProbList_FULL[colnames(FACTOR_MAT)]
225
  slate_list$Democratic <- slate_list$Democratic[names(assignmentProbList)]
226
  slate_list$Republican <- slate_list$Republican[names(assignmentProbList)]
227
 
228
  incProgress(0.4, detail = "Running strategize...")
229
 
230
- # Compute with strategize using a single lambda
231
  Qoptimized <- strategize(
232
  Y = Yobs,
233
  W = FACTOR_MAT,
234
- #X = X,
235
  X = NULL,
236
  p_list = assignmentProbList,
237
  slate_list = slate_list,
@@ -249,7 +281,6 @@ server <- function(input, output, session) {
249
  use_regularization = TRUE,
250
  force_gaussian = FALSE,
251
  adversarial = TRUE,
252
- #nFolds_glm = 3L,
253
  K = 1L,
254
  nMonte_adversarial = 20L,
255
  nSGD = params$nSGD,
@@ -263,37 +294,61 @@ server <- function(input, output, session) {
263
  )
264
 
265
  # Identify Democrat vs Republican based on "Pro-life" stance
266
- prolife_probs <- c(Qoptimized$pi_star_point$Democrat$Position.on.abortion["Pro-life"],
267
- Qoptimized$pi_star_point$Republican$Position.on.abortion["Pro-life"])
 
 
268
  which_repub <- which.max(prolife_probs)
269
  if (which_repub == 1) {
270
- # Swap
271
- Qoptimized$pi_star_point <- list(k1 = Qoptimized$pi_star_point$k2, k2 = Qoptimized$pi_star_point$k1)
272
- Qoptimized$pi_star_se <- list(k1 = Qoptimized$pi_star_se$k2, k2 = Qoptimized$pi_star_se$k1)
 
 
273
  }
274
  }
275
 
276
  incProgress(0.8, detail = "Finalizing results...")
277
- return(Qoptimized)
 
 
 
 
 
 
 
278
  })
279
  })
280
 
 
 
 
 
 
 
 
 
281
  # Render strategy plot
282
  output$strategy_plot <- renderPlot({
283
- req(result())
284
  factor_name <- input$factor
285
- pi_star_list <- result()$pi_star_point
286
- pi_star_se_list <- result()$pi_star_se
287
  plot_factor(pi_star_list, pi_star_se_list, factor_name)
288
  })
289
 
290
  # Render Q value
291
  output$q_value <- renderText({
292
- req(result())
293
- q_point <- result()$Q_point_mEst
294
- q_se <- result()$Q_se_mEst
295
  paste("Estimated Q Value: ", sprintf("%.3f ± %.3f", q_point, 1.96 * q_se))
296
  })
 
 
 
 
 
297
  }
298
 
299
  # Run the app
 
44
  ui <- fluidPage(
45
  titlePanel("Exploring strategize with the candidate choice conjoint data"),
46
 
47
+ tags$p(
48
+ style = "text-align: left; margin-top: -10px;",
49
+ tags$a(
50
+ href = "https://strategizelab.org/",
51
+ target = "_blank",
52
+ title = "strategizelab.org",
53
+ style = "color: #337ab7; text-decoration: none;",
54
+ "strategizelab.org ",
55
+ icon("external-link", style = "font-size: 12px;")
56
+ )
57
+ ),
58
+
59
  sidebarLayout(
60
  sidebarPanel(
61
  h4("Analysis Options"),
 
68
  choices = c("All", "Democrat", "Independent", "Republican"),
69
  selected = "All")
70
  ),
 
71
  numericInput("lambda_input", "Lambda (regularization):",
72
  value = 0.01, min = 1e-6, max = 10, step = 0.01),
73
  actionButton("compute", "Compute Results", class = "btn-primary"),
74
+ br(),
75
+ selectInput("previousResults", "View Previous Results:",
76
+ choices = NULL),
77
  hr(),
78
  h4("Visualization"),
79
  selectInput("factor", "Select Factor to Display:",
 
83
  p("1. Select a case type and, for Average case, a respondent group."),
84
  p("2. Specify the single lambda to be used by strategize."),
85
  p("3. Click 'Compute Results' to generate optimal strategies."),
86
+ p("4. Choose a factor to view its distribution."),
87
+ p("5. Use 'View Previous Results' to toggle among past computations.")
88
  ),
89
 
90
  mainPanel(
 
100
  p("**Average Case**: Optimizes candidate characteristics for a selected respondent group."),
101
  p("**Adversarial Case**: Finds equilibrium strategies for Democrats and Republicans, identified by 'Pro-life' stance.")
102
  )
103
+ ),
104
+ br(),
105
+ wellPanel(
106
+ h4("Currently Selected Computation:"),
107
+ verbatimTextOutput("selection_summary")
108
  )
109
  )
110
  )
 
116
  load("Processed_OnoData.RData")
117
  Primary2016 <- read.csv("PrimaryCandidates2016 - Sheet1.csv")
118
 
119
+ # Prepare a storage structure for caching multiple results
120
+ cachedResults <- reactiveValues(data = list())
121
+
122
+ # Dynamic update of factor choices
123
  observe({
124
  if (input$case_type == "Average") {
125
  factors <- colnames(FACTOR_MAT_FULL)[!colnames(FACTOR_MAT_FULL) %in% c("Office")]
 
129
  updateSelectInput(session, "factor", choices = factors, selected = factors[1])
130
  })
131
 
132
+ # Observe "Compute Results" button to generate a new result and cache it
133
+ observeEvent(input$compute, {
134
  withProgress(message = "Computing optimal strategies...", value = 0, {
 
135
  incProgress(0.2, detail = "Preparing data...")
136
 
137
+ # Common hyperparameters
138
  params <- list(
139
  nSGD = 1000L,
140
  batch_size = 50L,
 
150
  # Grab the single user-chosen lambda
151
  my_lambda <- input$lambda_input
152
 
153
+ # We'll define a label to track the result uniquely
154
+ # Include the case type, group (if Average), and lambda in the label
155
+ if (input$case_type == "Average") {
156
+ label <- paste("Case=Average, Group=", input$respondent_group, ", Lambda=", my_lambda, sep="")
157
+ } else {
158
+ label <- paste("Case=Adversarial, Lambda=", my_lambda, sep="")
159
+ }
160
+
161
  if (input$case_type == "Average") {
162
  # Subset data for Average case
163
  if (input$respondent_group == "All") {
164
+ indices <- which(my_data$Office == "President")
165
  } else {
166
+ indices <- which(
167
+ my_data_FULL$R_Partisanship == input$respondent_group &
168
+ my_data$Office == "President"
169
+ )
170
  }
171
 
172
  FACTOR_MAT <- FACTOR_MAT_FULL[indices,
173
+ !colnames(FACTOR_MAT_FULL) %in% c("Office","Party.affiliation","Party.competition")]
174
  Yobs <- Yobs_FULL[indices]
175
  X <- X_FULL[indices, ]
176
  log_pr_w <- log_pr_w_FULL[indices]
 
179
 
180
  incProgress(0.4, detail = "Running strategize...")
181
 
182
+ # Compute with strategize
183
  Qoptimized <- strategize(
184
  Y = Yobs,
185
  W = FACTOR_MAT,
 
191
  diff = TRUE,
192
  adversarial = FALSE,
193
  use_regularization = TRUE,
194
+ K = 1L,
195
  nSGD = params$nSGD,
196
  penalty_type = params$penalty_type,
197
  folds = params$nFolds,
 
201
  conda_env = params$conda_env,
202
  conda_env_required = params$conda_env_required
203
  )
204
+
205
+ } else {
206
+ # Adversarial case
207
+
208
  DROP_FACTORS <- c("Office", "Party.affiliation", "Party.competition")
209
  FACTOR_MAT <- FACTOR_MAT_FULL[, !colnames(FACTOR_MAT_FULL) %in% DROP_FACTORS]
210
  Yobs <- Yobs_FULL
 
212
  log_pr_w <- log_pr_w_FULL
213
  assignmentProbList <- assignmentProbList_FULL[!names(assignmentProbList_FULL) %in% DROP_FACTORS]
214
 
 
215
  incProgress(0.3, detail = "Preparing slate data...")
216
+
217
  FactorOptions <- apply(FACTOR_MAT, 2, table)
218
  prior_alpha <- 10
219
  Primary_D <- Primary2016[Primary2016$Party == "Democratic", colnames(FACTOR_MAT)]
 
239
 
240
  slate_list <- list("Democratic" = Primary_D_slate, "Republican" = Primary_R_slate)
241
 
242
+ indices <- which(
243
+ my_data$R_Partisanship %in% c("Republican","Democrat") &
244
+ my_data$Office == "President"
245
+ )
246
  FACTOR_MAT <- FACTOR_MAT_FULL[indices,
247
+ !colnames(FACTOR_MAT_FULL) %in% c("Office","Party.competition","Party.affiliation")]
 
 
248
  Yobs <- Yobs_FULL[indices]
249
  my_data_red <- my_data_FULL[indices,]
250
  pair_id <- pair_id_FULL[indices]
251
+ cluster_var <- cluster_var_FULL[indices]
252
+ my_data_red$Party.affiliation_clean <- ifelse(
253
+ my_data_red$Party.affiliation == "Republican Party",
254
+ yes = "Republican",
255
+ no = ifelse(my_data_red$Party.affiliation == "Democratic Party","Democrat","Independent")
256
+ )
257
 
 
258
  assignmentProbList <- assignmentProbList_FULL[colnames(FACTOR_MAT)]
259
  slate_list$Democratic <- slate_list$Democratic[names(assignmentProbList)]
260
  slate_list$Republican <- slate_list$Republican[names(assignmentProbList)]
261
 
262
  incProgress(0.4, detail = "Running strategize...")
263
 
 
264
  Qoptimized <- strategize(
265
  Y = Yobs,
266
  W = FACTOR_MAT,
 
267
  X = NULL,
268
  p_list = assignmentProbList,
269
  slate_list = slate_list,
 
281
  use_regularization = TRUE,
282
  force_gaussian = FALSE,
283
  adversarial = TRUE,
 
284
  K = 1L,
285
  nMonte_adversarial = 20L,
286
  nSGD = params$nSGD,
 
294
  )
295
 
296
  # Identify Democrat vs Republican based on "Pro-life" stance
297
+ prolife_probs <- c(
298
+ Qoptimized$pi_star_point$Democrat$Position.on.abortion["Pro-life"],
299
+ Qoptimized$pi_star_point$Republican$Position.on.abortion["Pro-life"]
300
+ )
301
  which_repub <- which.max(prolife_probs)
302
  if (which_repub == 1) {
303
+ # Swap if the first is actually "Republican"
304
+ Qoptimized$pi_star_point <- list(k1 = Qoptimized$pi_star_point$k2,
305
+ k2 = Qoptimized$pi_star_point$k1)
306
+ Qoptimized$pi_star_se <- list(k1 = Qoptimized$pi_star_se$k2,
307
+ k2 = Qoptimized$pi_star_se$k1)
308
  }
309
  }
310
 
311
  incProgress(0.8, detail = "Finalizing results...")
312
+
313
+ # Store in the reactiveValues cache
314
+ cachedResults$data[[label]] <- Qoptimized
315
+
316
+ # Update the choice list for previous results
317
+ updateSelectInput(session, "previousResults",
318
+ choices = names(cachedResults$data),
319
+ selected = label)
320
  })
321
  })
322
 
323
+ # Reactive to pick the result the user wants to display
324
+ selectedResult <- reactive({
325
+ validate(
326
+ need(input$previousResults != "", "No result computed or selected yet.")
327
+ )
328
+ cachedResults$data[[input$previousResults]]
329
+ })
330
+
331
  # Render strategy plot
332
  output$strategy_plot <- renderPlot({
333
+ req(selectedResult())
334
  factor_name <- input$factor
335
+ pi_star_list <- selectedResult()$pi_star_point
336
+ pi_star_se_list <- selectedResult()$pi_star_se
337
  plot_factor(pi_star_list, pi_star_se_list, factor_name)
338
  })
339
 
340
  # Render Q value
341
  output$q_value <- renderText({
342
+ req(selectedResult())
343
+ q_point <- selectedResult()$Q_point_mEst
344
+ q_se <- selectedResult()$Q_se_mEst
345
  paste("Estimated Q Value: ", sprintf("%.3f ± %.3f", q_point, 1.96 * q_se))
346
  })
347
+
348
+ # Show which set of parameters (label) is currently selected
349
+ output$selection_summary <- renderText({
350
+ input$previousResults
351
+ })
352
  }
353
 
354
  # Run the app