More work on O'Reilly book

* Make width narrower
* Convert deps to table
* Strip chapter status
This commit is contained in:
Hadley Wickham
2022-11-18 11:05:00 -06:00
parent 5895db09cd
commit 69b4597f3b
33 changed files with 784 additions and 1048 deletions

View File

@@ -1,29 +1,5 @@
<section data-type="chapter" id="chp-rectangling">
<h1><span id="sec-rectangling" class="quarto-section-identifier d-none d-lg-block"><span class="chapter-title">Data rectangling</span></span></h1><div data-type="note"><div class="callout-body d-flex">
<div class="callout-icon-container">
<i class="callout-icon"/>
</div>
</div><h1>
Base R
</h1><p>You are reading the work-in-progress second edition of R for Data Science. This chapter should be readable but is currently undergoing final polishing. You can find the complete first edition at <a href="https://r4ds.had.co.nz" class="uri">https://r4ds.had.co.nz</a>.</p>
<p>Its possible to put a list in a column of a <code>data.frame</code>, but its a lot fiddlier because <code><a href="https://rdrr.io/r/base/data.frame.html">data.frame()</a></code> treats a list as a list of columns:</p><div class="cell">
<pre data-type="programlisting" data-code-language="downlit">data.frame(x = list(1:3, 3:5))
#&gt; x.1.3 x.3.5
#&gt; 1 1 3
#&gt; 2 2 4
#&gt; 3 3 5</pre>
</div><p>You can force <code><a href="https://rdrr.io/r/base/data.frame.html">data.frame()</a></code> to treat a list as a list of rows by wrapping it in list <code><a href="https://rdrr.io/r/base/AsIs.html">I()</a></code>, but the result doesnt print particularly well:</p><div class="cell">
<pre data-type="programlisting" data-code-language="downlit">data.frame(
x = I(list(1:2, 3:5)),
y = c("1, 2", "3, 4, 5")
)
#&gt; x y
#&gt; 1 1, 2 1, 2
#&gt; 2 3, 4, 5 3, 4, 5</pre>
</div><p>Its easier to use list-columns with tibbles because <code><a href="https://tibble.tidyverse.org/reference/tibble.html">tibble()</a></code> treats lists like either vectors and the print method has been designed with lists in mind.</p></div>
<h1><span id="sec-rectangling" class="quarto-section-identifier d-none d-lg-block"><span class="chapter-title">Data rectangling</span></span></h1><p>::: status callout-note You are reading the work-in-progress second edition of R for Data Science. This chapter should be readable but is currently undergoing final polishing. You can find the complete first edition at <a href="https://r4ds.had.co.nz" class="uri">https://r4ds.had.co.nz</a>. :::</p>
<section id="introduction" data-type="sect1">
<h1>
Introduction</h1>
@@ -198,9 +174,7 @@ df
<p>Similarly, if you <code><a href="https://rdrr.io/r/utils/View.html">View()</a></code> a data frame in RStudio, youll get the standard tabular view, which doesnt allow you to selectively expand list columns. To explore those fields youll need to <code><a href="https://dplyr.tidyverse.org/reference/pull.html">pull()</a></code> and view, e.g. <code>df |&gt; pull(z) |&gt; View()</code>.</p>
<div data-type="note"><h1>
Base R
</h1><p>You are reading the work-in-progress second edition of R for Data Science. This chapter should be readable but is currently undergoing final polishing. You can find the complete first edition at <a href="https://r4ds.had.co.nz" class="uri">https://r4ds.had.co.nz</a>.</p>
<p>Its possible to put a list in a column of a <code>data.frame</code>, but its a lot fiddlier because <code><a href="https://rdrr.io/r/base/data.frame.html">data.frame()</a></code> treats a list as a list of columns:</p><div class="cell">
</h1><p>Its possible to put a list in a column of a <code>data.frame</code>, but its a lot fiddlier because <code><a href="https://rdrr.io/r/base/data.frame.html">data.frame()</a></code> treats a list as a list of columns:</p><div class="cell">
<pre data-type="programlisting" data-code-language="downlit">data.frame(x = list(1:3, 3:5))
#&gt; x.1.3 x.3.5
#&gt; 1 1 3
@@ -486,15 +460,15 @@ repos
unnest_longer(json) |&gt;
unnest_wider(json)
#&gt; # A tibble: 176 × 68
#&gt; id name full_…¹ owner private html_…² descr…³ fork url forks…⁴
#&gt; &lt;int&gt; &lt;chr&gt; &lt;chr&gt; &lt;list&gt; &lt;lgl&gt; &lt;chr&gt; &lt;chr&gt; &lt;lgl&gt; &lt;chr&gt; &lt;chr&gt;
#&gt; 1 6.12e7 after gaborc… &lt;named list&gt; FALSE https:… Run Co… FALSE http… https:…
#&gt; 2 4.05e7 argu… gaborc… &lt;named list&gt; FALSE https:… Declar… FALSE http… https:…
#&gt; 3 3.64e7 ask gaborc… &lt;named list&gt; FALSE https:… Friend… FALSE http… https:…
#&gt; 4 3.49e7 base… gaborc… &lt;named list&gt; FALSE https:… Do we … FALSE http… https:…
#&gt; 5 6.16e7 cite… gaborc… &lt;named list&gt; FALSE https:… Test R… TRUE http… https:…
#&gt; 6 3.39e7 clis… gaborc… &lt;named list&gt; FALSE https:… Unicod… FALSE http… https:…
#&gt; # … with 170 more rows, 58 more variables: keys_url &lt;chr&gt;,
#&gt; id name full_…¹ owner private html_…² descr…³ fork url
#&gt; &lt;int&gt; &lt;chr&gt; &lt;chr&gt; &lt;list&gt; &lt;lgl&gt; &lt;chr&gt; &lt;chr&gt; &lt;lgl&gt; &lt;chr&gt;
#&gt; 1 61160198 after gaborc… &lt;named list&gt; FALSE https:… Run Co… FALSE http…
#&gt; 2 40500181 argufy gaborc… &lt;named list&gt; FALSE https:… Declar… FALSE http…
#&gt; 3 36442442 ask gaborc… &lt;named list&gt; FALSE https:… Friend… FALSE http…
#&gt; 4 34924886 baseimpo… gaborc… &lt;named list&gt; FALSE https:… Do we … FALSE http…
#&gt; 5 61620661 citest gaborc… &lt;named list&gt; FALSE https:… Test R… TRUE http…
#&gt; 6 33907457 clisymbo… gaborc… &lt;named list&gt; FALSE https:… Unicod… FALSE http…
#&gt; # … with 170 more rows, 59 more variables: forks_url &lt;chr&gt;, keys_url &lt;chr&gt;,
#&gt; # collaborators_url &lt;chr&gt;, teams_url &lt;chr&gt;, hooks_url &lt;chr&gt;,
#&gt; # issue_events_url &lt;chr&gt;, events_url &lt;chr&gt;, assignees_url &lt;chr&gt;,
#&gt; # branches_url &lt;chr&gt;, tags_url &lt;chr&gt;, blobs_url &lt;chr&gt;, git_tags_url &lt;chr&gt;,
@@ -539,14 +513,14 @@ repos
unnest_wider(json) |&gt;
select(id, full_name, owner, description)
#&gt; # A tibble: 176 × 4
#&gt; id full_name owner description
#&gt; &lt;int&gt; &lt;chr&gt; &lt;list&gt; &lt;chr&gt;
#&gt; 1 61160198 gaborcsardi/after &lt;named list [17]&gt; Run Code in the Background
#&gt; 2 40500181 gaborcsardi/argufy &lt;named list [17]&gt; Declarative function argum
#&gt; 3 36442442 gaborcsardi/ask &lt;named list [17]&gt; Friendly CLI interaction i
#&gt; 4 34924886 gaborcsardi/baseimports &lt;named list [17]&gt; Do we get warnings for und
#&gt; 5 61620661 gaborcsardi/citest &lt;named list [17]&gt; Test R package and repo fo
#&gt; 6 33907457 gaborcsardi/clisymbols &lt;named list [17]&gt; Unicode symbols for CLI ap
#&gt; id full_name owner description
#&gt; &lt;int&gt; &lt;chr&gt; &lt;list&gt; &lt;chr&gt;
#&gt; 1 61160198 gaborcsardi/after &lt;named list [17]&gt; Run Code in the Backgro
#&gt; 2 40500181 gaborcsardi/argufy &lt;named list [17]&gt; Declarative function ar…
#&gt; 3 36442442 gaborcsardi/ask &lt;named list [17]&gt; Friendly CLI interactio…
#&gt; 4 34924886 gaborcsardi/baseimports &lt;named list [17]&gt; Do we get warnings for …
#&gt; 5 61620661 gaborcsardi/citest &lt;named list [17]&gt; Test R package and repo…
#&gt; 6 33907457 gaborcsardi/clisymbols &lt;named list [17]&gt; Unicode symbols for CLI…
#&gt; # … with 170 more rows</pre>
</div>
<p>You can use this to work back to understand how <code>gh_repos</code> was strucured: each child was a GitHub user containing a list of up to 30 GitHub repositories that they created.</p>
@@ -572,21 +546,21 @@ repos
select(id, full_name, owner, description) |&gt;
unnest_wider(owner, names_sep = "_")
#&gt; # A tibble: 176 × 20
#&gt; id full_…¹ owner…² owner…³ owner…⁴ owner…⁵ owner…⁶ owner…⁷ owner…⁸ owner…⁹
#&gt; &lt;int&gt; &lt;chr&gt; &lt;chr&gt; &lt;int&gt; &lt;chr&gt; &lt;chr&gt; &lt;chr&gt; &lt;chr&gt; &lt;chr&gt; &lt;chr&gt;
#&gt; 1 6.12e7 gaborc… gaborc… 660288 https:… "" https:… https:… https:… https:…
#&gt; 2 4.05e7 gaborc… gaborc… 660288 https:… "" https:… https:… https:… https:…
#&gt; 3 3.64e7 gaborc… gaborc… 660288 https:… "" https:… https:… https:… https:…
#&gt; 4 3.49e7 gaborc… gaborc… 660288 https:… "" https:… https:… https:… https:…
#&gt; 5 6.16e7 gaborc… gaborc… 660288 https:… "" https:… https:… https:… https:…
#&gt; 6 3.39e7 gaborc… gaborc… 660288 https:… "" https:… https:… https:… https:…
#&gt; # … with 170 more rows, 10 more variables: owner_gists_url &lt;chr&gt;,
#&gt; # owner_starred_url &lt;chr&gt;, owner_subscriptions_url &lt;chr&gt;,
#&gt; # owner_organizations_url &lt;chr&gt;, owner_repos_url &lt;chr&gt;,
#&gt; # owner_events_url &lt;chr&gt;, owner_received_events_url &lt;chr&gt;, owner_type &lt;chr&gt;,
#&gt; # owner_site_admin &lt;lgl&gt;, description &lt;chr&gt;, and abbreviated variable names
#&gt; # ¹full_name, ²owner_login, ³owner_id, ⁴owner_avatar_url, ⁵owner_gravatar_id,
#&gt; # owner_url, owner_html_url, owner_followers_url, owner_following_url</pre>
#&gt; id full_name owner…¹ owner…² owner…³ owner…⁴ owner…⁵ owner…⁶ owner…⁷
#&gt; &lt;int&gt; &lt;chr&gt; &lt;chr&gt; &lt;int&gt; &lt;chr&gt; &lt;chr&gt; &lt;chr&gt; &lt;chr&gt; &lt;chr&gt;
#&gt; 1 61160198 gaborcsar… gaborc… 660288 https:… "" https:… https:… https:…
#&gt; 2 40500181 gaborcsar… gaborc… 660288 https:… "" https:… https:… https:…
#&gt; 3 36442442 gaborcsar… gaborc… 660288 https:… "" https:… https:… https:…
#&gt; 4 34924886 gaborcsar… gaborc… 660288 https:… "" https:… https:… https:…
#&gt; 5 61620661 gaborcsar… gaborc… 660288 https:… "" https:… https:… https:…
#&gt; 6 33907457 gaborcsar… gaborc… 660288 https:… "" https:… https:… https:…
#&gt; # … with 170 more rows, 11 more variables: owner_following_url &lt;chr&gt;,
#&gt; # owner_gists_url &lt;chr&gt;, owner_starred_url &lt;chr&gt;,
#&gt; # owner_subscriptions_url &lt;chr&gt;, owner_organizations_url &lt;chr&gt;,
#&gt; # owner_repos_url &lt;chr&gt;, owner_events_url &lt;chr&gt;,
#&gt; # owner_received_events_url &lt;chr&gt;, owner_type &lt;chr&gt;,
#&gt; # owner_site_admin &lt;lgl&gt;, description &lt;chr&gt;, and abbreviated variable
#&gt; # names ¹owner_login, ²owner_id, ³owner_avatar_url, owner_gravatar_id, …</pre>
</div>
<p>This gives another wide dataset, but you can see that <code>owner</code> appears to contain a lot of additional data about the person who “owns” the repository.</p>
</section>
@@ -614,14 +588,14 @@ chars
<pre data-type="programlisting" data-code-language="downlit">chars |&gt;
unnest_wider(json)
#&gt; # A tibble: 30 × 18
#&gt; url id name gender culture born died alive titles aliases father
#&gt; &lt;chr&gt; &lt;int&gt; &lt;chr&gt; &lt;chr&gt; &lt;chr&gt; &lt;chr&gt; &lt;chr&gt; &lt;lgl&gt; &lt;list&gt; &lt;list&gt; &lt;chr&gt;
#&gt; 1 https://ww… 1022 Theo… Male "Ironb… "In … "" TRUE &lt;chr&gt; &lt;chr&gt; ""
#&gt; 2 https://ww… 1052 Tyri… Male "" "In … "" TRUE &lt;chr&gt; &lt;chr&gt; ""
#&gt; 3 https://ww… 1074 Vict… Male "Ironb… "In … "" TRUE &lt;chr&gt; &lt;chr&gt; ""
#&gt; 4 https://ww… 1109 Will Male "" "" "In … FALSE &lt;chr&gt; &lt;chr&gt; ""
#&gt; 5 https://ww… 1166 Areo… Male "Norvo… "In … "" TRUE &lt;chr&gt; &lt;chr&gt; ""
#&gt; 6 https://ww… 1267 Chett Male "" "At … "In … FALSE &lt;chr&gt; &lt;chr&gt; ""
#&gt; url id name gender culture born died alive titles aliases father
#&gt; &lt;chr&gt; &lt;int&gt; &lt;chr&gt; &lt;chr&gt; &lt;chr&gt; &lt;chr&gt; &lt;chr&gt; &lt;lgl&gt; &lt;list&gt; &lt;list&gt; &lt;chr&gt;
#&gt; 1 https:/… 1022 Theo… Male "Ironb… "In … "" TRUE &lt;chr&gt; &lt;chr&gt; ""
#&gt; 2 https:/… 1052 Tyri… Male "" "In … "" TRUE &lt;chr&gt; &lt;chr&gt; ""
#&gt; 3 https:/… 1074 Vict… Male "Ironb… "In … "" TRUE &lt;chr&gt; &lt;chr&gt; ""
#&gt; 4 https:/… 1109 Will Male "" "" "In … FALSE &lt;chr&gt; &lt;chr&gt; ""
#&gt; 5 https:/… 1166 Areo… Male "Norvo… "In … "" TRUE &lt;chr&gt; &lt;chr&gt; ""
#&gt; 6 https:/… 1267 Chett Male "" "At … "In … FALSE &lt;chr&gt; &lt;chr&gt; ""
#&gt; # … with 24 more rows, and 7 more variables: mother &lt;chr&gt;, spouse &lt;chr&gt;,
#&gt; # allegiances &lt;list&gt;, books &lt;list&gt;, povBooks &lt;list&gt;, tvSeries &lt;list&gt;,
#&gt; # playedBy &lt;list&gt;</pre>
@@ -633,14 +607,14 @@ chars
select(id, name, gender, culture, born, died, alive)
characters
#&gt; # A tibble: 30 × 7
#&gt; id name gender culture born died alive
#&gt; &lt;int&gt; &lt;chr&gt; &lt;chr&gt; &lt;chr&gt; &lt;chr&gt; &lt;chr&gt; &lt;lgl&gt;
#&gt; 1 1022 Theon Greyjoy Male "Ironborn" "In 278 AC or 279 AC, a… "" TRUE
#&gt; 2 1052 Tyrion Lannister Male "" "In 273 AC, at Casterly… "" TRUE
#&gt; 3 1074 Victarion Greyjoy Male "Ironborn" "In 268 AC or before, a… "" TRUE
#&gt; 4 1109 Will Male "" "" "In … FALSE
#&gt; 5 1166 Areo Hotah Male "Norvoshi" "In 257 AC or before, a… "" TRUE
#&gt; 6 1267 Chett Male "" "At Hag's Mire" "In … FALSE
#&gt; id name gender culture born died alive
#&gt; &lt;int&gt; &lt;chr&gt; &lt;chr&gt; &lt;chr&gt; &lt;chr&gt; &lt;chr&gt; &lt;lgl&gt;
#&gt; 1 1022 Theon Greyjoy Male "Ironborn" "In 278 AC or 279 AC… "" TRUE
#&gt; 2 1052 Tyrion Lannister Male "" "In 273 AC, at Caste… "" TRUE
#&gt; 3 1074 Victarion Greyjoy Male "Ironborn" "In 268 AC or before… "" TRUE
#&gt; 4 1109 Will Male "" "" "In … FALSE
#&gt; 5 1166 Areo Hotah Male "Norvoshi" "In 257 AC or before… "" TRUE
#&gt; 6 1267 Chett Male "" "At Hag's Mire" "In … FALSE
#&gt; # … with 24 more rows</pre>
</div>
<p>There are also many list-columns:</p>
@@ -649,15 +623,15 @@ characters
unnest_wider(json) |&gt;
select(id, where(is.list))
#&gt; # A tibble: 30 × 8
#&gt; id titles aliases allegiances books povBooks tvSeries playedBy
#&gt; &lt;int&gt; &lt;list&gt; &lt;list&gt; &lt;list&gt; &lt;list&gt; &lt;list&gt; &lt;list&gt; &lt;list&gt;
#&gt; 1 1022 &lt;chr [3]&gt; &lt;chr [4]&gt; &lt;chr [1]&gt; &lt;chr [3]&gt; &lt;chr [2]&gt; &lt;chr [6]&gt; &lt;chr [1]&gt;
#&gt; 2 1052 &lt;chr [2]&gt; &lt;chr [11]&gt; &lt;chr [1]&gt; &lt;chr [2]&gt; &lt;chr [4]&gt; &lt;chr [6]&gt; &lt;chr [1]&gt;
#&gt; 3 1074 &lt;chr [2]&gt; &lt;chr [1]&gt; &lt;chr [1]&gt; &lt;chr [3]&gt; &lt;chr [2]&gt; &lt;chr [1]&gt; &lt;chr [1]&gt;
#&gt; 4 1109 &lt;chr [1]&gt; &lt;chr [1]&gt; &lt;NULL&gt; &lt;chr [1]&gt; &lt;chr [1]&gt; &lt;chr [1]&gt; &lt;chr [1]&gt;
#&gt; 5 1166 &lt;chr [1]&gt; &lt;chr [1]&gt; &lt;chr [1]&gt; &lt;chr [3]&gt; &lt;chr [2]&gt; &lt;chr [2]&gt; &lt;chr [1]&gt;
#&gt; 6 1267 &lt;chr [1]&gt; &lt;chr [1]&gt; &lt;NULL&gt; &lt;chr [2]&gt; &lt;chr [1]&gt; &lt;chr [1]&gt; &lt;chr [1]&gt;
#&gt; # … with 24 more rows</pre>
#&gt; id titles aliases allegiances books povBooks tvSeries playe…¹
#&gt; &lt;int&gt; &lt;list&gt; &lt;list&gt; &lt;list&gt; &lt;list&gt; &lt;list&gt; &lt;list&gt; &lt;list&gt;
#&gt; 1 1022 &lt;chr [3]&gt; &lt;chr [4]&gt; &lt;chr [1]&gt; &lt;chr [3]&gt; &lt;chr [2]&gt; &lt;chr&gt; &lt;chr&gt;
#&gt; 2 1052 &lt;chr [2]&gt; &lt;chr [11]&gt; &lt;chr [1]&gt; &lt;chr [2]&gt; &lt;chr [4]&gt; &lt;chr&gt; &lt;chr&gt;
#&gt; 3 1074 &lt;chr [2]&gt; &lt;chr [1]&gt; &lt;chr [1]&gt; &lt;chr [3]&gt; &lt;chr [2]&gt; &lt;chr&gt; &lt;chr&gt;
#&gt; 4 1109 &lt;chr [1]&gt; &lt;chr [1]&gt; &lt;NULL&gt; &lt;chr [1]&gt; &lt;chr [1]&gt; &lt;chr&gt; &lt;chr&gt;
#&gt; 5 1166 &lt;chr [1]&gt; &lt;chr [1]&gt; &lt;chr [1]&gt; &lt;chr [3]&gt; &lt;chr [2]&gt; &lt;chr&gt; &lt;chr&gt;
#&gt; 6 1267 &lt;chr [1]&gt; &lt;chr [1]&gt; &lt;NULL&gt; &lt;chr [2]&gt; &lt;chr [1]&gt; &lt;chr&gt; &lt;chr&gt;
#&gt; # … with 24 more rows, and abbreviated variable name ¹playedBy</pre>
</div>
<p>Lets explore the <code>titles</code> column. Its an unnamed list-column, so well unnest it into rows:</p>
<div class="cell">
@@ -713,14 +687,14 @@ characters |&gt;
select(id, name) |&gt;
inner_join(titles, by = "id", multiple = "all")
#&gt; # A tibble: 53 × 3
#&gt; id name title
#&gt; &lt;int&gt; &lt;chr&gt; &lt;chr&gt;
#&gt; 1 1022 Theon Greyjoy Prince of Winterfell
#&gt; 2 1022 Theon Greyjoy Captain of Sea Bitch
#&gt; 3 1022 Theon Greyjoy Lord of the Iron Islands (by law of the green lands)
#&gt; 4 1052 Tyrion Lannister Acting Hand of the King (former)
#&gt; 5 1052 Tyrion Lannister Master of Coin (former)
#&gt; 6 1074 Victarion Greyjoy Lord Captain of the Iron Fleet
#&gt; id name title
#&gt; &lt;int&gt; &lt;chr&gt; &lt;chr&gt;
#&gt; 1 1022 Theon Greyjoy Prince of Winterfell
#&gt; 2 1022 Theon Greyjoy Captain of Sea Bitch
#&gt; 3 1022 Theon Greyjoy Lord of the Iron Islands (by law of the green land
#&gt; 4 1052 Tyrion Lannister Acting Hand of the King (former)
#&gt; 5 1052 Tyrion Lannister Master of Coin (former)
#&gt; 6 1074 Victarion Greyjoy Lord Captain of the Iron Fleet
#&gt; # … with 47 more rows</pre>
</div>
<p>You could imagine creating a table like this for each of the list-columns, then using joins to combine them with the character data as you need it.</p>
@@ -855,15 +829,15 @@ Deeply nested</h2>
unnest_wider(results)
locations
#&gt; # A tibble: 7 × 6
#&gt; city address_components formatted_address geometry place_id types
#&gt; &lt;chr&gt; &lt;list&gt; &lt;chr&gt; &lt;list&gt; &lt;chr&gt; &lt;list&gt;
#&gt; 1 Houston &lt;list [4]&gt; Houston, TX, USA &lt;named list&gt; ChIJAYW&lt;list&gt;
#&gt; 2 Washington &lt;list [2]&gt; Washington, USA &lt;named list&gt; ChIJ-bD&lt;list&gt;
#&gt; 3 Washington &lt;list [4]&gt; Washington, DC, USA &lt;named list&gt; ChIJW-T&lt;list&gt;
#&gt; 4 New York &lt;list [3]&gt; New York, NY, USA &lt;named list&gt; ChIJOwg&lt;list&gt;
#&gt; 5 Chicago &lt;list [4]&gt; Chicago, IL, USA &lt;named list&gt; ChIJ7cv&lt;list&gt;
#&gt; 6 Arlington &lt;list [4]&gt; Arlington, TX, USA &lt;named list&gt; ChIJ05g&lt;list&gt;
#&gt; # … with 1 more row</pre>
#&gt; city address_components formatted_address geometry place…¹ types
#&gt; &lt;chr&gt; &lt;list&gt; &lt;chr&gt; &lt;list&gt; &lt;chr&gt; &lt;list&gt;
#&gt; 1 Houston &lt;list [4]&gt; Houston, TX, USA &lt;named list&gt; ChIJAY… &lt;list&gt;
#&gt; 2 Washington &lt;list [2]&gt; Washington, USA &lt;named list&gt; ChIJ-b… &lt;list&gt;
#&gt; 3 Washington &lt;list [4]&gt; Washington, DC, &lt;named list&gt; ChIJW-… &lt;list&gt;
#&gt; 4 New York &lt;list [3]&gt; New York, NY, USA &lt;named list&gt; ChIJOw… &lt;list&gt;
#&gt; 5 Chicago &lt;list [4]&gt; Chicago, IL, USA &lt;named list&gt; ChIJ7c… &lt;list&gt;
#&gt; 6 Arlington &lt;list [4]&gt; Arlington, TX, U &lt;named list&gt; ChIJ05… &lt;list&gt;
#&gt; # … with 1 more row, and abbreviated variable name ¹place_id</pre>
</div>
<p>Now we can see why two cities got two results: Washington matched both Washington state and Washington, DC, and Arlington matched Arlington, Virginia and Arlington, Texas.</p>
<p>There are few different places we could go from here. We might want to determine the exact location of the match, which is stored in the <code>geometry</code> list-column:</p>
@@ -872,14 +846,14 @@ locations
select(city, formatted_address, geometry) |&gt;
unnest_wider(geometry)
#&gt; # A tibble: 7 × 6
#&gt; city formatted_address bounds location locati…¹ viewport
#&gt; &lt;chr&gt; &lt;chr&gt; &lt;list&gt; &lt;list&gt; &lt;chr&gt; &lt;list&gt;
#&gt; 1 Houston Houston, TX, USA &lt;named list&gt; &lt;named list&gt; APPROXI&lt;named list&gt;
#&gt; 2 Washington Washington, USA &lt;named list&gt; &lt;named list&gt; APPROXI&lt;named list&gt;
#&gt; 3 Washington Washington, DC, USA &lt;named list&gt; &lt;named list&gt; APPROXI&lt;named list&gt;
#&gt; 4 New York New York, NY, USA &lt;named list&gt; &lt;named list&gt; APPROXI&lt;named list&gt;
#&gt; 5 Chicago Chicago, IL, USA &lt;named list&gt; &lt;named list&gt; APPROXI&lt;named list&gt;
#&gt; 6 Arlington Arlington, TX, USA &lt;named list&gt; &lt;named list&gt; APPROXI&lt;named list&gt;
#&gt; city formatted_address bounds location locat…¹ viewport
#&gt; &lt;chr&gt; &lt;chr&gt; &lt;list&gt; &lt;list&gt; &lt;chr&gt; &lt;list&gt;
#&gt; 1 Houston Houston, TX, USA &lt;named list&gt; &lt;named list&gt; APPROX… &lt;named list&gt;
#&gt; 2 Washington Washington, USA &lt;named list&gt; &lt;named list&gt; APPROX… &lt;named list&gt;
#&gt; 3 Washington Washington, DC, &lt;named list&gt; &lt;named list&gt; APPROX… &lt;named list&gt;
#&gt; 4 New York New York, NY, USA &lt;named list&gt; &lt;named list&gt; APPROX… &lt;named list&gt;
#&gt; 5 Chicago Chicago, IL, USA &lt;named list&gt; &lt;named list&gt; APPROX… &lt;named list&gt;
#&gt; 6 Arlington Arlington, TX, U &lt;named list&gt; &lt;named list&gt; APPROX… &lt;named list&gt;
#&gt; # … with 1 more row, and abbreviated variable name ¹location_type</pre>
</div>
<p>That gives us new <code>bounds</code> (a rectangular region) and <code>location</code> (a point). We can unnest <code>location</code> to see the latitude (<code>lat</code>) and longitude (<code>lng</code>):</p>
@@ -889,14 +863,14 @@ locations
unnest_wider(geometry) |&gt;
unnest_wider(location)
#&gt; # A tibble: 7 × 7
#&gt; city formatted_address bounds lat lng locati…¹ viewport
#&gt; &lt;chr&gt; &lt;chr&gt; &lt;list&gt; &lt;dbl&gt; &lt;dbl&gt; &lt;chr&gt; &lt;list&gt;
#&gt; 1 Houston Houston, TX, USA &lt;named list&gt; 29.8 -95.4 APPROXI&lt;named list&gt;
#&gt; 2 Washington Washington, USA &lt;named list&gt; 47.8 -121. APPROXI&lt;named list&gt;
#&gt; 3 Washington Washington, DC, USA &lt;named list&gt; 38.9 -77.0 APPROXI&lt;named list&gt;
#&gt; 4 New York New York, NY, USA &lt;named list&gt; 40.7 -74.0 APPROXI&lt;named list&gt;
#&gt; 5 Chicago Chicago, IL, USA &lt;named list&gt; 41.9 -87.6 APPROXI&lt;named list&gt;
#&gt; 6 Arlington Arlington, TX, USA &lt;named list&gt; 32.7 -97.1 APPROXI&lt;named list&gt;
#&gt; city formatted_address bounds lat lng locat…¹ viewport
#&gt; &lt;chr&gt; &lt;chr&gt; &lt;list&gt; &lt;dbl&gt; &lt;dbl&gt; &lt;chr&gt; &lt;list&gt;
#&gt; 1 Houston Houston, TX, USA &lt;named list&gt; 29.8 -95.4 APPROX… &lt;named list&gt;
#&gt; 2 Washington Washington, USA &lt;named list&gt; 47.8 -121. APPROX… &lt;named list&gt;
#&gt; 3 Washington Washington, DC, &lt;named list&gt; 38.9 -77.0 APPROX… &lt;named list&gt;
#&gt; 4 New York New York, NY, USA &lt;named list&gt; 40.7 -74.0 APPROX… &lt;named list&gt;
#&gt; 5 Chicago Chicago, IL, USA &lt;named list&gt; 41.9 -87.6 APPROX… &lt;named list&gt;
#&gt; 6 Arlington Arlington, TX, U &lt;named list&gt; 32.7 -97.1 APPROX… &lt;named list&gt;
#&gt; # … with 1 more row, and abbreviated variable name ¹location_type</pre>
</div>
<p>Extracting the bounds requires a few more steps:</p>