library(tidyverse) library(janitor) library(stats) library(gt) library(learnr) source("theme_qcc.R") source("chart_Cpk.R") source("process_stats.R") source("process_stats_table.R") source("off_spec.R") source("process_Cpk.R") filter <- dplyr::filter select <- dplyr::select tablet_weight <- read_rds("tablet_weight.rds") knitr::opts_chunk$set(echo = FALSE, message = FALSE, warning = FALSE)
To get a new industrial product to the market there is often a long process that goes from the initial discussions and briefings to the start of production on the shop floor. For products produced in millions or billions of units this process can take several years but once its completed the specifications often remain stable for years.
This is why it is important to assess the capability of the manufacturing processes and to define good specifications from the start. For the characteristics that are critical to quality (CTQ) we may decide to implement a statistical process control (SPC).
Quality control is know for its many acronyms (we've just seen already seen CTQ, SPC). Would you know some more?
question( "Write down the acronyms of upper control limit, lower control limit, upper specification limit, lower specification limit, parts per million, standard operating procedure.", answer("UCL,LCL,USL,LSL,PPM,SOP", correct = TRUE), type = "learnr_text", try_again = "Use capitals, separated by a comma and no spaces (e.g: CTQ,SPC,...).", post_message = "Well done.", allow_retry = TRUE, options = list( placeholder = "USL,...", trim = TRUE ) )
For this exercise we've loaded the {industRial} package in memory with library(industRial). It comes with various simple functions in the area of SPC that can be used as a starting point to build dashboards and advanced applications, e.g. off_spec() and process_Cpk(). How can we easily check the arguments that the functions take?
dput(formals(process_Cpk))
It was useful to see in the previous question what USL means!
What about if we wanted to see the code inside the function? We're giving a hint but better workout your memory before!
body(process_Cpk)
As said its a rather simple function but it proves very helpful if we know the specification limits, the process mean and its standard deviation.
Lets now try all these ideas together in a dynamic context. In the app below the specification limits are calculated as a percentage of the specification target, starting with 10%. This means that for a target of 0.90 we have a min of 0.81 and a max of 0.99 [g]. In these circumstances the percentage out of specification is of 2.39%, very high for industry standards.
Check the following points below:
fluidPage( titlePanel("Process Capability Study"), fluidRow( column(6, plotOutput("capability_chart")), column(6, gt_output("statistics_table") ) ), fluidRow( # column(3), column(3, sliderInput( width = 150, "spec_perc", "Specification tolerance [%]", min = 1, max = 16, value = 9, step = 1 ) ), column(3, sliderInput( width = 150, "spec_deviation", "Specification deviation [g]", min = -0.1, max = +0.2, value = 0.0, step = 0.01 ) ) ) )
tablet_weight_clean <- reactive({ tablet_weight %>% janitor::clean_names(case = "snake") %>% mutate(weight_target_value = weight_target_value + input$spec_deviation) }) weight_statistics_data <- reactive({ process_stats( data = tablet_weight_clean(), part_spec_percent = input$spec_perc ) }) weight_normal <- reactive({ stats::rnorm( n = 100000, mean = mean(weight_statistics_data() %>% pull(weight_mean)), sd = mean(weight_statistics_data() %>% pull(weight_sd)) ) %>% as_tibble() }) output$capability_chart <- renderPlot({ chart_Cpk(weight_statistics_data()) + ggplot2::geom_density( data = weight_normal(), ggplot2::aes(x = value), linetype = 2 ) + expand_limits(x = c(0.7, 1.1)) }) output$statistics_table <- render_gt({ process_stats_table(weight_statistics_data()) %>% gt::fmt_number(columns = 2, decimals = 2) %>% gt::fmt_number(columns = 2, rows = Variable == "Sample size", decimals = 0) })
Finally a process capability chart is nothing more than our old histogram:
tablet_weight %>% clean_names() %>% ggplot(aes(x = weight_value)) + geom_histogram(fill = "grey80", color = "grey20") + labs( title = "Tablet weight process control", subtitle = "Process Capability chart", x = "Part Weight [g]", y = "Count", caption = "data source: Line1" ) + theme_qcc()
Enter below the code to obtain this histogram, using the tablet_weight data set:
tablet_weight %>% clean_names()
# Check out the chart_Cpk() function body, although there is more than a simple histogram the base is the same: body(chart_Cpk)
There are many different ways of expressing the process capability with various indexes that all resemble a bit. We've mostly been looking into the Cpk which takes into account the off centering of the process. From the function explored before we can now find out its mathematical formula.
question( "What is the exact mathematical formula to calculate the Cpk? (sd corresponds to the process standard deviation and sdLT to the long term standard deviation).", answer("(USL-LSL)/6sd", correct = FALSE, message = "This formula corresponds to the index Cp"), answer("6sd/(USL-LSL)", correct = FALSE, message = "This formula corresponds to the index Cr"), answer("min{(xbar-LSL)/3sd;(USL-xbar)/3sd}", correct = TRUE, message = "This formula corresponds to the index Cpk"), answer("(USL-LSL)/6sdLT", correct = FALSE, message = "This formula corresponds to the index Pp"), allow_retry = TRUE )
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.