Skip to content

Instantly share code, notes, and snippets.

@yabyzq
Last active February 20, 2017 12:56
Show Gist options
  • Save yabyzq/d1aa7c240071df581c775a370d229e70 to your computer and use it in GitHub Desktop.
Save yabyzq/d1aa7c240071df581c775a370d229e70 to your computer and use it in GitHub Desktop.
Shiny App on SOM
# based on Manuel Bernal's code
######## SOM GENERATOR ###########
#Loading Packages needed
library(png) # For writePNG function
library(kohonen)
library(shiny)
library(ggplot2)
library(jsonlite)
library(Hmisc)
library(gridExtra)
options(shiny.maxRequestSize=500*1024^2)#maximum 500mb file
#Start shiny server
shinyServer(function(input, output, session) {
#Reading file, inputs must be numeric
dataInput <- reactive({
inFile <- input$file1
players<-read.csv(inFile$datapath, header=input$header, sep=input$sep,
stringsAsFactors=FALSE)
})
#Generate SOM
generateSOM <- reactive({
head(dataInput())
players.sc <- scale(dataInput()) #Scale input
set.seed(15675)
players.som <- som(players.sc, grid = somgrid(input$slider1, input$slider2, input$fig)) #fig in "rectangular", "hexagonal"
})
#Generate Graphs
generateGraph = function(){
if (is.null(input$file1))
return(NULL)
else{
coolBlueHotRed <- function(n, alpha = 1) {
rainbow(n, end=4/6, alpha=alpha)[n:1]
}
plot(generateSOM(),type = input$select, main = "SOM", palette.name = coolBlueHotRed)
}
}
#Converts SOM to table
somToTable = function(){
as.table( as.matrix(generateSOM()) )
}
#RenderGraph
output$visual<-renderPlot({
generateGraph()
},height = 800, width = 800 )
#DownloadImpage
output$downloadData <- downloadHandler(
filename = "shiny_som_plot.png",
content = function(file) {
png(file,width=800,height=800)
generateGraph()
dev.off()
})
#Download structure
output$downloadTabla <- downloadHandler(
filename = "shiny_som_data.csv",
content = function(file) {
write.table(somToTable(), file, sep = ",",row.names = FALSE)
}
)
output$table <- DT::renderDataTable(
if (is.null(input$file1))
return(NULL)
else{
DT::datatable(dataInput(), options = list(searching = FALSE))
}
)
output$histogram<-renderPlot({
if (is.null(input$file1))
return(NULL)
else{
hist.data.frame(dataInput())
}
},height = 800, width = 800 )
output$property<-renderPlot({
if (is.null(input$file1))
return(NULL)
else{
coolBlueHotRed <- function(n, alpha = 1) {rainbow(n, end=4/6, alpha=alpha)[n:1]}
som_model <- generateSOM()
col <- ncol(som_model$data)
if (col > 4) {par(mfrow=c(3,3))} else {par(mfrow=c(2,2))}
for (i in 1:min(col, 9)){
plot(som_model, type = "property", property = som_model$codes[,i], main=colnames(som_model$data)[i], palette.name=coolBlueHotRed)
}
# var <- 2 #define the variable to plot
# var_unscaled <- aggregate(as.numeric(data_train[,var]), by=list(som_model$unit.classif), FUN=mean, simplify=TRUE)[,2]
# plot(som_model, type = "property", property=var_unscaled, main=names(data_train)[var], palette.name=coolBlueHotRed)
}
},height = 800, width = 800 )
output$cluster<-renderPlot({
if (is.null(input$file1))
return(NULL)
else{
som_model <- generateSOM()
som_cluster <- cutree(hclust(dist(som_model$codes)), input$clusterSize)
pretty_palette <- c("#1f77b4", '#ff7f0e', '#2ca02c', '#d62728', '#9467bd', '#8c564b', '#e377c2', '#76b7b2')
if (input$clusterChart){
par(mfrow=c(2,2))
codes <- som_model$codes
wss <- (nrow(codes)-1)*sum(apply(codes,2,var))
for (i in 2:15) {
wss[i] <- sum(kmeans(codes, centers=i)$withinss)
}
plot(wss, main = "Cluster WSS", xlab = "no of clusters")
#plot.new()
pca <- prcomp(som_model$codes, center = TRUE,scale. = TRUE)
plot(pca$x[,1], pca$x[,2], col = som_cluster, main = "PCA", xlab = "PCA1", ylab = "PCA2")
}else{
par(mfrow=c(1,2))
}
plot(som_model, type="codes", main = "SOM Code")
plot(som_model, type="mapping", bgcol = pretty_palette[som_cluster], main = "Clusters")
add.cluster.boundaries(som_model, som_cluster)
}
},height = 800, width = 800 )
output$info <- renderText({
if (is.null(input$file1) | is.null(input$plot_click))
return(NULL)
else {
x = 1
y = 4.82
xmax = 6
ymax = 0.36
y_offset = (ymax - y)/5
yn = ceiling((input$plot_click$y - y) / y_offset)
if (yn %% 2 == 0){
x = x - 0.5
xmax = xmax - 0.5
}
x_offset = (xmax - x)/5
xn = ceiling((input$plot_click$x - x) / x_offset)
paste0("x=", input$plot_click$x, "\ny=", input$plot_click$y, "\ncell = " , xn, ",", yn )
# grid <- som_model$grid$pts
# gridFrame <- data.frame(xvar = grid[,1], yvar = grid[,2])
# print(str(gridFrame))
# print(nearPoints(som_model, input$plot_click, xvar = "xvar", yvar = "yvar", maxpoints = 1))
}
})
output$distribution<-renderPlot({
if (is.null(input$file1) | is.null(input$plot_click))
return(NULL)
else{
x = 1
y = 4.82
xmax = 6
ymax = 0.36
y_offset = (ymax - y)/5
yn = ceiling((input$plot_click$y - y) / y_offset)
if (yn %% 2 == 0){
x = x - 0.5
xmax = xmax - 0.5
}
x_offset = (xmax - x)/5
xn = ceiling((input$plot_click$x - x) / x_offset)
som_model <- generateSOM()
population <- cbind(dataInput(), som = som_model$unit.classif)
column = input$slider1
index = xn+(yn-1)*column
print(index)
cell <- population[population$som == index,]
combined <- rbind(cbind(population, label = 'population'), cbind(cell, label = 'cell'))
par(mfrow=c(2,2))
p1 <- ggplot(combined, aes(x=combined[, 1]) ) + geom_density(aes(fill = label), alpha=0.2) + xlab(names(combined)[1]) + guides(fill=FALSE)
p2 <- ggplot(combined, aes(x=combined[, 2]) ) + geom_density(aes(fill = label), alpha=0.2) + xlab(names(combined)[2]) + guides(fill=FALSE)
p3 <- ggplot(combined, aes(x=combined[, 3]) ) + geom_density(aes(fill = label), alpha=0.2) + xlab(names(combined)[3]) + guides(fill=FALSE)
p4 <- ggplot(combined, aes(x=combined[, 4]) ) + geom_density(aes(fill = label), alpha=0.2) + xlab(names(combined)[4]) + guides(fill=FALSE)
grid.arrange(p1, p2, p3, p4, ncol=2)
}
})
})
# based on Manuel Bernal's code
library(shiny)
shinyUI(fluidPage(
titlePanel("Self-Organized-Maps"),
fluidRow(
sidebarPanel(
radioButtons('select', 'Graph Type', choices = c("Codebook" = "code",
"Training mean distance" = "changes",
"Objects per unit" = "counts",
"Distance to neighbours - class boundary have higher distance" = "dist.neighbours",
"Distance to codebook - lower the better" = "quality"), selected = 1),
selectInput("fig", label = "Shape",
choices = list("Hexagonal" = "hexagonal", "Rectangular" = "rectangular"),
selected = 1),
sliderInput("slider1", label = "Granularity X", min = 1,
max = 50, value = 5),
sliderInput("slider2", label = "Granularity Y", min = 1,
max = 50, value = 5),
sliderInput("clusterSize", label = "Cluster Size", min = 2,
max = 10, value = 4),
checkboxInput('clusterChart', 'Cluster wss plot ', TRUE),
tags$hr(),
tags$br(),
fileInput('file1', 'Select CSV',accept=c('text/csv','text/comma-separated-values,text/plain','.csv')),
checkboxInput('header', 'Header', TRUE),
selectInput("sep", label = "Separator",
choices = list("Coma" = ",", "Semicolon" = ";", "Tab" = '\t'),
selected = 1),
# selectInput("quote", label = "Quote",
# choices = list("Any"='','Double Quotes'='"','Single Quotes'="'"),
# selected = 1),
downloadButton('downloadData', 'Save as (PNG)'),
downloadButton('downloadTabla', 'Save SOM as (CSV)')
, verbatimTextOutput("info"),
plotOutput('distribution', width = "100%")
),
mainPanel(
navbarPage(
title = 'Generate SOM',
tabPanel('Table', helpText(" This table shows the content of the entered data. In order to generate the diagrams all values must be numeric."),
DT::dataTableOutput('table') ),
tabPanel('Histogram', helpText(" Generate histograms to inspect data"),
plotOutput('histogram'), width = "100%" ),
tabPanel('SOM', plotOutput('visual', width = "100%",click = "plot_click",hover = "plot_hover") ),
tabPanel('SOM Property', plotOutput('property', width = "100%") ),
tabPanel('SOM Cluster', plotOutput('cluster', width = "100%") )
)
)
)
))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment