Reputation: 1111
The code below generates a map with clusters. The cluster number will depend on the k
variable that is inside my function. To get this k
value, I use the Weighted Sum Method (WSM)
calculation. Note that for this calculation it is necessary to choose the weights of the criteria, in my case there are only two. Therefore, k
can vary depending on the chosen weights. In my function I manually put (weights <- c(0.5,0.5)
). However, I would like to put the weights from the two numericInput
I created. So how to do this? Another thing, in this case, the map is only generated after the weights are selected.
This question can help: Approach without inserting all the code on the server
library(shiny)
library(rdist)
library(geosphere)
library(shinythemes)
library(leaflet)
library(shinyjs)
function.cl<-function(df,k){
#database df
df<-structure(list(Properties = c(1,2,3,4,5,6,7),
Latitude = c(-23.8, -23.8, -23.9, -23.9, -23.9,-23.4,-23.5),
Longitude = c(-49.6, -49.3, -49.4, -49.8, -49.6,-49.4,-49.2),
Coverage = c (1526, 2350, 3526, 2469, 1285, 2433, 2456),
Production = c(526, 350, 526, 469, 285, 433, 456)), class = "data.frame", row.names = c(NA, -7L))
#Calculation WSM
weights <- c(0.5,0.5)
scaled <- df |>
mutate(Coverage = min(Coverage) / Coverage,
Production = Production / max(Production))
scaled <- scaled |>
rowwise() |>
mutate(`Performance Score` = weighted.mean(c(Coverage, Production), w = weights))
scaled$Rank <- (nrow(scaled) + 1) - rank(scaled$`Performance Score`)
k<-subset(scaled, Rank==2)$Properties #number of clusters
#clusters
coordinates<-df[c("Latitude","Longitude")]
d<-as.dist(distm(coordinates[,2:1]))
fit.average<-hclust(d,method="average")
clusters<-cutree(fit.average, k)
nclusters<-matrix(table(clusters))
df$cluster <- clusters
df1<-df[c("Latitude","Longitude")]
#Color and Icon for map
ai_colors <-c("red","gray","blue","orange","green","beige")
clust_colors <- ai_colors[df$cluster]
icons <- awesomeIcons(
icon = 'ios-close',
iconColor = 'black',
library = 'ion',
markerColor = clust_colors)
# Map for all clusters:
m1<-leaflet(df1) %>% addTiles() %>%
addMarkers(~Longitude, ~Latitude) %>%
addAwesomeMarkers(lat=~df$Latitude, lng = ~df$Longitude, icon=icons, label=~as.character(df$cluster)) %>%
addLegend( position = "topright", title="Cluster", colors = ai_colors[1:max(df$cluster)],labels = unique(df$cluster))
plot1<-m1
return(list(
"Plot1" = plot1
))
}
ui <- bootstrapPage(
useShinyjs(),
navbarPage(theme = shinytheme("flatly"), collapsible = TRUE,
"Cl",
tabPanel("Solution",
sidebarLayout(
sidebarPanel(
numericInput("weight1", label = h4("Weight 1"),
min = 0, max = 1, value = NA, step=0.1),
disabled(numericInput("weight2", label = h4("Weight 2"),
min = 0, max = 1, value = NA, step=0.1)),
helpText("The sum of weights should be equal to 1")),
mainPanel(
tabsetPanel(
tabPanel("Solution", (leafletOutput("Leaf1",width = "95%", height = "600")))))
))))
server <- function(input, output, session) {
Modelcl<-reactive({
function.cl(df,k)
})
output$Leaf1 <- renderLeaflet({
Modelcl()[[1]]
})
observeEvent(input$weight1, {
freezeReactiveValue(input, "weight2")
updateNumericInput(session, 'weight2', value = 1 - input$weight1)
})
}
shinyApp(ui = ui, server = server)
Upvotes: 0
Views: 57
Reputation: 24845
Why don't you redesign your function to this:
function.cl<-function(weights){
...
}
and in the reactive call on the server side you do this:
Modelcl<-reactive({
function.cl(weights=c(input$weight1, input$weight2))
})
Upvotes: 1