<p><div><div><div><div data-width="100" data-show-faces="false" data-send="true" data-layout="button_count" data-height="21" data-href="https://www.r-bloggers.com/how-to-analyze-max-diff-data-in-r/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="https://www.displayr.com/analyze-max-diff-data-r/"> R – Displayr</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<p><img sizes="(max-width: 300px) 100vw, 300px" alt="max-diff-preferences" class="webfeedsFeaturedVisual wp-post-image" src="https://i0.wp.com/www.displayr.com/wp-content/uploads/2017/05/max-diff-donut2-300x185.png?resize=300%2C185&ssl=1" data-recalc-dims="1">
<p><img sizes="(max-width: 780px) 100vw, 780px" alt="max-diff-preferences" class="wp-image-1928" src="https://i1.wp.com/www.displayr.com/wp-content/uploads/2017/05/max-diff-donut2.png?w=450&ssl=1" data-recalc-dims="1"></p>
<p>This post discusses a number of options that are available in R for analyzing data from max-diff experiments, using the package <span>flipMaxDiff</span>. For a more detailed explanation of how to analyze max-diff, and what the outputs mean, you should read the post <a target="_blank" rel="nofollow" href="https://www.displayr.com/how-max-diff-analysis-works/">How max-diff analysis works</a>.</p>
<p>The post will cover the processes of installing packages, importing your data and experimental design, before discussing counting analysis and the more powerful, and valid, latent class analysis.</p>
<h1>Step 1: Installing the packages</h1>
<p>The first step is to install the <span>flipMaxDiff </span>package and a series of dependent packages. Depending on how your R has been setup, you may need to install none of these (e.g., if using Displayr), or even more packages than are shown below.</p>
<pre> 
install.packages(&quot;devtools&quot;)
library(devtools)
install.packages(&quot;AlgDesign&quot;) 
install_github(&quot;Displayr/flipData&quot;)
install_github(&quot;Displayr/flipTransformations&quot;)
install.packages(&quot;Rcpp&quot;)
install.packages(&quot;foreign&quot;)
install_github(&quot;Displayr/flipMaxDiff&quot;)
install_github(&quot;Displayr/flipStandardCharts&quot;)
</pre>
<h1>Step 2: Bring in your data</h1>
<p>The mechanism by which you import your survery data will depend upon its format and location. For the example that is used in our <a target="_blank" rel="nofollow" href="https://www.displayr.com/how-max-diff-analysis-works/">main post </a>on analysing max-diff, you can use the following to import the SPSS file:</p>
<pre>
tech.data = foreign::read.spss(&quot;http://wiki.q-researchsoftware.com/images/f/f1/Technology_2017.sav&quot;, to.data.frame = TRUE)
</pre>
<p> </p>
<h1>Step 3: Bring in the experimental design</h1>
<p>The <span>flipMaxDiff</span> package contains a method for creating your own experimental design, and this is discussed more <a target="_blank" rel="nofollow" href="https://www.displayr.com/create-max-diff-experimental-design-r/">here</a>. In many cases, you may simply need to load in the design from your PC, or from a URL. The example that we cover here uses the following:</p>
<pre>
tech.design = read.csv(&quot;http://wiki.q-researchsoftware.com/images/7/78/Technology_MaxDiff_Design.csv&quot;)
</pre>
<h1>Step 4: Counting analysis</h1>
<p>While the latent class analysis technique described below is more valid and powerful than analyses based on counting the selections made by respondents, the following code may be used to examine the results discussed in the post <a target="_blank" rel="nofollow" href="https://www.displayr.com/how-max-diff-analysis-works/">How max-diff analysis works</a>.</p>
<p>First, collect the sections of the data set for the selections made by the respondents:</p>
<pre>
best = tech.data[, c(&quot;Q5a_left&quot;, &quot;Q5b_left&quot;, &quot;Q5c_left&quot;, 
                     &quot;Q5d_left&quot;, &quot;Q5e_left&quot;, &quot;Q5f_left&quot;)]
worst = tech.data[, c(&quot;Q5a_right&quot;, &quot;Q5b_right&quot;, &quot;Q5c_right&quot;, 
                      &quot;Q5d_right&quot;, &quot;Q5e_right&quot;, &quot;Q5f_right&quot;)]
</pre>
<p>Here, the variable naming convention arises from the most-preferred option being shown on the left in the questionnaire,  and the least-preferred option being shown on the right.</p>
<p>This code will count up the number of times each alternative was selected as best:</p>
<pre>
b = unlist(best) # Turning the 6 variables into 1 variable
t = table(b) # Creating a table
s = sort(t, decreasing = TRUE) # Sorting from highest to lowest
# Putting a name at the top of the column, and naming it.
best.score = cbind(Best = s) 
</pre>
<p>This code will count up the number of selections for each of the alternatives in your max-diff experiment:</p>
<pre>
b = table(unlist(best))
best.and.worst = cbind(Best = b, 
                       Worst = table(unlist(worst)))[order(b, decreasing = TRUE),]
</pre>
<p>To compute the difference between the best and worst counts:</p>
<pre>
diff = best.and.worst[, 1] - best.and.worst[, 2]
cbind(&quot;Best - Worst&quot; = diff)
</pre>
<h1>Step 5: Latent class analysis</h1>
<p>The flipMaxDiff package contains a function for estimating the shares in the max-diff experiment that uses latent class analysis. For a more detailed explanation of what this means, and how to interpret the outputs, see <a target="_blank" rel="nofollow" href="https://www.displayr.com/how-max-diff-analysis-works/">this post</a>.</p>
<p>To run the latent class analysis, you can use the following:</p>
<pre>
library(flipMaxDiff)
# Name the alternatives in the design
alt.names &lt;- c(&quot;Apple&quot;, &quot;Microsoft&quot;, &quot;IBM&quot;, &quot;Google&quot;, &quot;Intel&quot;, 
               &quot;Samsung&quot;, &quot;Sony&quot;, &quot;Dell&quot;, &quot;Yahoo&quot;, &quot;Nokia&quot;)
result = FitMaxDiff(design = tech.design, 
                    version = rep(1, nrow(best)), 
                    best = best, 
                    worst = worst, 
                    alternative.names = alt.names, 
                    n.classes = 5, 
                    output = &quot;Classes&quot;)
print(result)
</pre>
<p>The arguments that have been used in this example are:</p>
<ul>
<li><span>design</span>: a data frame containing the experimental design.</li>
<li><span>version</span>: a vector of integers which can be used to specify which respondents were shown different versions of the experimental design. In this example, the design is simple and there is only a single version shown to all respondents.</li>
<li><span>best</span>: a data frame containing the options that were chosen as most-preferred.</li>
<li><span>worst</span>: a data frame containing the options that were chosen as most-preferred.</li>
<li><span>alternative.names</span>: a vector containing the names of the alternatives that were used in the max-diff experiment. In the code above, the names of the technology companies are used.</li>
<li><span>n.classes</span>: the number of classes to include in the analysis. Refer to <a target="_blank" rel="nofollow" href="https://www.displayr.com/how-max-diff-analysis-works/">this post</a> for how to work out how many classes to include.</li>
<li><span>output</span>: a string which denotes the type of output that should be displayed when the object is printed. In this case we have chosen “Classes”, and so the print will show information about the preference shares for each class identified. Change this to “Probabilities”, and the output will show the Mean Probability (%) and distribution of shares.</li>
</ul>
<p> </p>
<h1>Step 6: Obtaining respondent-level information</h1>
<p>The latent class output can now be used to obtain various bits of information about the respondents. These can then be fed into later analyses:</p>
<p>To generate a new vector which tells you which class each respondent has been assigned to, you may use:</p>
<pre>
flipMaxDiff::Memberships(result)
</pre>
<p>In the latent class model, each respondent has a certain probability of membership for each class. The Memberships() method used above assigns each respondent to the class with the highest probability. To see the probabilities</p>
<pre>
input.maxdiff = result
probs = input.maxdiff$posterior.probabilities
colnames(probs) = paste0('Class ', 1:ncol(probs) )
probs
</pre>
<p>Respondent-level preference shares:</p>
<pre>
respondent.shares = prop.table(exp(as.matrix( (flipMaxDiff::RespondentParameters(result) ) ) ), 1)
</pre>
<h1>Step 7: Obtaining information from the output table</h1>
<p>While the latent class analysis outputs are displayed in a cool HTMLWidget, the data in the class table can be also be extracted with <span>results$probabilities</span>. This lets you extract parts of the table for charting or for other analyses. For example, in our 5-class solution, we can plot the preference shares from the Total column as a donut chart (from the package <span>flipStandardCharts</span>):</p>
<pre>
library(flipStandardCharts)
pref.shares = result$probabilities[, 6]
pref.shares = sort(pref.shares, decreasing = TRUE) * 100
Chart(pref.shares, type = &quot;Donut&quot;)
</pre>
<p><iframe width="450" src="https://embedded.azureedge.net/75668/213195/a97ff8dc-6ddf-4610-892e-6a7ccf42f482.html?v=34784-1334061661"></iframe></p>
<h1>Step 8: Preference simulation</h1>
<p>Here, preference simulation refers to the process of removing some alternatives from the calculated shares, and then rebasing the remaining shares to see how they adjust in the absence of the removed alternatives. Here, we first modify <span>result$probabilities</span> by removing the Total column (which will be recomputed later), as well as the rows for the alternatives that we want to exclude. Then, the results are rebased to add to 100 using the <span>prop.table</span> function. A new Total column is computed by taking the weighted sum, where the weights are given by the class sizes contained in <span>result$class.sizes</span>.</p>
<pre>
# Remove the total column
x = result$probabilities[, -6] * 100
# Removing Apple and Samsung
x = x[c(-1, -6),]
# Re-basing
x = prop.table(x, 2)* 100
# Adding the total
sizes = result$class.sizes
x = cbind(x, Total = rowSums(sweep(x, 2, sizes, &quot;*&quot;)))
new.preferences = rbind(x, Total = colSums(x))
</pre>
<h1>Summary</h1>
<p>Once you have loaded in your survey data and experimental design, the latent class analysis from <span>flipMaxDiff</span> can be run with a couple of lines of code. Additional methods are then available for saving respondent-level information, and data from the output table, to feed them in to your charts and analyses.</p>
<p>
<div>
<div>To <strong>leave a comment</strong> for the author, please follow the link and comment on their blog: <strong><a href="https://www.displayr.com/analyze-max-diff-data-r/"> R – Displayr</a></strong>.</div>
<hr>
<a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers.com</a> offers <strong><a rel="nofollow" href="https://feedburner.google.com/fb/a/mailverify?uri=RBloggers">daily e-mail updates</a></strong> about <a title="The R Project for Statistical Computing" rel="nofollow" href="https://www.r-project.org/">R</a> news and <a title="R tutorials" rel="nofollow" href="https://www.r-bloggers.com/search/tutorial">tutorials</a> on topics such as: <a title="Data science" rel="nofollow" href="https://www.r-bloggers.com/search/data%20science">Data science</a>, <a title="Big Data" rel="nofollow" href="https://www.r-bloggers.com/search/Big%20Data">Big Data, <a title="R jobs" rel="nofollow" href="https://www.r-users.com/">R jobs</a>, visualization (<a title="ggplot and ggplot2 tutorials" rel="nofollow" href="https://www.r-bloggers.com/search/ggplot2">ggplot2</a>, <a title="Boxplots using lattice and ggplot2 tutorials" rel="nofollow" href="https://www.r-bloggers.com/search/boxplot">Boxplots</a>, <a title="Maps and gis" rel="nofollow" href="https://www.r-bloggers.com/search/map">maps</a>, <a title="Animation in R" rel="nofollow" href="https://www.r-bloggers.com/search/animation">animation</a>), programming (<a title="RStudio IDE for R" rel="nofollow" href="https://www.r-bloggers.com/search/RStudio">RStudio</a>, <a title="Sweave and literate programming" rel="nofollow" href="https://www.r-bloggers.com/search/sweave">Sweave</a>, <a title="LaTeX in R" rel="nofollow" href="https://www.r-bloggers.com/search/LaTeX">LaTeX</a>, <a title="SQL and databases" rel="nofollow" href="https://www.r-bloggers.com/search/SQL">SQL</a>, <a title="Eclipse IDE for R" rel="nofollow" href="https://www.r-bloggers.com/search/eclipse">Eclipse</a>, <a title="git and github, Version Control System" rel="nofollow" href="https://www.r-bloggers.com/search/git">git</a>, <a title="Large data in R using Hadoop" rel="nofollow" href="https://www.r-bloggers.com/search/hadoop">hadoop</a>, <a title="Web Scraping of google, facebook, yahoo, twitter and more using R" rel="nofollow" href="https://www.r-bloggers.com/search/Web+Scraping">Web Scraping</a>) statistics (<a title="Regressions and ANOVA analysis tutorials" rel="nofollow" href="https://www.r-bloggers.com/search/regression">regression</a>, <a title="principal component analysis tutorial" rel="nofollow" href="https://www.r-bloggers.com/search/PCA">PCA</a>, <a title="Time series" rel="nofollow" href="https://www.r-bloggers.com/search/time+series">time series</a>, <a title="finance trading" rel="nofollow" href="https://www.r-bloggers.com/search/trading">trading</a>) and more...
<img height="1" alt="" width="1" src="http://feeds.feedburner.com/~r/RBloggers/~4/PpGHYzyh2Gs"></a></div>