Jakie typy powinieneś mieć w swojej drużynie Pokémonów? Efektywna symulacja z macierzami w R

Macierzowa magia

Początkowo myślałem o nazwaniu tego postu „Powrót do bazy”, ponieważ wychodzę z tidyverse i wkraczam w świat macierzy, ale tak naprawdę nie ma w tym nic podstawowego. Przejdźmy przez to krok po kroku.

Po pierwsze, weźmiemy naszą tabelę i zrobimy z niej macierz. Nie możemy po prostu zrobić tego bezpośrednio as.matrix(), ponieważ spowoduje to, że kolumna Atakowanie będzie pierwszą kolumną, podczas gdy my chcemy, aby to były nazwy własne, więc zrobimy to w dwóch krokach.

m <- as.matrix(type_comparisons)rownames(m) <- type_comparisons$Attacking

Następnie, ponieważ zależy nam tylko na tym, czy wpis jest 2, czy nie, zmienimy każdy wpis, który jest 2, na 1 i każdy wpis, który nie jest, na 0 (1L * sprawia, że jest to 1 lub 0 zamiast TRUE lub FALSE).

super_effective_m <- (m == 2) * 1L
super_effective_m
## Normal Fire Water Electric Grass Ice Fighting Poison Ground Flying## Normal 0 0 0 0 0 0 0 0 0 0## Fire 0 0 0 0 1 1 0 0 0 0## Water 0 1 0 0 0 0 0 0 1 0## Electric 0 0 1 0 0 0 0 0 0 1## Grass 0 0 1 0 0 0 0 0 1 0## Ice 0 0 0 0 1 0 0 0 1 1## Fighting 1 0 0 0 0 1 0 0 0 0## Poison 0 0 0 0 1 0 0 0 0 0## Ground 0 1 0 1 0 0 0 1 0 0## Flying 0 0 0 0 1 0 1 0 0 0## Psychic 0 0 0 0 0 0 1 1 0 0## Bug 0 0 0 0 1 0 0 0 0 0## Rock 0 1 0 0 0 1 0 0 0 1## Ghost 0 0 0 0 0 0 0 0 0 0## Dragon 0 0 0 0 0 0 0 0 0 0## Dark 0 0 0 0 0 0 0 0 0 0## Steel 0 0 0 0 0 1 0 0 0 0## Fairy 0 0 0 0 0 0 1 0 0 0## Psychic Bug Rock Ghost Dragon Dark Steel Fairy## Normal 0 0 0 0 0 0 0 0## Fire 0 1 0 0 0 0 1 0## Water 0 0 1 0 0 0 0 0## Electric 0 0 0 0 0 0 0 0## Grass 0 0 1 0 0 0 0 0## Ice 0 0 0 0 1 0 0 0## Fighting 0 0 1 0 0 1 1 0## Poison 0 0 0 0 0 0 0 1## Ground 0 0 1 0 0 0 1 0## Flying 0 1 0 0 0 0 0 0## Psychic 0 0 0 0 0 0 0 0## Bug 1 0 0 0 0 1 0 0## Rock 0 1 0 0 0 0 0 0## Ghost 1 0 0 1 0 0 0 0## Dragon 0 0 0 0 1 0 0 0## Dark 1 0 0 1 0 0 0 0## Steel 0 0 1 0 0 0 0 1## Fairy 0 0 0 0 1 1 0 0

Macierz all_combinations, którą stworzyliśmy wcześniej, jest w zasadzie zbiorem indeksów dla macierzy super_effective_m. Na przykład, kolumna 1 all_combinations to liczby od 1 do 6, co oznacza, że chcemy uzyskać wiersze od 1 do 6 super_effective_m. Pamiętaj, że każdy rząd super_effective_m to typ atakujący w naszej drużynie, a każda kolumna to typ broniący. Następnie chcemy uzyskać sumę każdej kolumny i wiedzieć, ile kolumn ma sumę większą niż 0, co oznacza, że przynajmniej jeden z naszych typów atakujących był super skuteczny przeciwko niemu. Stworzymy funkcję, super_effective_nb:

super_effective_nb <- function(indices) { sum(colSums(super_effective_m) > 0)}

Teraz możemy użyć apply() aby uzyskać wektor, dla wszystkich 18k+ drużyn, ile typów jest super skutecznych przeciwko nim. Jeśli nie jesteś zaznajomiony z apply(), pierwszym argumentem jest to, do czego stosujemy naszą funkcję, drugim jest to, czy ma ona być stosowana do wierszy czy kolumn (wybieramy 2 dla kolumn, ponieważ każda kolumna to drużyna), a trzecim jest funkcja.

super_effective_results <- apply(all_combinations, 2, super_effective_nb)

Jakie są kombinacje, które są super skuteczne przeciwko maksymalnej liczbie możliwych typów?

which(super_effective_results == max(super_effective_results))
## 14323 14325 15610 15612 16454 16459 16852 16854 16989 16994

Widzimy, że istnieje 10 możliwych kombinacji sześciu typów. Przyjrzyjmy się im, pobierając te kolumny z all_combinations.

best_combos <- all_combinationsbest_combos
## ## 4 4 5 5 5 5 6 6 6 6## 6 6 6 6 8 8 7 7 7 7## 7 7 7 7 9 9 8 8 9 9## 9 9 9 9 13 13 9 9 10 10## 10 10 10 10 14 16 10 10 14 16## 14 16 14 16 18 18 14 16 17 17

Mamy teraz macierz, best_combo, gdzie każda kolumna to zespół. Na przykład widzimy, że zespół typów 4, 6, 7, 9, 10 i 14 obejmuje maksymalną liczbę typów obrońców. Ale co to jest typ 4? Aby odpowiedzieć na to pytanie, weźmiemy nazwy wierszy z super_effective_m i zindeksujemy je przez best_combos.

rownames(super_effective_m)
## "Electric" "Ice" "Fighting" "Ground" "Flying" "Ghost" ## "Electric" "Ice" "Fighting" "Ground" "Flying" "Dark" ## "Grass" "Ice" "Fighting" "Ground" "Flying" "Ghost" ## "Grass" "Ice" "Fighting" "Ground" "Flying" "Dark" ## "Grass" "Poison" "Ground" "Rock" "Ghost" "Fairy" ## "Grass" "Poison" "Ground" "Rock" "Dark" "Fairy" ## "Ice" "Fighting" "Poison" "Ground" "Flying" "Ghost" ## "Ice" "Fighting" "Poison" "Ground" "Flying" "Dark" ## "Ice" "Fighting" "Ground" "Flying" "Ghost" "Steel" ## "Ice" "Fighting" "Ground" "Flying" "Dark" "Steel"

W ten sposób otrzymamy wektor postaci. Jest w porządku, więc wiemy, że pierwsza szóstka to drużyna 1, druga szóstka to drużyna 2 itd, ale nie jest to wyświetlane zbyt dobrze. Możemy użyć matrix aby zamienić to w matrycę, określając, że chcemy 6 rzędów.

strongest_teams <- matrix(rownames(super_effective_m), nrow = 6)
strongest_teams
## ## "Electric" "Electric" "Grass" "Grass" "Grass" "Grass" "Ice" ## "Ice" "Ice" "Ice" "Ice" "Poison" "Poison" "Fighting"## "Fighting" "Fighting" "Fighting" "Fighting" "Ground" "Ground" "Poison" ## "Ground" "Ground" "Ground" "Ground" "Rock" "Rock" "Ground" ## "Flying" "Flying" "Flying" "Flying" "Ghost" "Dark" "Flying" ## "Ghost" "Dark" "Ghost" "Dark" "Fairy" "Fairy" "Ghost" ## ## "Ice" "Ice" "Ice" ## "Fighting" "Fighting" "Fighting"## "Poison" "Ground" "Ground" ## "Ground" "Flying" "Flying" ## "Flying" "Ghost" "Dark" ## "Dark" "Steel" "Steel"

Dla naszego ostatniego kroku, faktycznie zamierzamy zrobić z tego tibble, więc mogę spojrzeć na to, które typy pojawiają się najczęściej w różnych możliwościach zespołu.

strongest_teams %>% as_tibble() %>% gather(team, type) %>% count(type, sort = TRUE) %>% knitr::kable()

.

.

typ n
Ground 10
Fighting 8
Flying 8
Ice 8
Dark 5
Ghost 5
Grass 4
Poison 4
Electric 2
Fairy 2
Rock 2
Steel 2

Widzimy, że wszystkie 10 drużyn potrzebuje typu podłoża, gdzie 8 ma typ Fighting, Flying, lub Ice. Z drugiej strony, Electric, Fairy, Rock i Steel są używane tylko przez dwie drużyny.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *