Conjoint Analysis: A Powerful Tool for Product Pricing
Conjoint analysis is a technique that extends regression analysis to understand customer preferences, pricing for your product and also roughly size the market for the product
When will you need conjoint analysis?
Consider this scenario. Samsung lists close to 15 phones for their Galaxy-M brand. Each phone is priced differently. How to decide which price-point should be used for which mobile phone?
Mobile phones differ in their specs by the kind of display, camera, battery charging, memory performance etc. If you are a product manager leading a product line of Galaxy-M phones, you must decide which features should be bundled together at which price point. Conjoint analysis is a valuable technique for these scenarios.
Before we start we will agree on the following terminology:
When you adopt the value based pricing, the price of a product will be determined based on how those features are valued by the customer. To know what features are valued we do a survey with a sample of customers. Conjoint analysis is entirely dependent on the survey data collected from the customer.
Customer survey and the different types of conjoint analysis
We can design customer surveys in many different ways. For example, customers can be asked to give a rating or given two options and asked which option they prefer. We have to adopt a type of analysis based on how we get the survey response data.
- Full-profile conjoint analysis: In this type, the survey respondent is shown a complete product description and asked to give a rating or rank
- Discrete choice-based conjoint analysis: In this type, the survey respondents are given the choice of products and asked which they will buy. Here the response is binary, i.e. 1 or 0.
- MaxDiff Conjoint analysis: In this type, the survey respondents are asked to give their preference regarding the features and rank the features by order of importance.
- Adaptive conjoint analysis: In this type, the survey questions are adaptively changed based on his previous answers
This tutorial will discuss full profile conjoint analysis and work on a dataset from a survey about car tyres.
Car tyres survey Dataset
This toy dataset assumes survey responses from customers for a combination of attributes for Car tyres. The attributes considered are:
- Brand: There are three possible attribute values, Sears, Goodyear, Goodrich
- Miles: There are three possible attribute values for miles, 30k, 40k, 50k
- Side: There are two possible attribute values, Black and white
In addition, the survey response has three possible price points 50$, 60$, 70$
The rest of the tutorial will explain how we use Python for conjoint analysis on this dataset. We will see how to
- Calculate part-worths from regression analysis
- Use part worths for selecting optimal feature bundle and price-point
- Simulate market share
Conjoint analysis with Python
The objective of the conjoint analysis is to find the combination of attributes or features that the customer most values and the price point for the optimal feature bundle. The first step is to calculate the part-worth utility for the attributes.
1. Calculate part-worths from regression analysis
The input data is read into a pandas dataframe
import numpy as np
import pandas as pd
cartyresDf = pd.read_csv("CarTyres_data.csv")
cartyresDf.head()
The dataset already is one-hot encoded with 1 or 0 for each of the attribute levels. We fit a regression model on these attributes
import statsmodels.api as sm
X = cartyresDf[["Sears",
"Goodyear",
"Goodrich",
"Price50",
"Price60",
"Price70",
"Miles30K",
"Miles40K",
"Miles50K",
"SideBlack",
"SideWhite"]]
Y = cartyresDf.Utility
linearRegression = sm.OLS(Y, X).fit()
linearRegression.summary()
Part worth utility for each of the attribute levels are just the regression coefficients obtained from regression model
coeff =linearRegression.params.to_dict()
attrarray = {
'brand' : ['Sears','Goodyear','Goodrich'],
'Price' : ['Price50','Price60','Price70'],
'Miles' : ['Miles30K','Miles40K','Miles50K'],
'Side' : ['SideBlack','SideWhite']
}
part_worth_utility ={}
for attribute in attrarray.keys():
print('\nAttribute:', attribute)
temp_list = attrarray[attribute]
for k in temp_list:
part_worth_utility[k] = coeff[k]
print(' ',k, format(part_worth_utility[k], '.2f'))
From the regression coefficients or the part-worth utilities , for every attribute we calculate the range for this part-worth-utility values. This range is called as importance of an attribute.
we also calculate relative importance
partworth_range = {}
for attribute in attrarray.keys():
temp_list = attrarray[attribute]
tempRange = []
for k in temp_list:
if k in coeff.keys():
tempRange.append(coeff[k])
partworth_range[attribute] = tempRange
print ("--"*10)
print("\nPartworth range",partworth_range )
importance = {}
relative_importance = {}
for key, v in partworth_range.items():
importance[key] = ( max(v) - min(v))
total_of_imp_values = sum(importance.values())
for key,val in importance.items():
relative_importance[key] = (100* round(val/total_of_imp_values,3))
print ("--"*10)
print ("Importance of Feature:\n brand:",format(importance['brand'],'.2f'),\
"\nPrice:", format(importance['Price'], '.2f'), "\nMiles:", format(importance['Miles'],'.2f'), \
"\nSide:", format(importance['Side'],'.2f'))
print ("--"*10)
print ("\nRelative Importance of Feature:\n brand:",format(relative_importance['brand'], '.2f'), "%",\
"\nPrice:",format(relative_importance['Price'], '.2f') , "%", \
"\nMiles:", format(relative_importance['Miles'], '.2f'), "%",\
"\nSide:", format(relative_importance['Side'], '.2f') , "%\n")
print ("--"*10)
The above calculated values are put-together as a table for subsequent analysis
2. Selecting optimal feature bundle and price-point
From the table we got for part-worthy utility results, it is possible to arrive at the optimal feature bundle and optimal price point
- From the part-worth utility values, we can say <Goodyear, Miles50K, Sidewhite> is the optimal feature bundle
- From the part-worth range, we can say that 1.22 is the importance for (maximum of price 70$ — minimum of price 50$)
- 1.22 to be the importance value associated with 20$
- 20$/1.22 =16.39 is the dollar cost of one unit of utility
3. Total predicted utility from the regression model for the feature combination <Goodyear, Miles50K, Sidewhite> is 7.71
optBundle = [0,1,0,0,0,0,0,0,1,0,1]
print ("The optimal feature bundle would have the highest utility:",\
linearRegression.predict(optBundle)[0])
The best possible Combination would have the highest utility: 7.71
hence the optimal price point is 7.71*16.3 = 125$
3. Market share simulation
To calculate the market share for a feature-bundle, we need to calculate the preference share or the probability that the customer will choose that particular feature-bundle. There are many ways to calculate this preference share. The reference[2] gives three methods of arriving at the preference share. One is the logit-choice rule which assumes the computed utilities follow a random process. According to this rule, the proportion of times that feature-bundle “j” will be chosen is given by:
cpcarTyresDf = cartyresDf.copy()
ignorepricecols = ["Price50","Price60","Price70"]
for col in ignorepricecols:
cpcarTyresDf[col] = 0
cpcarTyresDf = cpcarTyresDf.drop(["Utility"],axis=1)
X = cpcarTyresDf[["Sears",
"Goodyear",
"Goodrich",
"Price50",
"Price60",
"Price70",
"Miles30K",
"Miles40K",
"Miles50K",
"SideBlack",
"SideWhite"]]
predictUtil = linearRegression.predict(X)
cpcarTyresDf["predictedUtility"] = predictUtil
utility_values = list(cpcarTyresDf["predictedUtility"].values)
total_utility=0
for val in utility_values:
total_utility = total_utility + np.exp(val)
market_shares =[]
for val in utility_values:
probability = np.exp(val)/total_utility
market_shares.append(probability*100)
cpcarTyresDf["market_share"] = market_shares
cpcarTyresDf[["Sears",
"Goodyear",
"Goodrich",
"Miles30K",
"Miles40K",
"Miles50K",
"SideBlack",
"SideWhite",
"predictedUtility",
"market_share"]].drop_duplicates()
which shows that the optimal bundle that we identified will occupy 28% of the market share.
Summary
We see how conjoint analysis helps break the overall value perceived by the customer into individual part-worth utility values. From these part-worth utility values, we can prioritise or combine features to arrive at optimal product and price. We saw how to do the analysis, but it is crucial to carefully design the survey and collect the data reliably, as the conclusions drawn from conjoint analysis depend on the survey data.
Commercial conjoint simulators can do the analysis we did and also support other types of conjoint analysis. Some of them are Qualtrics, Sawtooth, Conjoint.ly, and displayR. Please also check out the spreadsheet available for conjoint analysis.
In conclusion, Conjoint analysis is a valuable tool for a data analytics product manager and can help understand customer preferences, willingness to pay and how much market share a product can have.
If you are looking for the complete code, please checkout the github link
References:
- https://www.youtube.com/watch?v=1hWvsL-gOFo
- “Conjoint Analysis: Marketing Engineering Technical Note” supplement to Chapter 6 of Principles of Marketing Engineering, by Gary L. Lilien, Arvind Rangaswamy, and Arnaud De Bruyn (2007).
- https://medium.com/@sonia_samipillai/understand-customer-preferences-using-conjoint-analysis-in-python-65b8b7254454
- https://www.youtube.com/watch?v=Ey0hzAsHjio
- https://github.com/JanisIranee/Traditional-Conjoint-Analysis-with-Python/blob/master/Traditional%20Conjoint%20Analyse.ipynb