Learning Data Exploration & Analysis Through the Pokedex Dataset

Data exploration & analysis

Data exploration is a critical skill that often goes under appreciated. It's often treated as more of an art than a science and that is because it requires a certain level of intution on how to take in raw data and turn out quantitative or qualitative results. In an attempt to hone my data exploration skills and teach myself how to create nice looking visualizations using Altair, I am using the most complete Pokemon dataset I could find from Kaggle.

How to be the very best?

The only real question when it comes to being a Pokemon trainer is, "Can I be the very best, like no one ever was?" In order to answer this question though we will need to do some digging to find out!

  1. What are the distributions of Pokemon stats? (HP, Attack, Defense, Special Attack, Special Defense, Speed)
  2. Which Pokemon are strongest overall using these stats? Which are the weakest?
  3. Which Pokemon types are the strongest overall? Which are the weakest?

By the end of this notebook I hope you will have a good idea of which Pokemon can help you become the greatest Pokemon trainer of all time!

Imports

First we'll import some python modules that we'll be using in this notebook

Data Sanitization

This dataset actually came pretty neatly packaged; however, there were a few things I needed to do. Namely, set some strings to lower case, have columns names match entry values for cross referencing, and change some column names for convenience. All other work is done by creating new dataframes off of this dataframe.

Make a Pokedex

For thematic purposes and for some conveniences later on we'll also make a Pokedex dataframe for easy reference of the Pokemon attributes that are not quantitative in nature.

1. What are the distributions of Pokemon stats? (HP, Attack, Defense, Special Attack, Special Defense, Speed)

First, we'd like to explore the whole world of Pokemon to understand how their stats vary and in order to do that we need to standardize the dataset. Here we adjust the values of the stats across the whole pokedex to have zero mean and unit standard deviation. This will allow us to more uniformly compare individual Pokemon to others on an even basis. We then perform a sanity check for our peace of mind.

The next thing we do is start exploring the stats and checking for correlations. We can create a matrix scatter plot to show how different statistics correlate to eachother. Here we can notice a few things:

  1. In general, there is a positive correlation across all of the statistics. This makes intuitive sense since any pokemon that is "stronger" than another would also very likely be higher in all the attributes. So all stats go up for stronger Pokemon.
  2. The primary counter example to the previous point is that speed and defense seem to not be correlated at all. This interesting since I would expect slower Pokemon to be bigger and bulkier, meaning that they would also be high in defense, but clearly the spread is more independent than that.
  3. Finally, the strongest correlations tend to be between attack and special attack as well as defense and special defense as well as attack and defense. Together, this all means essentially that "stronger Pokemon are stronger" in that we see Pokemon whose attack is high also have high defense, etc. This furthers the point in number 1.

Another interesting note is that if we code the color of the scatter matrix by type between Normal (i.e. common), Sub Legendary, Legendary and Mythical we see that all of the Sub Legendary, Legendary and Mythical Pokemon skew to the upper right in the plots. In the density plots they also tend to be above the zero mean, while common Pokemon tned to stay below the zero mean mark. Again, it would appear that intutitively Mythical, Legendary, Sub Legendary Pokemon tend to be stronger than Normal Pokemon on the whole.

2. Which Pokemon are strongest overall?

Z-score Strength Analysis

So now we have a feel for how the attibutes are distributed against each other, but what makes a strong Pokemon? One method of determining strength is to sum up all of the standardized stats we have for each Pokemon and divide it by the square root of the number of attributes. This is known as Stouffer's Z-score method. By doing this we are making two major assumptions:

  1. That all stats should be weighted the same (should they?)
  2. and that they are mostly independent (they clearly aren't)

So obviously this isn't a perfect metric for strength; however, for the most part this should suffice and we can always tweak it later if we want.

We sum up the individual standardized attributes and divide by the square root of the number of attributes (in this case 6) to arrive at the z-score for each Pokemon. Using this metric, we can directly look up the most powerful Pokemon in our pokedex.

No surprise, all of the strongest Pokemon are Mythical or Legendary! We can also look at the median for a given type (or dual type) Pokemon and see if there are some types that stand out more than others.

Here we highlight the top 10 median values for Pokemon with given types. Both steel and dragon types make a strong showing while bug type tends to really stand out as being very, very weak. But we should keep in mind this incorporates Legendary/Mythical Pokemon. It is a little too unreasonable to say that to be the best you must catch Pokemon that are literally legends, so let's filter those out.

We can see below now that we've filtered out the legendaries our top 10 has changed. We are still very heavy on the dragon front though. Let's take a look at the type strengths.

Only considering normal Pokemon we see that dragon and steel make strong showings, while bug types are still the weakest (sorry Butterfree fans). Below are both charts side by side for convenience in referencing them. You'll notice many empty squares on the right. This is because many of the legendary Pokemon are the only ones of their unique type.

One thing I wanted to investigate though was the likelihood of catching the common Pokemon that fit the best types. We don't have data for encounter rates or frequency of interaction, but we can do a kind of proxy by seeing how many different Pokemon exist of a given type. Below is a heatmap of how many common Pokemon exist of a given type-pair (or single type) with boxes around the strongest types from above. Here we can see that

  1. There are many more instances of single-types (e.g. bug-bug) than many other dual types and
  2. All of the dual types identified as the "best" previously only have a few Pokemon that exist that fit the bill.

This tends to tell us again that to get these Pokemon with the types that have good strength we may have to work a bit harder. This makes sense though since it shouldn't necessarily come very easy.

Finally, one thing worth noticing is that on our previous list of strongest normal Pokemon (recreated below) actually has types that aren't identified as "best" in terms of median. Slaking and Goodra are both single type Pokemon, which means their strong scores get watered down by other weaker Pokemon. In fact 6 of the top 10 listed below are different dragon types while we only identified dragon-flying as being a top-10 strength type.

Z-score Strength Analsysis Conclusions

Overall, the z-score method of evaluating a Pokemon's strength has helped break down the mutliple attributes, but it doesn't tell the whole story and needs refinement. Some ways to do this could be weighting the z-score (e.g. scaling HP by 2), using the norm of the stats instead of the z-score as our strength metric, or using principal component analysis (PCA) like in the next section.

Principal Component Analysis of Pokemon Strength

Principal component analysis (PCA) is used to explore datasets and reduce dimensionality of observations. Mathematically, PCA determines a vector basis that maximizes the variance of the samples, but put in regular English it simply means that we can determine which combination of stats explain the biggest differences between Pokemon so we can breakdown weak Pokemon from strong Pokemon.

Before when using the Z-score method we made two assumptions, that the stats weights should be uniformly weighted and that they are also independent, both of which were weak assumptions. Here PCA actually handles both of these for us by giving us stat weights and forcing those different weights to be independent. Ideally this should be a better metric.

For this we take the standardized stats we used before, but perform PCA on them to effectively get weights for each of the stats. The first principal compnent then tells us which combination of stats are the most important to the variation of Pokemon strength, the second tells us which combination of stats are second most important and so on. We can do this up to 6 times (the number of original stats we have to begin with), but the nice part about PCA is that we can probably get a good feel by using fewer components than we had to begin with. In our case we'll look at the firt 3 principal components.

Here we see that the first 3 principal components explain 76.8% of the variance in the Pokemon stats HP, Attack, Defense, Special Attack, Special Defense and Speed. 100% would be ideal since it would fully explain the dataset, but 76.8% isn't too bad (a common acceptable level is about 80%). The first principal component here tells us that we can weight the HP stat by 42%, Attack by 43% and so on. We actually see in the first PC that each of the stats are weighted relatively the same. Intuitively, this would suggest that Pokemon that are higher in all stats then have higher PC1 values, so let's take a closer look.

Each of the dots here represent Pokemon stats in their principal components. By coding the color in terms of legendary/non-legendary Pokemon we actually see that our mythical, legendary & sub legendary Pokemon have higher values in the first principal component PC1. Legendary Pokemon have high values for all stats so this follows our intutition from above where Pokemon high in all stats will have high PC1 values. There is a clear break in the dataset between legendary/non-legendary Pokemon, so in one sense our PC1 is actualy a sense of how "legendary" a Pokemon actually is. We also see in the PC2/PC3 plots that they are more centralized and gaussian in nature. The only clear break is that sub-legendary and mythical Pokemon tend to skew outward in the radial direction, but true legendary Pokemon actually overlap more with normal Pokemon.

Using this information, we can begin to rank Pokemon by their PC1 values to see which Pokemon are more "legendary" than others and compare to our previous z-score strength metric.

We see here that our first three Pokemon are the same, but there are some differences later. First, the PCA metric has some Pokemon shifting around like Ho-oh, Giratina and Eternatus, but some Pokemon also don't show up in the PCA column like Lugia and Solgaleo. Now let's look at non-legendary Pokemon like before.

Here again we see the same kind of idea, the top Pokemon stay on top and others shift around. Interestingly, the top 10 all stayed the top 10 though. Maybe our z-score metric was pretty good afterall!

PCA Conclusions

Here we tried to develop a separate metric for how strong a Pokemon is. Using PCA we determined that the first PC was actually a good metric for how "legendary" a Pokemon was in terms of base stats. Using this information we ranked the top legendary and non-legendary Pokemon and saw that there was not much difference in the very top echelon of Pokemon. Just because our metrics correlate though doesn't mean they're good; however, it would appear that as a first pass these aren't necessarily bad metrics since almost by defintion legendary Pokemon should be stronger than others.

3. Which Pokemon types are strongest and weakest?

Another way we can look at Pokemon strength is not based on their individual stats, but on their type matchup bonuses. The equation for dealing damage in Pokemon is very complicated, but ultimately there is a multiplier for when certain types of Pokemon match up against others. For example, when a fire type Pokemon attacks a grass type it deals double damage. We can assess how strong a given type of Pokemon is if it can deal more damage by having a higher multiplier in more matchups.

First we'll make a type matchup matrix that reflects all the different possible combinations.

NOTE: One quick note about this section. Before when we talked about "normal" Pokemon it was actually in the context of rarity and was a reference for if it was common or not. Here "normal" is an actual Pokemon attack type and is not correlated to how common a Pokemon is.

You can think of this chart as how well an attack will do against a certain type. First we find the row of the attack we want to perform, for example Flamethrower from a Charizard. Then we find the defending Pokemon column to see what the multiplier is, in our example Venasaur is a grass type. So Charizard's attack will deal double damage to Venasaur over another type of Pokemon matchup.

Important to know here though is that a Pokemon's defense type is static (a Venasaur will always be grass), but Pokemon can learn attacks from many different types. That is, Charizard can learn normal attack types such as Tackle and when used against Venasaur this has unit multiplier, it does not deal double damage. So for our analysis we aren't neceassrily considering literal matchup types, but rather attack types vs defending Pokemon types.

One natural way of assessing how effective an attack type would be over the long run is assessing the means of attack multipliers and defense multipliers. This shows that across all battles and all Pokemon a multiplier would average out to the mean. This makes a large assumption that you're uniformly likely to run into any Pokemon type, which definitely isn't the case, but it's not a bad way get a feel.

We can take the means across the columns to get an effective attack multiplier and do the same for rows to get effective defense multipliers. For attack multipliers, higher is better since we want to do more damage, but for defense multiplier lower is better because we would want our Pokemon to receive less damage. We can plot these against each other on a scatter plot to see which types have optimal values. Similarly we can take the ratio of attack multiplier over defense multiplier and now we have a monotonic metric where higher is always better.

We see here that the top left corner is optimal and the types of steel, fairy, fire and ground form a Pareto front for optimizing damage done while minmizing damage received. We also plot the ratio of the two and see that indeed these two have the highest ratios.

This is only for single type match ups though and as we saw many Pokemon have dual types, which have a multiplicative factor so if I used a fire type attack on a grass/water type Pokemon (which doesn't exist but bear with me for this example) then the 2 multiplier and the .5 multiplier would balance out to have a unit multiplier.

We can plot these dual type values and ratios as heat map to see if any trends emerge.

Looking at the ratio heatmap we see that steel performs very, very well in terms of multipliers. Additionally, grass type Pokemon seem to perform very poorly and as before bug type also perform poorly. From these plots it would seem that steel types can expect to have very favorable results across the long term. Also, similar to single type matchups, steel, fairy, fire and ground all perform favorably with the addition of flying and fighting types.

Type Matchup Strength Analysis Conclusions

Rather than look at individual Pokemon stats we tried to use an independent portion of the data to see if any types would stand out further. Single and dual type matchups indicated that steel, ground, fairy and fire matchups are favorable for the attacker and further flying and fighting types perform well for dual type matchups.

Final Conclusions

In an effort to be the very best, like no one ever was, we attempted to assess how find the best Pokemon. First we standardized Pokemon stats of HP, Attack, Defense, Special Attack, Special Defense and Speed and plotted them against each other to see how they correlate. Most of the stats were positively correlated, which lead us to the conclusion that "stronger Pokemon are stronger" since an increase in HP also means an increase in Attack, etc.

We then took these standardized statistics and combined them into a z-score. We used z-score to rank Pokemon first in terms of absolute standing, but also in terms of finding the best types of Pokemon to capture. This lead us to two conclusions: 1. dragon type Pokemon tend to be more favorable across the board and 2. it's still useful to find the strongest overall Pokemon (e.g. Slaking) since their z-score gets "watered" down by other Pokemon in its type class.

We then used PCA to perform a similar type of analysis as z-score. The first principal component was a good metric for how "legendary" a Pokemon was. We then saw that there was a strong overlap between PCA ranking and Z-score ranking validating our z-score method and confirming our intutition that the more "legendary" a Pokemon is the stronger they are.

Finally, we used a different part of the dataset to just assess Pokemon on how effective their attacks would be against other types rather than look at Pokemon directly. This indicated that steel types, above all others, are preferable in terms of dealing the most damage and receiving the least damage, while dragon, fairy, fire, ground, flying and fighting types are all strong as well.

This analysis wouldn't be complete without determing which Pokemon would make a strong roster though. To do this we'll make a rough metric by multiplying the ratio of the multipliers by PC1 and determining rank from there.

So there we have it. Of course the ideal would be to use strictly legendary Pokemon to have the most elite roster, but for us mere mortals there is at least a roster of very strong Pokemon to use as well. In the end though, there are so many factors that go into selecting a Pokemon team and often it could be tailored to who you are facing. If you know you are going up against something heavy in Fire/Fighting/Psychic types we can redo the calculations to determine what ideal roster would like, but if you want the ultimate team that can go up against just about anybody we've determined that dragon types are dominant as are steel and psychic. I hope this helps in your adventure to become the greatest Pokemon trainer the world has ever known!

References

  1. https://stackoverflow.com/questions/53484548/format-text-of-mark-text-in-altair
  2. https://stackoverflow.com/questions/60237871/altair-access-rsquared-value-in-a-regression
  3. https://inmachineswetrust.com/posts/exploring-pokemon-dataset/
  4. https://www.kaggle.com/strakul5/principal-component-analysis-of-pokemon-data
  5. https://towardsdatascience.com/pca-clearly-explained-how-when-why-to-use-it-and-feature-importance-a-guide-in-python-7c274582c37e
  6. https://altair-viz.github.io/gallery/percentage_of_total.html