Nothing
#
# This is a Shiny web application.
#
library("shiny")
library("shinydashboard")
library("shinyjs")
library("shinyDTC")
distance <- function(x, y, method="euclidean") {
n <- nrow(x)
k <- nrow(y)
as.matrix(dist(rbind(y, x), method=method))[k+1:n,1:k]
}
gettext <- function(txt) { txt } # Currently only support for English
# data preparation
file <- getOption("shinyDTC.data")
x <- try({ readRDS(file) }, silent = TRUE)
if (inherits(x, "try-error") || !is.data.frame(x) || (nrow(x)==0) || (ncol(x)!=2)) x <- faithful[sample(nrow(faithful), 25),]
#stopifnot("'x' should be a data frame"=is.data.frame(x))
#x <- x[, sapply(x, is.numeric)]
#stopifnot("'x' should have two colums"=(ncol(x)==2))
x <- scale(x[complete.cases(x),]) # delete all NA's and standardize
mx <- max(abs(x))
#
schoices <- gettext(c("K-Means", "K-Median", "K-Means++", "K-Medoid"))
choices <- structure(as.list(seq_along(schoices)), names=schoices)
ui <- dashboardPage(
dashboardHeader(title="MM*Stat",
tags$li(
class = "dropdown",
tags$div(
style = "margin-right: 15px; margin-top: 10px;",
actionButton("quit", "Quit")
))),
dashboardSidebar(
useShinyjs(),
radioButtons("method", gettext("Method"), choices),
numericInput("ncluster", gettext("Cluster"), 2, min=2, max=10, step=1),
timerInput("gonzales"),
collapsed = FALSE
),
dashboardBody(
plotOutput("plot", height = "80vh")
)
)
appenv <- new.env()
server <- function(input, output, session) {
tr <- timer("gonzales", input, session)
observeEvent({ input$method ; input$ncluster } , { resetTimer("gonzales") })
observeEvent(input$quit, { stopApp() })
output$plot <- renderPlot({
oldpar <- par(no.readonly = TRUE) # saves the original settings
on.exit(par(oldpar)) # restores them automatically when done
t <- tr()
n <- nrow(x)
col <- rep("black", n)
ncluster <- isolate(input$ncluster)
method <- as.integer(isolate(input$method))
smethod <- names(choices)[method]
colk <- rainbow(ncluster)
par(mar=c(5.1, 4.1, 2.1, 2.1))
if (method==1) { # K-Means
if (t==0) {
repeat {
appenv$center <- matrix(runif(2*ncluster, -mx, mx), ncol=2)
appenv$dist <- NULL
d <- distance(x, appenv$center)
cluster <- apply(d, 1, which.min)
if (all(table(cluster)>1)) break
}
} else {
for (i in 1:ncluster) appenv$center[i,] <- apply(x[appenv$cluster==i,,drop=FALSE], 2, mean)
}
d <- distance(x, appenv$center)
appenv$cluster <- apply(d, 1, which.min)
appenv$dist <- c(appenv$dist, sum(apply(d, 1, min)))
}
if (method==2) { # K-Median
if (t==0) {
repeat {
appenv$center <- matrix(runif(2*ncluster, -mx, mx), ncol=2)
appenv$dist <- appenv$sdist <- NULL
d <- distance(x, appenv$center, method = "manhattan")
cluster <- apply(d, 1, which.min)
if (all(table(cluster)>1)) break
}
} else {
for (i in 1:ncluster) appenv$center[i,] <- apply(x[appenv$cluster==i,,drop=FALSE], 2, median)
}
d <- distance(x, appenv$center)
appenv$cluster <- apply(d, 1, which.min)
appenv$dist <- c(appenv$dist, sum(apply(d, 1, min)))
}
if (method==3) { # K-Means++
if (t<ncluster) {
if (t==0) {
appenv$center <- matrix(NA, ncol=2, nrow=ncluster)
appenv$dist <- NULL
i <- sample(n, 1)
} else {
d <- distance(x, appenv$center)
d <- apply(d, 1, min, na.rm=TRUE)
i <- sample(length(d), 1, prob=d^2) # exponential growth
}
appenv$center[t+1,] <- x[i,]
} else{
for (i in 1:ncluster) appenv$center[i,] <- apply(x[appenv$cluster==i,,drop=FALSE], 2, mean)
}
d <- distance(x, appenv$center)
appenv$cluster <- apply(d, 1, which.min)
dc <- sum(apply(d, 1, min, na.rm=TRUE))
appenv$dist <- c(appenv$dist, dc)
}
if (method==4) { # K-Medoid
if (t==0) { # init
icenter <- sample(n, ncluster)
appenv$dist <- NULL
} else { # swap
icenter <- appenv$icenter
# d <- apply(distance(x, x[icenter,]), 1, min, na.rm=TRUE)
icenter[sample(ncluster, 1)] <- sample(1:n, 1)
}
d <- distance(x, x[icenter,])
dc <- sum(apply(d, 1, min))
if (all(appenv$dist>dc)) { # if better keep the configuration
appenv$icenter <- icenter
appenv$center <- x[appenv$icenter,]
appenv$cluster <- apply(d, 1, which.min)
appenv$dist <- c(appenv$dist, dc)
}
layout(matrix(c(1,3,2,3), ncol=2), heights=c(2,1))
plot(x, pch=19, col=colk[appenv$cluster], asp=TRUE, xlim=-c(-mx, mx), ylim=c(-mx, mx), sub=paste(smethod, "(best)"))
points(appenv$center, pch="+", cex=2, col=colk)
cluster <- apply(d, 1, which.min)
plot(x, pch=19, col=colk[cluster], asp=TRUE, xlim=-c(-mx, mx), ylim=c(-mx, mx), sub=paste(smethod, "(candidate)"))
points(x[icenter,], pch="+", cex=2, col=colk)
plot(c(appenv$dist, dc), type="b", xlab="t", ylab="", pch=19, sub="Sum of distances to cluster centers")
} else {
layout(1:2, heights=c(2,1))
plot(x, pch=19, col=colk[appenv$cluster], asp=TRUE, xlim=-c(-mx, mx), ylim=c(-mx, mx), sub=smethod)
points(appenv$center, pch="+", cex=2, col=colk)
plot(appenv$dist, type="b", xlab="t", ylab="", pch=19, sub="Sum of distances to cluster centers")
}
})
}
shinyApp(ui, server)
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.