CKTG Catalog Analysis

CKTG Catalog Analysis

Tags
Analysis
R
Published
March 29, 2022

Summary

When it comes to selecting a new knife, a professional chef has several attributes to decide upon. When browsing a website that hosts more than a thousand knives, being able to make an informed decision about the relative prices of different knife constructions is a big advantage.
By breaking down the price distributions of each class of knives we can improve the buying experience for chefs looking to make their next purchase
Chef Knives To Go (written CKTG henceforth) is one of the most popular knife vendors among professional chefs. They have a catalog of more than 1000 knives across 23 styles and 18 varieties of steel. Coming to an informed decision on the price range for just one combination of style and steel can be time-consuming work, so an analysis of the dataset will greatly improve the shopping experience for any chef.

Catalog Breakdown

The following images show the number of knives in each form factor and each steel group
Form factors:
Plot 1
Plot 1
Steel groups:
Plot 2
Plot 2
While there are 18 varieties of steel, these can be broken down into 4 major categories: High Carbon, Carbon, Stainless, and Powdered
Plot 3
Plot 3
These breakdowns give us the insight that CKTG mainly specializes in Carbon Steel blades (representing 60% of the steel varieties), and Gyutos (representing 30% of the form factors).

Price analysis

The following boxplot displays the 8 most populous knife steel varities in the catalog by their median price
Plot 4
Plot 4
This chart shows us the difference of price by each steel type. For chefs, this chart can help build a mental model of the premiums associated with each variety of steel. By displaying the same boxplot above, but with only one style of knife, we can get a more concrete idea of the premium for that specific form factor.
Here it is with only Petty Knives, looking at the top 6 steel varieties.
Plot 5
Plot 5
 
The most represented knife style in the catalog is a Gyuto. A Gyuto is simply an all-purpose Japanese chef knife. Many knife vendors stock more Gyuto’s due to their versatility and the many lengths that they are made in.
For a chef selecting a Gyuto, finding the right combination of length, steel, and price can be a time-consuming challenge. For the tasks a chef chooses a Gyuto for, multiple lengths and steel combinations may serve the job equally well. By grouping these factors together and displaying their price range, a chef will be able to quickly come to a decision on the top knives for a job.
Here is a set of plots that display all of the combinations of Gyuto length, and steel type.
Plot 6
Plot 6
Although this simplifies the problem, combining all of the charts into one, and only selecting the steels and lengths that a chef is specifically looking for is a much cleaner solution.
Here is that solution. We will select only Gyutos between 210 and 240 mm, and only those that are carbon steel.
Plot 7
Plot 7
By building an interactive chart, we can create the optimal solution of allowing the consumer the chance to select the qualities that they most desire
Interactive Plot
The code to generate all of these plots is below

Code

#libraries used library(magrittr) library(dplyr) library(forcats) library(ggplot2) library(hrbrthemes) library(plotly) library(manipulateWidget) #Colors to match this site background.panel = "#EBEDE8" background.plot = background.panel lines.plot = "#28262C" fill.plot = "#4390C7" width = 1600 height = 760 #Theme to apply the colors to plots webtheme = theme( text = element_text(color=lines.plot), panel.background = element_rect(fill=background.plot, color=background.plot), panel.border = element_blank(), panel.grid.major = element_line(size= 0.5, linetype = 'solid', color = lines.plot), axis.line = element_line(color = lines.plot), plot.background = element_rect(fill = background.panel, color=background.panel)) plot1 = df %>% group_by(Style) %>% summarise(Count = n()) %>% mutate(Style = fct_reorder(Style, Count)) %>% ggplot(aes(x = Style, y = Count)) + geom_bar( stat = "identity", fill = fill.plot, width = .4 ) + coord_flip() + ggtitle("Number of Knives in Each Form Factor") + xlab("Form Factors") + theme_ipsum(axis_title_size = 20) + webtheme plot2 = df %>% group_by(SteelGroup) %>% summarise(Count = n()) %>% mutate(SteelGroup = fct_reorder(SteelGroup, Count)) %>% ggplot(aes(x = SteelGroup, y = Count)) + geom_bar( stat = "identity", fill = fill.plot, width = .4 ) + coord_flip() + xlab("Steel Variety") + ggtitle("Number of Knives in Each Steel Type") + theme_ipsum(axis_title_size = 20) + webtheme plot3 = df %>% group_by(Steel) %>% summarise(Count = n()) %>% mutate(Steel = fct_reorder(Steel, Count)) %>% ggplot(aes(x = Steel, y = Count)) + geom_bar( stat = "identity", fill = fill.plot, width = .4 ) + coord_flip() + ggtitle("Number of knives in Each Steel Group") + xlab("Steel Group") + theme_ipsum(axis_title_size = 20) + webtheme #Used for sorting certain groups med= df%>% group_by(SteelGroup) %>% summarise(med = median(Prices, na.rm = TRUE)) %>% right_join(df[,c("SteelGroup", "X")], by="SteelGroup")%>% select("X", "med") plot4 = df %>% group_by(SteelGroup) %>% summarise(Count = n()) %>% right_join(df,by="SteelGroup") %>% left_join(med, by="X") %>% mutate(SteelGroup = fct_reorder(SteelGroup, med)) %>% filter(Count>40) %>% ggplot(aes(x = SteelGroup, y = Prices, fill = SteelGroup)) + geom_boxplot(fill=fill.plot, outlier.shape = NA) + geom_jitter(color="black", size=.7, alpha=.9) + coord_flip() + theme_ipsum(axis_title_size = 20) + webtheme + theme(legend.position = "none") + ggtitle("Boxplot of Steel Variety by Price") + xlab("Steel Variety") plot5 = df %>% filter(Style=="Petty Knives") %>% group_by(SteelGroup) %>% summarise(Count = n()) %>% right_join(df,by="SteelGroup") %>% left_join(med, by="X") %>% mutate(SteelGroup = fct_reorder(SteelGroup, med)) %>% filter(Style=="Petty Knives") %>% filter(Count>7) %>% ggplot(aes(x = SteelGroup, y = Prices, fill = SteelGroup)) + geom_boxplot(fill=fill.plot, outlier.shape = NA) + geom_jitter(color="black", size=.7, alpha=.9) + coord_flip() + theme_ipsum(axis_title_size = 20) + webtheme + theme(legend.position = "none") + ggtitle("Petty Knife Boxplot of Steel Variety by Price") + xlab("Steel Variety") plotA = df %>% filter(SubStyle == "Gyutos 180 - 195mm") %>% group_by(SteelGroup) %>% summarise(Count = n()) %>% right_join(df, by = "SteelGroup") %>% left_join(med, by = "X") %>% mutate(SteelGroup = fct_reorder(SteelGroup, med)) %>% filter(SubStyle == "Gyutos 180 - 195mm") %>% filter(Count > 1) %>% ggplot(aes(x = SteelGroup, y = Prices, fill = SteelGroup)) + geom_boxplot(fill = fill.plot) + geom_jitter(color = "black", size = .4, alpha = .9) + coord_flip() + theme_ipsum(axis_title_size = 20) + webtheme + theme(legend.position = "none") + ggtitle("Gyutos 180 - 195mm") + xlab("SteelGroup") plotA plotB = df %>% filter(SubStyle=="Gyutos 210mm ") %>% group_by(SteelGroup) %>% summarise(Count = n()) %>% right_join(df,by="SteelGroup") %>% left_join(med, by="X") %>% mutate(SteelGroup = fct_reorder(SteelGroup, med)) %>% filter(SubStyle=="Gyutos 210mm ") %>% filter(Count>5) %>% ggplot(aes(x = SteelGroup, y = Prices, fill = SteelGroup)) + geom_boxplot(fill=fill.plot) + geom_jitter(color="black", size=.4, alpha=.9) + ggtitle("Gyutos 210mm ") + xlab("SteelGroup") + theme(legend.position = "none") + coord_flip() + theme_ipsum(axis_title_size = 20) + webtheme plotC = df %>% filter(SubStyle=="Gyutos 240mm") %>% group_by(SteelGroup) %>% summarise(Count = n()) %>% right_join(df,by="SteelGroup") %>% left_join(med, by="X") %>% mutate(SteelGroup = fct_reorder(SteelGroup, med)) %>% filter(SubStyle=="Gyutos 240mm") %>% filter(Count>4) %>% ggplot(aes(x = SteelGroup, y = Prices, fill = SteelGroup)) + geom_boxplot(fill=fill.plot) + geom_jitter(color="black", size=.4, alpha=.9) + ggtitle("Gyutos 240mm") + xlab("SteelGroup") + theme(legend.position = "none") + coord_flip() + theme_ipsum(axis_title_size = 20) + webtheme plotD = df %>% filter(SubStyle=="Gyutos 270-300mm ") %>% group_by(SteelGroup) %>% summarise(Count = n()) %>% right_join(df,by="SteelGroup") %>% left_join(med, by="X") %>% mutate(SteelGroup = fct_reorder(SteelGroup, med)) %>% filter(SubStyle=="Gyutos 270-300mm ") %>% filter(Count>1) %>% ggplot(aes(x = SteelGroup, y = Prices, fill = SteelGroup)) + geom_boxplot(fill=fill.plot) + geom_jitter(color="black", size=.4, alpha=.9) + ggtitle("Gyutos 270-300mm ") + xlab("SteelGroup") + theme(legend.position = "none") + coord_flip() + theme_ipsum(axis_title_size = 20) + webtheme plot6 = multiplot(plotA, plotB, plotC, plotD, cols=2) plot7 = df %>% filter(SubStyle=="Gyutos 240mm" | SubStyle== "Gyutos 210mm ") %>% group_by(SteelGroup) %>% summarise(Count = n()) %>% right_join(df,by="SteelGroup") %>% left_join(med, by="X") %>% mutate(SteelGroup = fct_reorder(SteelGroup, med)) %>% filter(SubStyle=="Gyutos 240mm" | SubStyle== "Gyutos 210mm ") %>% filter(Steel =="Carbon") %>% ggplot(aes(x = SteelGroup, y = Prices, fill = SteelGroup)) + geom_boxplot(fill=fill.plot, outlier.shape = NA) + geom_jitter(color=lines.plot, size=.4, alpha=.9) + ggtitle("Gyutos 210 - 240mm") + xlab("SteelGroup") + theme(legend.position = "none") + coord_flip() + theme_ipsum(axis_title_size = 20) + webtheme plotInteractive = function(SteelT = c("Stainless", "Carbon", "PowderedSteel", "HighCarbon") , Length = c("Gyutos 180 - 195mm", "Gyutos 210mm ", "Gyutos 240mm", "Gyutos 270-300mm "), CountT = 5) { dataset <- df %>% filter(Steel %in% SteelT & SubStyle %in% Length) %>% group_by(SteelGroup) %>% summarise(Count = n()) %>% right_join(df, by = "SteelGroup") %>% left_join(med, by = "X") %>% mutate(SteelGroup = fct_reorder(SteelGroup, med)) %>% filter(Steel %in% SteelT, SubStyle %in% Length) %>% filter(Count > CountT) ggplot(dataset, aes(x = SteelGroup, y = Prices)) + geom_boxplot(fill=fill.plot, outlier.shape = NA) + geom_jitter(color = "black", size = .4, alpha = .9, aes(text = paste("Knife = ", title))) + xlab("SteelGroup") + theme(legend.position = "none") + coord_flip() + theme_ipsum(axis_title_size = 20) + webtheme } #Function call to generate the interactive plot manipulateWidget(plotInteractive(SteelT, Length, CountT) %>% ggplotly(), SteelT = mwCheckboxGroup(c("Stainless", "Carbon", "PowderedSteel", "HighCarbon"), value="Carbon"), Length = mwCheckboxGroup(c("Gyutos 180 - 195mm", "Gyutos 210mm ", "Gyutos 240mm", "Gyutos 270-300mm "), value = "Gyutos 210mm "), CountT = mwSlider(1,15, 5, label = "Minimum Knives in Steel Group"))