Tuesday, 30 May 2017

Manpower Planning using Shiny in R

Manpower  planning is an operational problem that requires determining number of manpower for performing standardised work. The post focuses on implementation of such system with use of functional programming in R. Shiny is a powerful library available in R that helps in intertwining code with user interface (ui) for building a GUI (graphical user interface). We will describe R scripts for server and ui as we go along with the implementation. 



Script for ui in R
First step is to load the shiny package.

library(shiny)

Next define the UI for random distribution application

shinyUI(fluidPage(

The title of application in GUI window is created as:

titlePanel("Workstation Manpower Planning"),

The sidebar layout is created with controls to select the random distribution type and number of observations to generate. Note that the use of the br() element is to introduce extra vertical spacing. In side bar panel, input files are loaded as csv. Product changeover data sets account for change over time in switching from one product to another product. ProductChangeover.csv file consists of workstation, from product, to product and associated changeover time. Demand file has associated demand for the three products. Work station available time depicts the time available at workstation in a shift, by removing the downtime. Work content provides statistics for operation time of different products at various workstations. The statistics are mean and standard deviation of set up and manual time, while fixed processing times on machines, if any. Data sets are shown at end of posts for your understanding.




  sidebarLayout(
    sidebarPanel(
      fileInput('WCfile', 'Select the Workcontent.csv file',
                accept=c('text/csv','text/comma-separated-values,text/plain','.csv')),
      tags$hr(),
      fileInput('COfile', 'Select the ProductChangeover.csv file',
                accept=c('text/csv','text/comma-separated-values,text/plain','.csv')),
      tags$hr(),
      fileInput('DEMfile', 'Select the Demand.csv file',
                accept=c('text/csv','text/comma-separated-values,text/plain','.csv')),
      tags$hr(),
      fileInput('WSATfile', 'Select the Workstationavailtimes.csv file',
                accept=c('text/csv','text/comma-separated-values,text/plain','.csv')),
      tags$hr(),
      helpText("All .csv files must be uploaded in required format under headers")
    ),

Next, we have the main panel that is declare in tab form with three categories: first one is output table on planned manpower allocation at the workstations, second tab is balancing efficiency plot and third tab is plotting of product mix losses.

    mainPanel(
      tabsetPanel(type="tab",
                  tabPanel("Summary - Workstation Planned Manpower",dataTableOutput("mytable")),
                  tabPanel("Plot- Workstation Manpower Efficiency", plotOutput("myplot")),
                  tabPanel("Plot - Workstation Product Mix Loss", plotOutput("myplot1"))
                  )
   
    )
  ))

)


Script for server in R:

First we load the shiny library:

library(shiny)

Next, we create a function under shinyServer that declares input from ui script.

shinyServer(function(input, output) {

  observe({
    WCfile = input$WCfile
    COfile = input$COfile
    DEMfile = input$DEMfile
    WSATfile = input$WSATfile
    if (is.null(WCfile) || is.null(COfile) || is.null(DEMfile) || is.null(WSATfile)) {
      return(NULL)
    }

The input data is stored in different data frames from csv files for work content, product changeover times, demand and workstation available times.
 
    workcontent.df <- data.frame(read.csv(WCfile$datapath))
    productco.df <- data.frame(read.csv(COfile$datapath))
    dem.df <- data.frame(read.csv(DEMfile$datapath))
    wsavailtim.df <- data.frame(read.csv(WSATfile$datapath))
 
Step 1 calculations require determining maximum manual work content for each workstation among all products which is MAX(Manual time + Set-up time) + MAX(Change-over time)

 
    workcontent.df$totalmanualtime <- workcontent.df$Mean_Set.up + workcontent.df$SD_Set.up + workcontent.df$Mean_Manual + workcontent.df$SD_Manual
    co.df <- data.frame(Workstation=productco.df$Workstation, time=productco.df$Changeover_time)
    maxcotime.df <- aggregate(.~Workstation,co.df,FUN = max)
    wc.df <- data.frame(Workstation=workcontent.df$Workstation,time=workcontent.df$totalmanualtime)
    maxwc.df <- aggregate(.~Workstation,wc.df,FUN = max)
    aggregwc.df <- rbind(maxwc.df,maxcotime.df)
    manualwc.df <- aggregate(.~Workstation,aggregwc.df,FUN = sum)
 

Step 2 Calculations is to determine maximum production units for each workstation i.e. SUM(Workstation production units for all products)
 
    wswc.df <-data.frame(Workstation=workcontent.df$Workstation,Product=workcontent.df$Product)
    demwspr.df <- merge(wswc.df,dem.df,by="Product")
    aggrdemws.df <- data.frame(Workstation=demwspr.df$Workstation,Demand=demwspr.df$Demand)
    aggrdemws.df <- aggregate(.~Workstation,aggrdemws.df,FUN = sum)
 
 
Step 3 calculations determine cycle time for each workstation i.e. Max production units / Available time. Step 4 determines number of workers for each workstation as ROUNDUP(Max work content/Cycle time) and Step 5 determine Manpower Efficiency for each workstation as (# Operators/(Max work content/Cycle time))
 
    cycletime.df <- merge(wsavailtim.df,aggrdemws.df,by="Workstation")
    cycletime.df$ct <- cycletime.df$Demand/cycletime.df$Availabletime
    NoofOper.df <- merge(manualwc.df,cycletime.df,by="Workstation")
    NoofOper.df$Operators <- ceiling(NoofOper.df$time/NoofOper.df$ct)
    NoofOper.df$Efficiency <- round(((NoofOper.df$time/NoofOper.df$ct)/NoofOper.df$Operators)*100,0)
    NoofOpersop.df <- data.frame(Workstation = NoofOper.df$Workstation, Number_Of_Manpower = NoofOper.df$Operators,Manpower_Efficiency = paste(NoofOper.df$Efficiency,"%"))
    NoofOpersef.df <- data.frame(Workstation = NoofOper.df$Workstation, Manpower_Efficiency = NoofOper.df$Efficiency)
 
Step 6 calculates product mix loss percentage for the workstations. First, calculate the manual time by adding mean and standard deviations of manual time and set up time. This will aid in design of workstation for maximum time. Next, multiply the total work content with demand of the products for the workstations. After that, get the total work content on the workstations, obtained by summing it up for all products. The design of workstation requires work content that is multiplication of Step 1 and Step 2 time and quantities. The product mix loss percentage is [1 - (Actual Work content / Design Work content)].
 
    wcwspr <- data.frame(Workstation = workcontent.df$Workstation,Product = workcontent.df$Product, time_des = workcontent.df$totalmanualtime)
    wcwspr <- merge(wcwspr,dem.df,by="Product")
    wcwspr$ActualWC <- wcwspr$time_des * wcwspr$Demand
    aggrwcws <- aggregate(.~Workstation,data = wcwspr,FUN = sum)
    aggrwcws <- merge(aggrwcws,manualwc.df,by="Workstation")
    aggrwcws$DesgnWC <- aggrwcws$time * aggrwcws$Demand
    aggrwcws$ProductMixLoss <- (1 - (aggrwcws$ActualWC/aggrwcws$DesgnWC)) * 100
    aggrwcws$ProductMixLoss <- round(aggrwcws$ProductMixLoss)
    aggrwcwsref <- data.frame(Workstation = aggrwcws$Workstation, Product_Mix_Loss = paste(aggrwcws$ProductMixLoss,"%"))
    aggrwcwsplot <- data.frame(Workstation = aggrwcws$Workstation, Product_Mix_Loss = aggrwcws$ProductMixLoss)

Merge two data frames to get number of operators by workstation.
 
    NoofOpersop.df <- merge(NoofOpersop.df,aggrwcwsref,by="Workstation")
 
 
Finally, delete unwanted data frames
 
    rm(list=c("aggrdemws.df","aggregwc.df","co.df","cycletime.df","demwspr.df","manualwc.df","maxcotime.df","maxwc.df","wc.df","wswc.df"))
 
 
The last step is to display and plot the output for the three tabs. First, render data table to display number of operators, load lattice package and plot bar chart for efficiency and product mix loss for the workstations.
 
    output$mytable <- renderDataTable({NoofOpersop.df})
 
    library(lattice)
    output$myplot <- renderPlot({
     barchart(Manpower_Efficiency~Workstation,data=NoofOpersef.df,label = NoofOpersef.df$Manpower_Efficiency,col="grey",main="Workstation Manpower Efficiency",xlab = "Workstation",ylab = "Efficiency (%)",ylim=c(0,100))
    })
 
    output$myplot1 <- renderPlot({
      barchart(Product_Mix_Loss ~ Workstation,data=aggrwcwsplot,xlab="Workstation",ylab="Product Loss Percentage",col="blue",ylim=c(0,100))
    })
 
  })

})

Datasets (.csv)

1. Workstationavailtimes.csv


Workstation Availabletime
WS1 420
WS2 420
WS3 420
WS4 420

2. Workcontent.csv

Workstation Product Mean_Set-up SD_Set-up Mean_Manual SD_Manual Machine Time
WS1 A 11 3 28 11 5
WS1 B 4 1 12 3 6
WS1 C 3 1 8 2 4
WS2 A 5 2 12 10 12
WS2 B 7 3 15 5 8
WS3 A 5 3 37 26 0
WS4 A 14 5 34 6 24
3. Demand.csv

Product  Demand
A 4000
B 2500
C 1000

4. ProductChangeover.csv

Workstation From_Product To_Product Changeover_time
WS1 A B 4
WS1 B A 2
WS1 B C 1
WS1 C B 3
WS1 A C 2
WS1 C A 3
WS2 A B 5
WS2 B A 8

Output

The code will run the app to give three outputs on Summary, Plot of workstation manpower efficiency and Plot of workstation product mix loss.

Tuesday, 23 May 2017

Efficiency versus Productivity

For years, efficiency has been a curious parameter in manufacturing systems. But, there are soft factors in the shop floor that are not considered for analyzing the system in a more comprehensible manner. While, efficiency has been replaced with productivity it is still not able to come to terms with the way in which it has to be implemented in the system. Before, going ahead it is important that we understand the fundamental difference that differentiates the two manufacturing jargons with focus on their specific and generic interpretation.

Efficiency
Efficiency is measured by actual output production to aggregate capacity of resources in the manufacturing systems. Resources can be anything that is involved in the manufacturing operation, be it human workforce (or labor) and machines. Thus, we calculate efficiency as:

Efficiency = Actual output / Capacity

For illustration purpose, say capacity of a machine is 200 units per day and the output produced is 150 units per day on day 1 and 180 units per day on day 2. The efficiency of the machine is 75% and 90% for day 1 and day 2 respectively. The machine is a part of an assembly line with stated capacity of 120 units per day with assembled components into a finished product and the production for same day 1 and day 2 are 110 units and 100 units. The efficiency of the assembly line is 92% and 83% on day 1 and day 2. This doesn’t make more sense here as 75% efficiency of machine resulted in 92% efficiency of the line, while 90% efficiency resulted in 83% efficiency of the line. The actual reason for contradictory results will be explained later for better understanding. From, above formula we calculate the efficiency in a generic sense by aggregation of resources for a system and with single resource for a sub-system. The efficiency of a sub-system may not always provide the right answer, but would certainly make sense by determining efficiency of a system.
Determining the system boundaries is essential to understand what is within and beyond the capabilities of the system. The system has to operate within the stated external constraints and other resources are aggregated to work towards achieving the output by exploiting the internal constraints.  
Productivity                                                                                                               
Productivity is a rather better measure of the system performance as compared to efficiency, which is more like a performance tracker used for hiding the actual performance. Productivity of a manufacturing system is calculated as:
Productivity = Output produced / Inputs used


The productivity provides a rather better measure than efficiency which doesn’t consider the impact on output produced by the system. But, is there a consideration for difference between the system and sub-system for productivity calculation. To calculate the productivity of a sub-system, one has to build the link between sub-systems and output. If, one identifies that there is no direct value addition by a resource and it doesn’t contribute to output produced, than it is a clear indication of deficiency of the system. This where the concept of work content (or labor content) comes into the picture and provides a better understanding of direct labor, indirect labor, overheads, materials and depreciation among others. The different factors involved in the manufacturing must be tied together for a better understanding of the system capabilities. But, how does one calculate aggregate production cost and tie it down with labor, capital and materials in the system. It is wrong to compare a unit of measurement with different unit of measurement. To, avoid this it is important that everything is translated in the same scale for comparison of productivity and it is done first at aggregate level and then move down the ladder for identifying gaps in sub-systems for improvement opportunities.