Análise Estatística e Mecânicas de Pokémon

Carregamento de Dados

Inicialmente, vamos instalar e carregar os pacotes que serão usados:

install.packages("DT", repos = "https://cloud.r-project.org/")
library(dplyr)
library(readr)
library(stringr)
library(DT)
library(janitor)

Após isso, vamos carregar os datasets que vamos utilizar:

url1 <- "https://raw.githubusercontent.com/michaellomuscio/Exploring-Data/master/PokemonData.csv"
df1 <- read_csv(url1)
url2 <- "https://www.dropbox.com/scl/fi/yr4srrbfd2jsx281kxk0u/pokemon.csv?rlkey=aujmk34bb06mu0qb7s90ehe4a&st=24oxpb16&dl=1"
df2 <- read_csv(url2)

Aqui vamos usar dois datasets para conseguir todas as informações necessárias para algumas demonstrações e análises.

Pré-processamento

Neste passo, vamos unir as principais colunas de cada um dos datasets. O segundo dataset será utilizado principalmente para complementar o primeiro com informações mais técnicas. Embora o segundo contenha quase todos os dados, o primeiro apresenta informações mais consistentes, por isso será adotado como dataset principal.

df_pokemon <- df1 %>%
  select(everything()) %>%  
  inner_join(
    df2 %>% select(name, classfication, experience_growth, percentage_male, is_legendary, starts_with("against_"), capture_rate),
    by = c("Name" = "name")
  )

Aqui temos uma organização geral desse dataframe que será utilizado, ajustando as nomenclaturas e os tipos de algumas das colunas:

df_pokemon <- df_pokemon %>%
  mutate(is_legendary = as.logical(is_legendary)) %>%
  mutate(classfication = as.factor(classfication)) %>%
  mutate(Generation = factor(Generation, levels = sort(unique(Generation)), ordered = TRUE)) %>%
  mutate(capture_rate = as.double(capture_rate)) %>%
  rename(CaptureRate = capture_rate) %>%
  rename(Classification = classfication) %>%
  rename(ExpGrowth = experience_growth) %>%
  rename(ID = Num) %>%
  rename_with(~ str_replace_all(., "_([a-z])", function(x) toupper(sub("_", "", x))))
str(df_pokemon)

Colunas Adicionadas

Pokémon Míticos e Lendários

Aqui nós temos a primeiro coluna adicinal do nosso dataframe:

mythical_names <- c("Jirachi", "Darkrai", "Arceus", "Victini", "Diancie", "Volcanion")

df_pokemon <- df_pokemon %>%
  # Pequeno ajuste, apenas porque alguns pokemon míticos estavam sendo tratados como lendários e vice-versa
  mutate(Legendary = case_when(
      Name %in% mythical_names ~ FALSE,
      Name == "Cresselia" ~ TRUE,
      TRUE ~ Legendary)) %>%
  mutate(isLegendary = !Legendary & isLegendary) %>%
  rename(Mythical = isLegendary)

Embora essas duas colunas (“Legendary” e “isLegendary”) dos dataframes originais pareçam ter a mesma função, elas tem uma pequena variação de significado:

  • Para o “df1”, “Legendary” são apenas os Pokémon de fato considerados lendários;
  • Para o “df2”, “isLegendary” inclui os Pokémon míticos.
Pokémon Lendários!
Pokémon Lendários!
 df_pokemon %>%
  filter(Legendary) %>%
  select(Name, Type1, Type2, Legendary, Generation) %>%
  datatable(
    options = list(
      pageLength = 5,
      autoWidth = TRUE
    ),
    caption = "Pokémon Lendários")

De fato, em geral Pokémon Míticos são entendidos como sendo um subconjunto dos Pokémon Lendários. A diferenciação entre eles é puramente determinada por como eles são apresentados nos jogos. (Bulbapedia contributors 2025c) O entendimento geral da comunidade é que os Míticos se difeririam dos Lendários por serem tão incrivelmente raros no mundo de Pokémon que poucas pessoas realmente acreditam na sua existência.(Bulbapedia contributors 2025d) Tradicionalmente, os Míticos, ao contrário dos Lendários que em geral podem ser obtidos normalmente no decorrer do jogos, só poderiam ser obtidos por meio de eventos de distribuição oficiais.

df_pokemon %>%
  filter(Mythical)%>%
  select(Name, Type1, Type2, Mythical, Generation) %>%
  datatable(
    options = list(
      pageLength = 5,
      autoWidth = TRUE
    ),
    caption = "Pokémon Míticos")
Pokémon Míticos!
Pokémon Míticos!

Pokémon Pseudo-Lendários

Há ainda uma terceira categoria para classificação de Pokémon, essa sendo um tanto mais matemática que as demais. Trata-se da divisão de Pokémon Pseudo-Lendários. (Bulbapedia contributors 2025e)

Essa classificação não é oficial, sendo apenas um termo cunhado pela comunidade para definir um pequeno grupo de Pokémon que não são lendários ou míticos mas que obdecem alguns critérios: \[ \text{PseudoLegendary}_i = \begin{cases} \text{TRUE}, & \text{se } \begin{aligned}[t] & \text{TotalStats}_i \ge 600 \;\land\; \neg \text{Legendary}_i \;\land\; \neg \text{Mythical}_i \\[4pt] & \land\; \text{ExpGrowth}_i = 1{,}250{,}000 \;\land\; \text{FinalStageOfThreeStageLine}_i \end{aligned} \\[10pt] \text{FALSE}, & \text{caso contrário} \end{cases} \]

Sendo:

  • \(\text{Legendary}_i\) verdadeiro se o Pokémon é Lendário;
  • \(\text{Mythical}_i\) verdadeiro se o Pokémon é Mítico;
  • \(\text{ExpGrowth}_i = 1{,}250{,}000\) verdadeiro caso o total de pontos de experiência acumulados pelo Pokémon sejam iguais a 1.200.00 ao chegar ao nível 100;
  • \(\text{FinalStageOfThreeStageLine}_i\) verdadeiro se o Pokémon é o estágio finald e uma linha evolutiva com 3 estágios evolutivos;
  • \(\text{TotalStats}_i\) definido como: \[ \text{TotalStats}_i = \text{HP}_i + \text{Attack}_i + \text{Defense}_i + \text{SpAtk}_i + \text{SpDef}_i + \text{Speed}_i \] , sendo por sua vez:
    • \(\text{HP}_i\) o total base de pontos de vida;
    • \(\text{Attack}_i\) o total base de pontos de ataque;
    • \(\text{Defense}_i\) o total base de pontos de defesa;
    • \(\text{SpAtk}_i\) o total base de pontos de ataque especial;
    • \(\text{SpDef}_i\) o total base de pontos de defesa especial;
    • \(\text{Speed}_i\) o total base de pontos de velocidade.
df_pokemon <- df_pokemon %>%
  mutate(PseudoLegendary = (rowSums(across(c(5:10)), na.rm = TRUE) >= 600) & !Legendary & !Mythical & ExpGrowth == 1250000) %>%
  select(ID, Generation, Name, Type1, Type2, Classification, HP, Attack, Defense, SpAtk, SpDef, Speed, Legendary, Mythical, PseudoLegendary, ExpGrowth, percentageMale, everything())
df_pokemon %>% filter(PseudoLegendary) %>% select(c(Name, ExpGrowth, Classification))

Esses critérios foram aqui usados (com exceção do último, já que os datasets não apresentavam essa informação e ela não foi necessária) para definir uma coluna adicional justamente para definir quais Pokémon são Pseudo-Lendários.

Pokémon Pseudo-Lendários!
Pokémon Pseudo-Lendários!
df_pokemon %>%
  filter(PseudoLegendary)%>%
  select(Name, Type1, Type2, PseudoLegendary, Generation) %>%
  datatable(
    options = list(
      pageLength = 5,
      autoWidth = TRUE
    ),
    caption = "Pokémon Pseudo-Lendários")

Curiosidade:

Análisando os resultados advindos dessas databases podemos ver um pokémon que normalmente não é listado como um pseudo-lendário: Slaking.

Quase um pseudo-lendário
Quase um pseudo-lendário

Ele aparece na listagem anteriormente apresentada porque de fato ele cumpre todos os requisitos para ser um Pseudo-lendário. O único ponto que faz com que ele não seja considerado como tal pela comunidade é a sua habilidade “Truant” (livremente traduzido para “Gazeador”), que faz com que ele não seja um Pokémon tão forte quanto os demais.

Truant (Ability)

Effect: Truant causes the ability-bearer to only attack every alternate turn. On the even turns, it will say the Pokémon is loafing around.

Tipagem de Pokémon

Efetividade por Tipo

Em Pokémon, há várias tipagens diferentes para os Pokémon, isso não é apenas mais uma características deles como também é uma forma que definir quais são mais fortes entre si por natureza. (Bulbapedia contributors 2025f)

Cada tipo de Pokémon possui diferentes níveis de efetividade em relação a outros tipos. Além disso, um Pokémon pode ter até dois tipos, e as vantagens ou desvantagens se combinam, podendo se somar ou se anular conforme a combinação.

A efetividade total de um ataque de determinado tipo contra um Pokémon é calculada multiplicando as efetividades correspondentes a cada um dos tipos do Pokémon defensor. (Bulbapedia contributors 2025g)

\[ \text{TypeEffectiveness} = \text{EType1} \times \text{EType2} \] Sendo:

  • \(\text{Type1}\) representa a efetividade do ataque em relação ao primeiro tipo do Pokémon defensor;
  • \(\text{Type2}\) representa a efetividade do ataque em relação ao segundo tipo do Pokémon defensor. Se o Pokémon não tiver um segundo tipo esse valor é 1;

Por exemplo, um movimento do tipo Voador contra o Pokémon Parasect seria calculado como:

\[ \text{TypeEffectiveness} = 2\text{ (Voador x Inseto)} \times 2\text{ (Voador x Planta)} = 4 \]

df_pokemon %>%
  filter(Name == "Parasect") %>%
  select(Name, Type1, Type2, againstFlying) %>%
  knitr::kable(
    align = "c"
  )
Name Type1 Type2 againstFlying
Parasect Bug Grass 4

Ou mesmo, um ataque do tipo psíquico com o Pokémon Pangoro:

\[ \text{TypeEffectiveness} = 2\text{ (Psíquico x Lutador)} \times 0\text{ (Psíquico x Noturno)} = 0 \]

df_pokemon %>%
  filter(Name == "Pangoro") %>%
  select(Name, Type1, Type2, againstPsychic) %>%
  knitr::kable(
    align = "c"
  )
Name Type1 Type2 againstPsychic
Pangoro Fighting Dark 0

\[ \text{Damage} = \left( \frac {\frac{(2 \times \text{Level} \times \text{Critical})}{5} + 2) \times \text{Power} \times \frac{A}{D}}{50} + 2 \right) \times \text{STAB} \times \text{Type} \times \text{random} \]

\[ \text{Type} = \text{Type1 Effectiveness} + \text{Type2 Effectiveness} \]

Determinismo com um pouco de Aleatoriedade

Algumas mecânicas em Pokémon são determinadas por alguns fatores específicos mas também tem um pouco de aleatoriedade envolvida, vamos ver alguns adiante:

Cálculo de Dano

O dano causado por um ataque em Pokémon é determinado por uma fórmula que leva em consideração múltiplos fatores — como o nível do atacante, seu poder de ataque, o poder defensivo do alvo, o tipo do movimento e até elementos de aleatoriedade. (Bulbapedia contributors 2025b)

\[ \text{Damage} = \left( \frac{((2 \times \text{Level} / 5 + 2) \times \text{Power} \times \frac{A}{D})}{50} + 2 \right) \times \text{Modifier} \]

Sendo:

  • Level o nível do Pokémon atacante;
  • Power o poder base do ataque;
  • \(\frac{A}{D}\) a razão entre o Attack (ou Special Attack, dependendo do tipo de golpe) do atacante e o Defense (ou Special Defense) do defensor;
  • \(\text{Modifier}\) definido como: \[ \text{Modifier} = \text{STAB} \times \text{TypeEffectiveness} \times \text{Critical} \times \text{Random} \]

, que por sua vez: - STAB (Same Type Attack Bonus) é 1.5× se o tipo do ataque for o mesmo tipo do atacante.
- TypeEffectiveness é o multiplicador baseado nas relações de tipo definito na seção de Tipagem (ex: 2×, 0.5×, 0×).
- Critical: se for um golpe crítico, multiplica o dano por 1.5×.
- Random: fator aleatório entre 0.85 e 1.00.


Mecânica de Captura e Catch Rate

A captura de um Pokémon selvagem depende de vários fatores, resumidos na seguinte fórmula(Bulbapedia contributors 2025a):

\[ a = \left(\frac{3 \times \text{MaxHP} - 2 \times \text{CurrentHP}}{3 \times \text{MaxHP}}\right) \times \text{CatchRate} \times \text{BallBonus} \times \text{StatusBonus} \]

Sendo:

  • MaxHP: os pontos de vida máximos do Pokémon selvagem.
  • CurrentHP: os pontos de vida atuais — quanto menor esse valor, maior a chance de captura.
  • CatchRate: um valor base específico de cada espécie de Pokémon (por exemplo, Mewtwo possui taxa 3, enquanto Pidgey tem 255).
  • BallBonus: o multiplicador da Pokébola utilizada.
  • StatusBonus: o multiplicador concedido por condições de status, como sono ou paralisia.

Exemplos de modificadores de Pokébola comuns:

  • Poké Ball comum: \(1 \times\)
  • Great Ball: \(1.5 \times\)
  • Ultra Ball: \(2 \times\)
  • Pokémon adormecido ou congelado: \(2 \times\)
  • Pokémon paralisado, envenenado ou queimado: \(1.5 \times\)

Se \(a \ge 255\), a captura é garantida; caso contrário, o jogo calcula a probabilidade real de sucesso com base em um número aleatório gerado internamente.

A aproximação usada nas gerações clássicas é dada por:

\[ \text{CaptureProbability} \approx \frac{\text{StatusCondition}}{\text{Ball} + 1} + \left(\frac{(\text{CatchRate} + 1)}{\text{Ball} + 1} \times \frac{(f + 1)}{256}\right) \]

onde:

\[ \text{StatusCondition} = \begin{cases} \frac{1}{2}, & \text{se estiver envenenado, queimado ou paralisado} \\[6pt] \frac{5}{2}, & \text{se estiver dormindo ou congelado} \\[6pt] 0, & \text{caso contrário} \end{cases} \]

\[ \text{Ball} = \begin{cases} 255, & \text{Poké Ball} \\[6pt] 200, & \text{Great Ball} \\[6pt] 150, & \text{Ultra ou Safari Ball} \end{cases} \]

O termo \(f\) depende dos pontos de vida e da bola utilizada, refletindo o quanto o Pokémon foi enfraquecido durante a batalha.


Em resumo, o processo de captura e de batalha combina fatores determinísticos — como HP atual, tipo de bola e condição de status — com um elemento de aleatoriedade.

Referências

Bulbapedia contributors. 2025a. Catch rate — Bulbapedia, the community-driven Pokémon encyclopedia.” https://bulbapedia.bulbagarden.net/wiki/Catch_rate.
———. 2025b. Damage — Bulbapedia, the community-driven Pokémon encyclopedia.” https://bulbapedia.bulbagarden.net/wiki/Damage.
———. 2025c. Legendary Pokémon — Bulbapedia, the community-driven Pokémon encyclopedia.” https://bulbapedia.bulbagarden.net/wiki/Legendary_Pokémon.
———. 2025d. Mythical Pokémon — Bulbapedia, the community-driven Pokémon encyclopedia.” https://bulbapedia.bulbagarden.net/wiki/Mythical_Pokémon.
———. 2025e. Pseudo-legendary Pokémon — Bulbapedia, the community-driven Pokémon encyclopedia.” https://bulbapedia.bulbagarden.net/wiki/Pseudo-legendary_Pok%C3%A9mon.
———. 2025f. Type — Bulbapedia, the community-driven Pokémon encyclopedia.” https://bulbapedia.bulbagarden.net/wiki/Type.
———. 2025g. Type effectiveness — Bulbapedia, the community-driven Pokémon encyclopedia.” https://bulbapedia.bulbagarden.net/wiki/Type#Type_effectiveness.