<p><div><div><div><div data-show-faces="false" data-height="21" data-width="100" data-layout="button_count" data-send="true" data-href="https://www.r-bloggers.com/gotr-r-wrapper-for-an-api-of-ice-and-fire/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="https://www.mango-solutions.com/blog/gotr-r-wrapper-for-an-api-of-ice-and-fire"> Mango Solutions</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<p> <img sizes="100vw" src="https://i2.wp.com/www.mango-solutions.com/blog/images/c/6/6/6/d/c666d98c123bc3e523a4d2e57ce1389cf7b6e44b-gotr-post-header.png?w=456&ssl=1" data-recalc-dims="1"></p>
<h4><em>Ava Yang</em></h4>
<p>It’s Game of Thrones time again as the battle for Westeros is heating up. There are tons of ideas, ingredients and interesting analyses out there and I was craving for my own flavour. So step zero, where is the data?</p>
<p>Jenny Bryan’s <a rel="nofollow" href="https://jennybc.github.io/purrr-tutorial/ls00_inspect-explore.html" target="_blank">purrr tutorial</a> introduced the list <strong>got_chars</strong>, representing characters information from the first five books, which seems not much fun beyond exercising list manipulation muscle. However, it led me to an <a rel="nofollow" href="https://anapioficeandfire.com/" target="_blank">API of Ice and Fire</a>, the world’s greatest source for quantified and structured data from the universe of Ice and Fire including the HBO series Game of Thrones. I decided to create my own API functions, or better, an R package (inspired by the famous rwar package).</p>
<p>The API resources cover 3 types of endpoint – Books, Characters and Houses. <code>GoTr</code> pulls data in JSON format and parses them to R list objects. <code>httr</code>’s <a rel="nofollow" href="https://cran.r-project.org/web/packages/httr/vignettes/api-packages.html" target="_blank">Best practices for writing an API package</a> by Hadley Wickham is another life saver.</p>
<p>The package contains: – One function <code>got_api()</code> – Two ways to specify parameters generally, i.e. endpoint <strong>type</strong> + <strong>id</strong> or <strong>url</strong> – Three endpoint types</p>
<pre><code>## Install GoTr from github
#devtools::install_github(&quot;MangoTheCat/GoTr&quot;)
library(GoTr)
library(tidyverse)
library(listviewer)

# Retrieve books id 5
books_5 &lt;- got_api(type = &quot;books&quot;, id = 5)
# Retrieve characters id 583
characters_583 &lt;- got_api(type = &quot;characters&quot;, id = 583)
# Retrieve houses id 378
house_378 &lt;- got_api(type = &quot;houses&quot;, id = 378)
# Retrieve pov characters data in book 5
povData &lt;- books_5$povCharacters %>% 
  flatten_chr() %>%
  map(function(x) got_api(url = x))</code></pre>
<pre><code># Helpful functions to check structure of list object
length(books_5)
## [1] 11
names(books_5)
##  [1] &quot;url&quot;           &quot;name&quot;          &quot;isbn&quot;          &quot;authors&quot;      
##  [5] &quot;numberOfPages&quot; &quot;publisher&quot;     &quot;country&quot;       &quot;mediaType&quot;    
##  [9] &quot;released&quot;      &quot;characters&quot;    &quot;povCharacters&quot;
names(house_378)
##  [1] &quot;url&quot;              &quot;name&quot;             &quot;region&quot;          
##  [4] &quot;coatOfArms&quot;       &quot;words&quot;            &quot;titles&quot;          
##  [7] &quot;seats&quot;            &quot;currentLord&quot;      &quot;heir&quot;            
## [10] &quot;overlord&quot;         &quot;founded&quot;          &quot;founder&quot;         
## [13] &quot;diedOut&quot;          &quot;ancestralWeapons&quot; &quot;cadetBranches&quot;   
## [16] &quot;swornMembers&quot;
str(characters_583, max.level = 1)
## List of 16
##  $ url        : chr &quot;https://anapioficeandfire.com/api/characters/583&quot;
##  $ name       : chr &quot;Jon Snow&quot;
##  $ gender     : chr &quot;Male&quot;
##  $ culture    : chr &quot;Northmen&quot;
##  $ born       : chr &quot;In 283 AC&quot;
##  $ died       : chr &quot;&quot;
##  $ titles     :List of 1
##  $ aliases    :List of 8
##  $ father     : chr &quot;&quot;
##  $ mother     : chr &quot;&quot;
##  $ spouse     : chr &quot;&quot;
##  $ allegiances:List of 1
##  $ books      :List of 1
##  $ povBooks   :List of 4
##  $ tvSeries   :List of 6
##  $ playedBy   :List of 1
map_chr(povData, &quot;name&quot;)
##  [1] &quot;Aeron Greyjoy&quot;     &quot;Arianne Martell&quot;   &quot;Arya Stark&quot;       
##  [4] &quot;Arys Oakheart&quot;     &quot;Asha Greyjoy&quot;      &quot;Brienne of Tarth&quot; 
##  [7] &quot;Cersei Lannister&quot;  &quot;Jaime Lannister&quot;   &quot;Samwell Tarly&quot;    
## [10] &quot;Sansa Stark&quot;       &quot;Victarion Greyjoy&quot; &quot;Areo Hotah&quot;
#listviewer::jsonedit(povData)</code></pre>
<p>Another powerful parameter is <strong>query</strong> which allows filtering by specific attribute such as the name of a character, pagination and so on.</p>
<p>It’s worth knowing about pagination. The first simple request will render a list of 10 elements, since the default number of items per page is 10. The maximum valid <strong>pageSize</strong> is 50, i.e. if 567 is passed on to it, you still get 50 characters.</p>
<pre><code># Retrieve character by name
Arya_Stark &lt;- got_api(type = &quot;characters&quot;, query = list(name = &quot;Arya Stark&quot;))
# Retrieve characters on page 3, change page size to 20. 
characters_page_3 &lt;- got_api(type = &quot;characters&quot;, query = list(page = &quot;3&quot;, pageSize=&quot;20&quot;))</code></pre>
<p>So how do we get ALL books, characters or houses information? The package does not provide the function directly but here’s an implementation.</p>
<pre><code># Retrieve all books
booksAll &lt;- got_api(type = &quot;books&quot;, query = list(pageSize=&quot;20&quot;))
# Extract names of all books
map_chr(booksAll, &quot;name&quot;)</code></pre>
<pre><code>##  [1] &quot;A Game of Thrones&quot;              &quot;A Clash of Kings&quot;              
##  [3] &quot;A Storm of Swords&quot;              &quot;The Hedge Knight&quot;              
##  [5] &quot;A Feast for Crows&quot;              &quot;The Sworn Sword&quot;               
##  [7] &quot;The Mystery Knight&quot;             &quot;A Dance with Dragons&quot;          
##  [9] &quot;The Princess and the Queen&quot;     &quot;The Rogue Prince&quot;              
## [11] &quot;The World of Ice and Fire&quot;      &quot;A Knight of the Seven Kingdoms&quot;</code></pre>
<pre><code># Retrieve all houses
houses &lt;- 1:9 %>% 
  map(function(x) got_api(type = &quot;houses&quot;, query = list(page=x, pageSize=&quot;50&quot;))) %>%
  unlist(recursive=FALSE)</code></pre>
<pre><code>map_chr(houses, &quot;name&quot;) %>% length()
## [1] 444
map_df(houses, `[`, c(&quot;name&quot;, &quot;region&quot;)) %>% head()
## # A tibble: 6 x 2
##                          name          region
##                         </code></pre>