<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/gotta-catch-them-all/"></div></div><div><a data-url="https://www.r-bloggers.com/gotta-catch-them-all/" data-counturl="https://www.r-bloggers.com/gotta-catch-them-all/" data-count="horizontal" data-text="Gotta catch them all" class="twitter-share-button" data-via="rbloggers" href="https://twitter.com/share"></a></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="http://eighty20.github.io//technique%20review/2016/08/21/Pokemon-clustering/"> Pareto's Playground</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<h1>Introduction</h1>
<p>When data becomes high-dimensional, the inherent relational structure between the variables can sometimes become unclear or indistinct. One, might want to find clusters for numerous amounts of reasons – me, I want to use it to better understand my childhood. To be more specific, I will be using clustering to highlight different groupings of pokemon. The results of this analysis can then retrospectively be applied to a younger me having to choose which pokemon I catch and keep, or perhaps which I must rather use in battle to gain experience points. The clusters should help me identify groupings of pokemons that assimilate with my style of play, be it catching pokemon who are <em>specialist</em> of their type, <em>strong attackers</em>, <em>survivalist</em> who have good defensive capabilities or pokemon who have the potential to become great as soon as they evolve.</p>
<p>This train of thought (aka hypothesis) will carry through to the analysis when number of cluster and inference needs to be conducted.</p>
<h1>About clustering techniques</h1>
<p>Within the CRM field, a common practice is to segment client data in order to identify certain clusters of customers, users or products. The first question that I asked myself when I first encountered this technique was: “How usefull can this really be when there is no quantitative measure which dictates the number of clusters”. The answer to this question became quite clear to me when I encountered a dataset of 8000 variables.</p>
<p>Clustering lies within the field of data-reduction, and has the intention to uncover cohesive subgroups of observations within a very large dataset where inference aren’t always clear from face value – i.e an Excel pivot table isn’t going to cut it. Clustering is not only used within marketing, but is applied in biology, behavioural sciences, economics and medical research. The application of cluster analysis in the medical sciences interest me, as they use this technique to help catalog gene-expression patters which were obtained from DNA microarray data. Very cool application of this statistical technique. Without clustering, this task would become almost impossible due to the large amount of information.</p>
<p>Clustering can primarily be divided up in two techniques:</p>
<ul>
<li>Hierarchical Agglomerative methods</li>
<li>Partitioning clustering</li>
</ul>
<p>Hierarchical agglomerative clustering works from a bottom up approach where at the beginning, each observation is in its own cluster. From this clusters are combined into larger clusters, 2 at a time, until all the cluster have essentially been merged into one big cluster. With partitioning, one will specify <strong>K</strong> cluster which are sought after. Then the algorithm will essentially start by picking randomly dividing observations into clusters, assessing similarity, reshuffle, asses again and keep doing this until cohesive clusters are formed.</p>
<p>There is a lot of different techniques, but for the rest of this exploration into the topic, I will be using hierarchical agglomerative clustering (hclust) as my choice of clustering algorithm.</p>
<p>Now, the question is: “How are the observations linked to form these clusters?”. In hclust the most popular techniques are:</p>
<ul>
<li>Single linkage: Shortest distance between a point in one cluster and a point in the other cluster.</li>
<li>Complete linkage: Longest distance between a point in one cluster and a point in the other cluster.</li>
<li>Average linkage: Average distance between each point in one cluster and each point in the other<br>
cluster (also called UPGMA [unweighted pair group mean averaging])</li>
<li>Centroid: Distance between the centroids (vector of variable means) of the two clusters.<br>
For a single observation, the centroid is the variable’s values.</li>
<li>Ward’s Method: The ANOVA sum of squares between the two clusters added up over all the<br>
variables.</li>
</ul>
<p>You are probably asking – what distance are you talking about here? We will use the <code>dist()</code> function in R to calculate the euclidean distance:</p>
<p><img alt="Euclidean dit" src="https://i2.wp.com/eighty20.github.io/_rmd/Pokemon_fig/euclidean.JPG?w=456" data-recalc-dims="1"></p>
<p>where <strong>q</strong> and <strong>p</strong> are the observations and <strong>N</strong> is the number of variables. Easy enough right? I will be using <em>ward</em>’s method to cluster my objects as it is the default setting for <em>Hierarchical agglomerative clustering</em> for the <code>HCPC</code> function in <code>library(FactoMineR)</code></p>
<h1>Lets go catch our pokemon</h1>
<p>To collect the data on all the first generation pokemon, I employ Hadley Wickam’s <a target="_blank" href="https://cran.r-project.org/web/packages/rvest/index.html">rvest</a> package. I find it very intuitive and can handle all of my needs in collecting and extracting the data from a pokemon <a target="_blank" href="http://bulbapedia.bulbagarden.net/wiki/Main_Page">wiki</a>. I will grab all the Pokemon up until to Gen II, which constitutes 251 individuals. I did find the website structure a bit of a pain as each pokemon had very different looking web pages. But, with some manual hacking, I eventually got the data in a nice format.</p>
<p>The cleaned data looks as follows:</p>
<figure>
<pre><code data-lang="r"><span>library</span><span>(</span><span>ggplot2</span><span>)</span><span>
</span><span>library</span><span>(</span><span>FactoMineR</span><span>)</span><span>
</span><span>all_pokemon</span><span> </span><span>&lt;-</span><span> </span><span>download.file</span><span>(</span><span>&quot;https://raw.githubusercontent.com/Eighty20/eighty20.github.io/master/_rmd/Post_data/All_pokemon.csv&quot;</span><span>,</span><span> </span><span>destfile</span><span> </span><span>=</span><span> </span><span>&quot;/tmp/Pokemon.csv&quot;</span><span>,</span><span> </span><span>method</span><span> </span><span>=</span><span> </span><span>&quot;curl&quot;</span><span>)</span><span>
</span><span>all_pokemon</span><span> </span><span>&lt;-</span><span> </span><span>read.csv</span><span>(</span><span>&quot;/tmp/Pokemon.csv&quot;</span><span>,</span><span> </span><span>stringsAsFactors</span><span> </span><span>=</span><span> </span><span>F</span><span>)</span><span>
</span><span>cat</span><span>(</span><span>&quot;Dimensions for pokemon data is :&quot;</span><span>,</span><span>dim</span><span>(</span><span>all_pokemon</span><span>))</span></code></pre>
</figure>
<figure>
<pre><code data-lang="text">## Dimensions for pokemon data is : 251 15</code></pre>
</figure>
<figure>
<pre><code data-lang="r"><span>head</span><span>(</span><span>all_pokemon</span><span>)</span></code></pre>
</figure>
<figure>
<pre><code data-lang="text">##   Nat    Pokemon HP Atk Def  SA  SD Spd Total Type.I Type.II    Gender
## 1   1  Bulbasaur 45  49  49  65  65  45   318  Grass  Poison M (87.5%)
## 2   2    Ivysaur 60  62  63  80  80  60   405  Grass  Poison M (87.5%)
## 3   3   Venusaur 80  82  83 100 100  80   525  Grass  Poison M (87.5%)
## 4   4 Charmander 39  52  43  60  50  65   309   Fire         M (87.5%)
## 5   5 Charmeleon 58  64  58  80  65  80   405   Fire         M (87.5%)
## 6   6  Charizard 78  84  78 109  85 100   534   Fire  Flying M (87.5%)
##   Evolves.From lvl_up Evolves.Into
## 1           -- Lv. 16      Ivysaur
## 2    Bulbasaur Lv. 32     Venusaur
## 3      Ivysaur     --           --
## 4           -- Lv. 16   Charmeleon
## 5   Charmander Lv. 36    Charizard
## 6   Charmeleon     --           --</code></pre>
</figure>
<p>For those of you who know pokemon well, will also know that certain pokemon have only one evolution stage. We remove them in order to not intervere with our clustering at a later stage.</p>
<figure>
<pre><code data-lang="r"><span>Evo_none</span><span> </span><span>&lt;-</span><span> </span><span>all_pokemon</span><span>[</span><span>which</span><span>(</span><span>all_pokemon</span><span>$</span><span>Evolves.From</span><span> </span><span>==</span><span> </span><span>&quot;--&quot;</span><span> </span><span>&amp;</span><span> </span><span>all_pokemon</span><span>$</span><span>Evolves.Into</span><span>==</span><span>&quot;--&quot;</span><span>),</span><span> </span><span>]</span></code></pre>
</figure>
<p>The following pokemon were removed from the dataset: Farfetch’d, Kangaskhan, Pinsir, Tauros, Lapras, Ditto, Aerodactyl, Articuno, Zapdos, Moltres, Mewtwo, Mew, Unown, Girafarig, Dunsparce, Qwilfish, Shuckle, Heracross, Corsola, Delibird, Skarmory, Stantler, Smeargle, Miltank, Raikou, Entei, Suicune, Lugia, Ho-oh, Celebi</p>
<p>The next step was to aggregate all the stage 2 statistics for the stage 1 evolution pokemon. This results in a nice wide dataset of variables we are able to use in our clustering. I am hoping to extract some sense of strenghts in pokemon, not only by their stage 1 statistics, but also perhaps their potential to become awesome assets later. One hopeful example of this would be everyone’s favourite: magikarp.</p>
<figure>
<pre><code data-lang="r"><span>Evo_1</span><span> </span><span>&lt;-</span><span> </span><span>all_pokemon</span><span>[</span><span>which</span><span>(</span><span>all_pokemon</span><span>$</span><span>Evolves.From</span><span>==</span><span>&quot;--&quot;</span><span> </span><span>&amp;</span><span> </span><span>all_pokemon</span><span>$</span><span>Evolves.Into</span><span>!=</span><span>&quot;--&quot;</span><span>),</span><span> </span><span>]</span><span>
</span><span>Evo_2</span><span> </span><span>&lt;-</span><span> </span><span>all_pokemon</span><span>[</span><span>which</span><span>(</span><span>all_pokemon</span><span>$</span><span>Evolves.From</span><span>!=</span><span>&quot;--&quot;</span><span>),</span><span> </span><span>]</span><span>
</span><span>##### Housekeeping - organise data into cluster format #####
</span><span>Matched_pokemon</span><span> </span><span>&lt;-</span><span> </span><span>merge</span><span>(</span><span>Evo_1</span><span>,</span><span>
</span><span>Evo_2</span><span>[,</span><span>!</span><span>names</span><span>(</span><span>Evo_2</span><span>)</span><span> </span><span>%in%</span><span> </span><span>c</span><span>(</span><span>'Evolves.Into'</span><span>)],</span><span> </span><span>by.x</span><span> </span><span>=</span><span> </span><span>&quot;Evolves.Into&quot;</span><span>,</span><span>
</span><span>by.y</span><span> </span><span>=</span><span> </span><span>&quot;Pokemon&quot;</span><span>,</span><span>
</span><span>all.x</span><span> </span><span>=</span><span> </span><span>T</span><span>,</span><span>
</span><span>suffixes</span><span> </span><span>=</span><span> </span><span>c</span><span>(</span><span>&quot;.lv1&quot;</span><span>,</span><span>&quot;.lv2&quot;</span><span>))</span><span>
</span><span>#Create level of evolution variable </span><span>Matched_pokemon</span><span>$</span><span>lvl_up.lv1</span><span> </span><span>&lt;-</span><span> </span><span>as.integer</span><span>(</span><span>gsub</span><span>(</span><span>&quot;[^0-9]+&quot;</span><span>,</span><span>&quot;&quot;</span><span>,</span><span> </span><span>Matched_pokemon</span><span>$</span><span>lvl_up.lv1</span><span>))</span><span>
</span><span>#Finalize complete set of pokemon
</span><span>Matched_pokemon</span><span> </span><span>&lt;-</span><span> </span><span>Matched_pokemon</span><span>[</span><span>complete.cases</span><span>(</span><span>Matched_pokemon</span><span>),</span><span> </span><span>]</span><span>
</span><span>pokemon</span><span> </span><span>&lt;-</span><span> </span><span>Matched_pokemon</span><span>$</span><span>Pokemon</span><span>
</span><span>#Correct for Nidoran
</span><span>pokemon</span><span>[</span><span>grep</span><span>(</span><span>&quot;Nido&quot;</span><span>,</span><span>pokemon</span><span>)]</span><span> </span><span>&lt;-</span><span> </span><span>c</span><span>(</span><span>&quot;Nidoran(F)&quot;</span><span>,</span><span>&quot;Nidoran(M)&quot;</span><span>)</span><span>
</span><span>selected_var</span><span>&lt;-</span><span>c</span><span>(</span><span>&quot;HP.lv1&quot;</span><span>,</span><span>&quot;HP.lv2&quot;</span><span>,</span><span>
</span><span>&quot;Atk.lv1&quot;</span><span>,</span><span>&quot;Atk.lv2&quot;</span><span>,</span><span>
</span><span>&quot;Def.lv1&quot;</span><span>,</span><span>&quot;Def.lv2&quot;</span><span>,</span><span>
</span><span>&quot;SA.lv1&quot;</span><span>,</span><span>&quot;SA.lv2&quot;</span><span>,</span><span>
</span><span>&quot;SD.lv1&quot;</span><span>,</span><span>&quot;SD.lv2&quot;</span><span>,</span><span>
</span><span>&quot;Spd.lv1&quot;</span><span>,</span><span>&quot;Spd.lv2&quot;</span><span>,</span><span>
</span><span>&quot;Total.lv1&quot;</span><span>,</span><span>&quot;Total.lv2&quot;</span><span>,</span><span>
</span><span>&quot;Type.I.lv1&quot;</span><span>,</span><span>&quot;lvl_up.lv1&quot;</span><span>)</span><span>
</span><span>Matched_pokemon</span><span> </span><span>&lt;-</span><span> </span><span>Matched_pokemon</span><span>[</span><span> </span><span>,</span><span>names</span><span>(</span><span>Matched_pokemon</span><span>)</span><span>%in%</span><span>selected_var</span><span>]</span><span>
</span><span>row.names</span><span>(</span><span>Matched_pokemon</span><span>)</span><span> </span><span>&lt;-</span><span> </span><span>pokemon</span></code></pre>
</figure>
<p>The data has been constructed to capture characteristics of a specific pokemon at both the first and second level of evolution. It is these variables that we will be using in our clustering. The <code>total</code> column acts as a general indicator of pokemon’s attributes:</p>
<table>
<thead>
<tr>
<th> </th>
<th>HP.lv1</th>
<th>Atk.lv1</th>
<th>Def.lv1</th>
<th>SA.lv1</th>
<th>SD.lv1</th>
<th>Spd.lv1</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Ekans</strong></td>
<td>30</td>
<td>60</td>
<td>44</td>
<td>40</td>
<td>54</td>
<td>55</td>
</tr>
<tr>
<td><strong>Spinarak</strong></td>
<td>40</td>
<td>60</td>
<td>40</td>
<td>40</td>
<td>40</td>
<td>30</td>
</tr>
<tr>
<td><strong>Chikorita</strong></td>
<td>45</td>
<td>49</td>
<td>65</td>
<td>49</td>
<td>65</td>
<td>45</td>
</tr>
<tr>
<td><strong>Charmander</strong></td>
<td>39</td>
<td>52</td>
<td>43</td>
<td>60</td>
<td>50</td>
<td>65</td>
</tr>
<tr>
<td><strong>Totodile</strong></td>
<td>50</td>
<td>65</td>
<td>64</td>
<td>44</td>
<td>48</td>
<td>43</td>
</tr>
<tr>
<td><strong>Seel</strong></td>
<td>65</td>
<td>45</td>
<td>55</td>
<td>45</td>
<td>70</td>
<td>45</td>
</tr>
</tbody>
</table>
<p>Table: Table continues below</p>
<table>
<thead>
<tr>
<th> </th>
<th>Total.lv1</th>
<th>Type.I.lv1</th>
<th>lvl_up.lv1</th>
<th>HP.lv2</th>
<th>Atk.lv2</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Ekans</strong></td>
<td>283</td>
<td>Poison</td>
<td>22</td>
<td>60</td>
<td>85</td>
</tr>
<tr>
<td><strong>Spinarak</strong></td>
<td>250</td>
<td>Bug</td>
<td>22</td>
<td>70</td>
<td>90</td>
</tr>
<tr>
<td><strong>Chikorita</strong></td>
<td>318</td>
<td>Grass</td>
<td>16</td>
<td>60</td>
<td>62</td>
</tr>
<tr>
<td><strong>Charmander</strong></td>
<td>309</td>
<td>Fire</td>
<td>16</td>
<td>58</td>
<td>64</td>
</tr>
<tr>
<td><strong>Totodile</strong></td>
<td>314</td>
<td>Water</td>
<td>18</td>
<td>65</td>
<td>80</td>
</tr>
<tr>
<td><strong>Seel</strong></td>
<td>325</td>
<td>Water</td>
<td>34</td>
<td>90</td>
<td>70</td>
</tr>
</tbody>
</table>
<p>Table: Table continues below</p>
<table>
<thead>
<tr>
<th> </th>
<th>Def.lv2</th>
<th>SA.lv2</th>
<th>SD.lv2</th>
<th>Spd.lv2</th>
<th>Total.lv2</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Ekans</strong></td>
<td>69</td>
<td>65</td>
<td>79</td>
<td>80</td>
<td>438</td>
</tr>
<tr>
<td><strong>Spinarak</strong></td>
<td>70</td>
<td>60</td>
<td>60</td>
<td>40</td>
<td>390</td>
</tr>
<tr>
<td><strong>Chikorita</strong></td>
<td>80</td>
<td>63</td>
<td>80</td>
<td>69</td>
<td>414</td>
</tr>
<tr>
<td><strong>Charmander</strong></td>
<td>58</td>
<td>80</td>
<td>65</td>
<td>80</td>
<td>405</td>
</tr>
<tr>
<td><strong>Totodile</strong></td>
<td>80</td>
<td>59</td>
<td>63</td>
<td>58</td>
<td>405</td>
</tr>
<tr>
<td><strong>Seel</strong></td>
<td>80</td>
<td>70</td>
<td>95</td>
<td>70</td>
<td>475</td>
</tr>
</tbody>
</table>
<p>For those curious to see the pokemon which ended up in our dataset. Here they are:</p>
<figure>
<pre><code data-lang="text">##  [1] &quot;Ekans&quot;      &quot;Spinarak&quot;   &quot;Chikorita&quot;  &quot;Charmander&quot; &quot;Totodile&quot;  
##  [6] &quot;Seel&quot;       &quot;Doduo&quot;      &quot;Phanpy&quot;     &quot;Dratini&quot;    &quot;Diglett&quot;   
## [11] &quot;Voltorb&quot;    &quot;Spearow&quot;    &quot;Pineco&quot;     &quot;Sentret&quot;    &quot;Oddish&quot;    
## [16] &quot;Zubat&quot;      &quot;Psyduck&quot;    &quot;Snubbull&quot;   &quot;Magikarp&quot;   &quot;Gastly&quot;    
## [21] &quot;Houndour&quot;   &quot;Drowzee&quot;    &quot;Bulbasaur&quot;  &quot;Smoochum&quot;   &quot;Kabuto&quot;    
## [26] &quot;Abra&quot;       &quot;Weedle&quot;     &quot;Krabby&quot;     &quot;Chinchou&quot;   &quot;Ledyba&quot;    
## [31] &quot;Machop&quot;     &quot;Slugma&quot;     &quot;Magnemite&quot;  &quot;Cubone&quot;     &quot;Caterpie&quot;  
## [36] &quot;Grimer&quot;     &quot;Nidoran(F)&quot; &quot;Nidoran(M)&quot; &quot;Hoothoot&quot;   &quot;Remoraid&quot;  
## [41] &quot;Omanyte&quot;    &quot;Paras&quot;      &quot;Meowth&quot;     &quot;Pidgey&quot;     &quot;Swinub&quot;    
## [46] &quot;Poliwag&quot;    &quot;Mankey&quot;     &quot;Larvitar&quot;   &quot;Wooper&quot;     &quot;Cyndaquil&quot; 
## [51] &quot;Ponyta&quot;     &quot;Rhyhorn&quot;    &quot;Sandshrew&quot;  &quot;Horsea&quot;     &quot;Goldeen&quot;   
## [56] &quot;Hoppip&quot;     &quot;Slowpoke&quot;   &quot;Tentacool&quot;  &quot;Teddiursa&quot;  &quot;Squirtle&quot;  
## [61] &quot;Bellsprout&quot; &quot;Koffing&quot;    &quot;Natu&quot;</code></pre>
</figure>
<p>One of the interesting variables that forms part of the data is the crucial question every trainer asks himself when catching pokemon – which types are the strongest? For each of my ~60 pokemon I use a boxplot to evaluate the relative strenght of a type. The data was normalized per level of evolution to ease plotting and interpretation.<br>
<img title="center" alt="center" src="https://i2.wp.com/eighty20.github.io/figures/Pokemon_clustering/unnamed-chunk-7-1.png?w=456" data-recalc-dims="1"><br>
Good old bug pokemons don’t catch a break, with the median <code>total</code> points being the lowest in both stages of evolution. For Normal, Poison and Water types, there seems to be a definite advantage to evolve in order to ‘up’ the overall statistics. An interesting type to evaluate is the Fire type pokemon. In the first stage of evolution this type of pokemon seems to have an overall advantage, but once the pokemon starts evolving, the advantage dissipates.</p>
<p>One of the concerns I had was the class imbalance that might be present in the pokemon type.<br>
<img title="center" alt="center" src="https://i1.wp.com/eighty20.github.io/figures/Pokemon_clustering/unnamed-chunk-8-1.png?w=456" data-recalc-dims="1"><br>
The graph clearly points this out, so instead of adding the pokemon types into the analysis, they will be included as supplementary variable.</p>
<h1>Going Prof Elm and analysing pokemon</h1>
<p>If you don’t know who Prof Elm is, this <a target="_blank" href="http://bulbapedia.bulbagarden.net/wiki/Professor_Elm">link</a> should help. To start our exploration into the pokemon dataset, we will conduct a <em>multiple factor analysis</em>. I find the flexibility of this function being able to conduct <code>MCA</code> and <code>PCA</code> in one go very helpful. It also has incredible plotting functions that helps to visually analyse your data.</p>
<figure>
<pre><code data-lang="r"><span>Matched_pokemon</span><span>$</span><span>Type.I.lv1</span><span> </span><span>&lt;-</span><span> </span><span>as.factor</span><span>(</span><span>Matched_pokemon</span><span>$</span><span>Type.I.lv1</span><span>)</span><span>
</span><span>res</span><span> </span><span>&lt;-</span><span> </span><span>MFA</span><span>(</span><span>Matched_pokemon</span><span>,</span><span>group</span><span> </span><span>=</span><span> </span><span>c</span><span>(</span><span>6</span><span>,</span><span>1</span><span>,</span><span>1</span><span>,</span><span>7</span><span>,</span><span>1</span><span>),</span><span>type</span><span>=</span><span>c</span><span>(</span><span>rep</span><span>(</span><span>&quot;s&quot;</span><span>,</span><span>2</span><span>),</span><span>&quot;n&quot;</span><span>,</span><span>rep</span><span>(</span><span>&quot;s&quot;</span><span>,</span><span>2</span><span>)),</span><span>
</span><span>ncp</span><span>=</span><span>5</span><span>,</span><span>name.group</span><span> </span><span>=</span><span> </span><span>c</span><span>(</span><span>&quot;Lvl1&quot;</span><span>,</span><span>&quot;ToT1&quot;</span><span>,</span><span>&quot;Type&quot;</span><span>,</span><span>&quot;Lvl2&quot;</span><span>,</span><span>&quot;ToT2&quot;</span><span>),</span><span>
</span><span>num.group.sup</span><span> </span><span>=</span><span> </span><span>c</span><span>(</span><span>2</span><span>,</span><span>3</span><span>,</span><span>5</span><span>),</span><span>graph</span><span> </span><span>=</span><span> </span><span>F</span><span>)</span><span>
</span><span>plot</span><span>(</span><span>res</span><span>,</span><span>choix</span><span> </span><span>=</span><span> </span><span>&quot;var&quot;</span><span>,</span><span> </span><span>habillage</span><span> </span><span>=</span><span> </span><span>&quot;group&quot;</span><span>,</span><span> </span><span>cex</span><span>=</span><span>0.8</span><span>,</span><span> </span><span>shadow</span><span> </span><span>=</span><span> </span><span>T</span><span>)</span></code></pre>
</figure>
<p><img title="center" alt="center" src="https://i2.wp.com/eighty20.github.io/figures/Pokemon_clustering/unnamed-chunk-9-1.png?w=456" data-recalc-dims="1"><br>
Here we see that there is a definite inverse relationship between the speed of a Pokemon and its attack statistics. I find the relationship between special attack and normal attack interesting. It would seem that you either specialise or defualt to having a strong overall attack.</p>
<p>The first thing to look at is the dispersion of the pokemon types to see how correlation all the pokemons are given their type.<br>
<img title="center" alt="center" src="https://i1.wp.com/eighty20.github.io/figures/Pokemon_clustering/unnamed-chunk-10-1.png?w=456" data-recalc-dims="1"><br>
It would seem that Ghost, Psyhic and Electric pokemon have different characteristics than those of Ground, Fighting and Bug for instance.</p>
<p>Given these factor groups, next it would be interesting to see which of the pokemon had the highest contribution to the construction dimension (Contribution 10). I also want to see the highest quality of representation (cos2>0.6). The <em>cos squared</em>, indicates the contribution of a component to the squared distance of the observation to the origin. i.e <em>cos squared</em> is an important contributor to find the components that are important to interpret both active and supplementary observations, <a target="_blank" href="https://www.utdallas.edu/~herve/abdi-awPCA2010.pdf">Abdi H, 2010</a>.<br>
<img title="center" alt="center" src="https://i1.wp.com/eighty20.github.io/figures/Pokemon_clustering/unnamed-chunk-11-1.png?w=456" data-recalc-dims="1"></p>
<p>Now that we have a clearer understanding of the data, its finally time to conduct the exciting cluster analysis on the data. With the <code>MFA</code> function, this is easily done by plugging the results directly into a hierarchical clustering algorithm. I decided to cut the tree to get 4 clusters in the end. Felt that these represented the different facets of pokemon quite well.</p>
<figure>
<pre><code data-lang="r"><span>res.hcpc</span><span> </span><span>&lt;-</span><span> </span><span>HCPC</span><span>(</span><span>res</span><span>,</span><span> </span><span>nb.clust</span><span>=</span><span>4</span><span>,</span><span> </span><span>consol</span><span>=</span><span>TRUE</span><span>,</span><span> </span><span>iter.max</span><span>=</span><span>10</span><span>,</span><span> </span><span>min</span><span>=</span><span>3</span><span>,</span><span>
</span><span>max</span><span>=</span><span>NULL</span><span>,</span><span> </span><span>metric</span><span>=</span><span>&quot;euclidean&quot;</span><span>,</span><span> </span><span>method</span><span>=</span><span>&quot;ward&quot;</span><span>,</span><span> </span><span>order</span><span>=</span><span>TRUE</span><span>,</span><span>
</span><span>graph.scale</span><span>=</span><span>&quot;inertia&quot;</span><span>,</span><span> </span><span>nb.par</span><span>=</span><span>5</span><span>,</span><span> </span><span>graph</span><span>=</span><span>F</span><span>,</span><span> </span><span>proba</span><span>=</span><span>0.05</span><span>,</span><span> </span><span>cluster.CA</span><span>=</span><span>&quot;rows&quot;</span><span>,</span><span>kk</span><span>=</span><span>Inf</span><span>)</span></code></pre>
</figure>
<p>Here we can see a 3D representation of the tree that was build:<br>
<img title="center" alt="center" src="https://i0.wp.com/eighty20.github.io/figures/Pokemon_clustering/unnamed-chunk-13-1.png?w=456" data-recalc-dims="1"></p>
<p>I wanted to see the type dispersion among the clusters, perhaps hoping to see a coherent split of types among the clusters…</p>
<table>
<thead>
<tr>
<th> </th>
<th>1</th>
<th>2</th>
<th>3</th>
<th>4</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Bug</strong></td>
<td>0</td>
<td>1</td>
<td>3</td>
<td>2</td>
</tr>
<tr>
<td><strong>Dark</strong></td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td><strong>Dragon</strong></td>
<td>0</td>
<td>0</td>
<td>1</td>
<td>0</td>
</tr>
<tr>
<td><strong>Electric</strong></td>
<td>2</td>
<td>0</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td><strong>Fighting</strong></td>
<td>0</td>
<td>0</td>
<td>1</td>
<td>1</td>
</tr>
<tr>
<td><strong>Fire</strong></td>
<td>2</td>
<td>0</td>
<td>2</td>
<td>0</td>
</tr>
<tr>
<td><strong>Ghost</strong></td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td><strong>Grass</strong></td>
<td>2</td>
<td>0</td>
<td>3</td>
<td>0</td>
</tr>
<tr>
<td><strong>Ground</strong></td>
<td>0</td>
<td>0</td>
<td>1</td>
<td>4</td>
</tr>
<tr>
<td><strong>Ice</strong></td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>1</td>
</tr>
<tr>
<td><strong>Normal</strong></td>
<td>0</td>
<td>1</td>
<td>5</td>
<td>2</td>
</tr>
<tr>
<td><strong>Poison</strong></td>
<td>0</td>
<td>0</td>
<td>4</td>
<td>2</td>
</tr>
<tr>
<td><strong>Psychic</strong></td>
<td>2</td>
<td>1</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td><strong>Rock</strong></td>
<td>1</td>
<td>0</td>
<td>0</td>
<td>2</td>
</tr>
<tr>
<td><strong>Water</strong></td>
<td>3</td>
<td>3</td>
<td>4</td>
<td>4</td>
</tr>
<tr>
<td><strong>Sum</strong></td>
<td>15</td>
<td>6</td>
<td>24</td>
<td>18</td>
</tr>
</tbody>
</table>
<p>Now comes the interesting bit, dissecting the data to see which pokemon clustered together and why they were thrown into the same cluster.</p>
<h2>Cluster 1</h2>
<p>Ok, so the pokemon that ended up in cluster 1 was: Voltorb, Oddish, Psyduck, Gastly, Houndour, Bulbasaur, Smoochum, Abra, Slugma, Magnemite, Remoraid, Omanyte, Ponyta, Horsea, Natu. This is quite an odd bunch if you know pokemon well. So, what was it that made them cluster together?</p>
<table>
<thead>
<tr>
<th>Stat</th>
<th>v.test</th>
<th>Mean.in.category</th>
<th>Overall.mean</th>
<th>p.value</th>
</tr>
</thead>
<tbody>
<tr>
<td>SA.lv1</td>
<td>6.2</td>
<td>77</td>
<td>49</td>
<td>0</td>
</tr>
<tr>
<td>SA.lv2</td>
<td>5.9</td>
<td>99</td>
<td>71</td>
<td>0</td>
</tr>
<tr>
<td>Total.lv1</td>
<td>2.5</td>
<td>320</td>
<td>297</td>
<td>0.01</td>
</tr>
<tr>
<td>Spd.lv1</td>
<td>2</td>
<td>61</td>
<td>52</td>
<td>0.05</td>
</tr>
<tr>
<td>HP.lv1</td>
<td>-2</td>
<td>39</td>
<td>46</td>
<td>0.04</td>
</tr>
<tr>
<td>Atk.lv1</td>
<td>-2.1</td>
<td>45</td>
<td>54</td>
<td>0.04</td>
</tr>
<tr>
<td>Atk.lv2</td>
<td>-2.1</td>
<td>67</td>
<td>79</td>
<td>0.03</td>
</tr>
<tr>
<td>HP.lv2</td>
<td>-2.3</td>
<td>61</td>
<td>70</td>
<td>0.02</td>
</tr>
</tbody>
</table>
<p>These Pokemon are specialist in special attacking moves. With the mean attack stat being almost 1/4 higher than the mean of all the other pokemon. These pokemon should be used when there is a type advantage!</p>
<h2>Cluster 2</h2>
<p>Moving onto cluster 2: Seel, Drowzee, Chinchou, Ledyba, Hoothoot, Tentacool.</p>
<table>
<thead>
<tr>
<th>Stat</th>
<th>v.test</th>
<th>Mean.in.category</th>
<th>Overall.mean</th>
<th>p.value</th>
</tr>
</thead>
<tbody>
<tr>
<td>SD.lv1</td>
<td>4.8</td>
<td>75</td>
<td>46</td>
<td>0</td>
</tr>
<tr>
<td>SD.lv2</td>
<td>4.5</td>
<td>102</td>
<td>70</td>
<td>0</td>
</tr>
<tr>
<td>HP.lv2</td>
<td>2.8</td>
<td>89</td>
<td>70</td>
<td>0</td>
</tr>
<tr>
<td>Atk.lv2</td>
<td>-2</td>
<td>59</td>
<td>79</td>
<td>0.05</td>
</tr>
<tr>
<td>Atk.lv1</td>
<td>-2.4</td>
<td>37</td>
<td>54</td>
<td>0.02</td>
</tr>
</tbody>
</table>
<p>Although these pokemon have defensive capabilities, these capabilities are more pronounced than what we saw in cluster 1 where the individuals had a small significant advantage in a specialized situation.</p>
<h2>Cluster 3</h2>
<p>This cluster was the biggest with 24 Pokemon ending up in this category. The pokemon that forms part of this cluster is: Ekans, Spinarak, Chikorita, Charmander, Totodile, Doduo, Dratini, Diglett, Spearow, Sentret, Zubat, Magikarp, Weedle, Caterpie, Nidoran(F), Nidoran(M), Meowth, Pidgey, Poliwag, Mankey, Cyndaquil, Hoppip, Squirtle, Bellsprout.</p>
<table>
<thead>
<tr>
<th>Stat</th>
<th>v.test</th>
<th>Mean.in.category</th>
<th>Overall.mean</th>
<th>p.value</th>
</tr>
</thead>
<tbody>
<tr>
<td>SD.lv1</td>
<td>-2.1</td>
<td>41</td>
<td>46</td>
<td>0.04</td>
</tr>
<tr>
<td>Def.lv1</td>
<td>-2.5</td>
<td>42</td>
<td>50</td>
<td>0.01</td>
</tr>
<tr>
<td>HP.lv2</td>
<td>-2.5</td>
<td>63</td>
<td>70</td>
<td>0.01</td>
</tr>
<tr>
<td>HP.lv1</td>
<td>-2.6</td>
<td>39</td>
<td>46</td>
<td>0.01</td>
</tr>
<tr>
<td>SA.lv1</td>
<td>-2.7</td>
<td>40</td>
<td>49</td>
<td>0.01</td>
</tr>
<tr>
<td>SD.lv2</td>
<td>-2.8</td>
<td>62</td>
<td>70</td>
<td>0</td>
</tr>
<tr>
<td>Def.lv2</td>
<td>-3</td>
<td>64</td>
<td>75</td>
<td>0</td>
</tr>
<tr>
<td>SA.lv2</td>
<td>-3.5</td>
<td>58</td>
<td>71</td>
<td>0</td>
</tr>
<tr>
<td>Total.lv1</td>
<td>-3.8</td>
<td>272</td>
<td>297</td>
<td>0</td>
</tr>
<tr>
<td>Total.lv2</td>
<td>-3.9</td>
<td>396</td>
<td>434</td>
<td>0</td>
</tr>
<tr>
<td>lvl_up.lv1</td>
<td>-4.5</td>
<td>20</td>
<td>25</td>
<td>0</td>
</tr>
</tbody>
</table>
<p>It would seem that these pokemon underscore on all statistics and should probably we avoided as strategic investments in your lineup.</p>
<h2>Cluster 4</h2>
<p>The last group that was identified were Pokemon that are all-rounders. Phanpy, Pineco, Snubbull, Kabuto, Krabby, Machop, Cubone, Grimer, Paras, Swinub, Larvitar, Wooper, Rhyhorn, Sandshrew, Goldeen, Slowpoke, Teddiursa, Koffing – have overall statistics which are higher than average, but does not specialize in any of the type specific advantages that exist in the Pokemon games.</p>
<table>
<thead>
<tr>
<th>Stat</th>
<th>v.test</th>
<th>Mean.in.category</th>
<th>Overall.mean</th>
<th>p.value</th>
</tr>
</thead>
<tbody>
<tr>
<td>Atk.lv2</td>
<td>4.6</td>
<td>102</td>
<td>79</td>
<td>0</td>
</tr>
<tr>
<td>Def.lv2</td>
<td>4.5</td>
<td>96</td>
<td>75</td>
<td>0</td>
</tr>
<tr>
<td>Atk.lv1</td>
<td>4.3</td>
<td>70</td>
<td>54</td>
<td>0</td>
</tr>
<tr>
<td>Def.lv1</td>
<td>4.3</td>
<td>68</td>
<td>50</td>
<td>0</td>
</tr>
<tr>
<td>HP.lv1</td>
<td>3.5</td>
<td>56</td>
<td>46</td>
<td>0</td>
</tr>
<tr>
<td>lvl_up.lv1</td>
<td>3.1</td>
<td>30</td>
<td>25</td>
<td>0</td>
</tr>
<tr>
<td>HP.lv2</td>
<td>3</td>
<td>81</td>
<td>70</td>
<td>0</td>
</tr>
<tr>
<td>Total.lv2</td>
<td>2.1</td>
<td>460</td>
<td>434</td>
<td>0.03</td>
</tr>
<tr>
<td>SD.lv1</td>
<td>-2</td>
<td>40</td>
<td>46</td>
<td>0.05</td>
</tr>
<tr>
<td>SA.lv1</td>
<td>-2.6</td>
<td>38</td>
<td>49</td>
<td>0.01</td>
</tr>
<tr>
<td>Spd.lv2</td>
<td>-3.8</td>
<td>51</td>
<td>70</td>
<td>0</td>
</tr>
<tr>
<td>Spd.lv1</td>
<td>-4</td>
<td>35</td>
<td>52</td>
<td>0</td>
</tr>
</tbody>
</table>
<h2>Paragons of the clusters</h2>
<p>One of the nicest outputs of <code>HCPC</code> is the listed paragons per group. These paragons can be seen as the poster-child representative of each cluster as they lie closest to the center of the cluster:</p>
<p>Cluster 1:</p>
<table>
<thead>
<tr>
<th>Natu</th>
<th>Psyduck</th>
<th>Houndour</th>
<th>Remoraid</th>
<th>Bulbasaur</th>
</tr>
</thead>
<tbody>
<tr>
<td>0.67</td>
<td>1.2</td>
<td>1.3</td>
<td>1.3</td>
<td>1.4</td>
</tr>
</tbody>
</table>
<p>Cluster 2:</p>
<table>
<thead>
<tr>
<th>Drowzee</th>
<th>Hoothoot</th>
<th>Seel</th>
<th>Tentacool</th>
<th>Chinchou</th>
</tr>
</thead>
<tbody>
<tr>
<td>0.88</td>
<td>1.1</td>
<td>1.2</td>
<td>1.7</td>
<td>1.7</td>
</tr>
</tbody>
</table>
<p>Cluster 3:</p>
<table>
<thead>
<tr>
<th>Nidoran(M)</th>
<th>Zubat</th>
<th>Pidgey</th>
<th>Poliwag</th>
<th>Sentret</th>
</tr>
</thead>
<tbody>
<tr>
<td>0.57</td>
<td>0.65</td>
<td>0.71</td>
<td>0.83</td>
<td>0.89</td>
</tr>
</tbody>
</table>
<p>Cluster 4:</p>
<table>
<thead>
<tr>
<th>Snubbull</th>
<th>Phanpy</th>
<th>Machop</th>
<th>Larvitar</th>
<th>Swinub</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>1.1</td>
<td>1.1</td>
<td>1.1</td>
<td>1.2</td>
</tr>
</tbody>
</table>
<p>The output of the <code>HCPC</code> also allows us to see the individuals which are the most distance from all the other cluster. For brevity, ill leave this table out of this post. These most distant individuals are usually outliers which end up in the group to which it relates (relatively) the closest.</p>
<p>#Conclusion<br>
This post explored cluster analysis, or formally put, a tool in which a multivariate dataset can be explored and eventually be divided into subgroups of similar data based on some kind of proximity estimate. I used Pokemon data as I found it to be an interesting dataset to apply this kind of technique. I must say, that the <code>FactoMineR</code> library helps a lot in facilitating the clustering process once your dataset is in proper format. It takes you through a natural progression of clustering application with a lot of flexibility available to the user to tune the analysis to his/hers needs. I especially like the <code>MFA</code> function where both <code>PCA</code> and <code>MCA</code> can be integrated into a concise function.</p>
<p>In terms of the results, I think it would be interesting to further delve into type combinations within the group in order to have the strongest Pokemon along with a type advantage. But we will leave this for another day…</p>
<p><div><div><div><div data-width="55" data-show-faces="false" data-send="true" data-layout="box_count" data-height="62" data-href="https://www.r-bloggers.com/gotta-catch-them-all/"></div></div><div><a data-url="https://www.r-bloggers.com/gotta-catch-them-all/" data-counturl="https://www.r-bloggers.com/gotta-catch-them-all/" data-count="vertical" data-text="Gotta catch them all" class="twitter-share-button" data-via="rbloggers" href="https://twitter.com/share"></a></div><div></div></div><div></div></div>
<div>
<div>To <strong>leave a comment</strong> for the author, please follow the link and comment on their blog: <strong><a href="http://eighty20.github.io//technique%20review/2016/08/21/Pokemon-clustering/"> Pareto's Playground</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/?s=tutorial">tutorials</a> on topics such as: <a title="Data science" rel="nofollow" href="https://www.r-bloggers.com/?s=data%20science">Data science</a>, <a title="Big Data" rel="nofollow" href="https://www.r-bloggers.com/?s=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/?s=ggplot2">ggplot2</a>, <a title="Boxplots using lattice and ggplot2 tutorials" rel="nofollow" href="https://www.r-bloggers.com/?s=boxplot">Boxplots</a>, <a title="Maps and gis" rel="nofollow" href="https://www.r-bloggers.com/?s=map">maps</a>, <a title="Animation in R" rel="nofollow" href="https://www.r-bloggers.com/?s=animation">animation</a>), programming (<a title="RStudio IDE for R" rel="nofollow" href="https://www.r-bloggers.com/?s=RStudio">RStudio</a>, <a title="Sweave and literate programming" rel="nofollow" href="https://www.r-bloggers.com/?s=sweave">Sweave</a>, <a title="LaTeX in R" rel="nofollow" href="https://www.r-bloggers.com/?s=LaTeX">LaTeX</a>, <a title="SQL and databases" rel="nofollow" href="https://www.r-bloggers.com/?s=SQL">SQL</a>, <a title="Eclipse IDE for R" rel="nofollow" href="https://www.r-bloggers.com/?s=eclipse">Eclipse</a>, <a title="git and github, Version Control System" rel="nofollow" href="https://www.r-bloggers.com/?s=git">git</a>, <a title="Large data in R using Hadoop" rel="nofollow" href="https://www.r-bloggers.com/?s=hadoop">hadoop</a>, <a title="Web Scraping of google, facebook, yahoo, twitter and more using R" rel="nofollow" href="https://www.r-bloggers.com/?s=Web+Scraping">Web Scraping</a>) statistics (<a title="Regressions and ANOVA analysis tutorials" rel="nofollow" href="https://www.r-bloggers.com/?s=regression">regression</a>, <a title="principal component analysis tutorial" rel="nofollow" href="https://www.r-bloggers.com/?s=PCA">PCA</a>, <a title="Time series" rel="nofollow" href="https://www.r-bloggers.com/?s=time+series">time series</a>, <a title="finance trading" rel="nofollow" href="https://www.r-bloggers.com/?s=trading">trading</a>) and more...
<img height="1" alt="" width="1" src="http://feeds.feedburner.com/~r/RBloggers/~4/0m1LrVk1B_o"></a></div>