Käivitame sissekehravad veerud - loendid R keeles (pakett tidyr ja unnest funktsioonide pere)

Enamikul juhtudel, kui töötate API-lt saadud vastustega või muude keerukate puustruktuuriga andmetega, kohtate JSON- ja XML-formaate.

Neil formaatidel on palju eeliseid: need salvestavad andmeid kompaktselt ja aitavad vältida liigset teabe dubleerimist.

Nende formaatide miinus on keerukus nende töötlemisel ja analüüsimisel. Struktuureerimata andmeid ei saa kasutada arvutustes ja nende põhjal visualiseerimist luua.

Käivitame sissekehravad veerud - loendid R keeles (pakett tidyr ja unnest funktsioonide pere)

See artikkel on loogiline jätk avaldamisele "R-pakett tidyr ja selle uued funktsioonid pivot_longer ja pivot_wider". See aitab teil tuua struktuureerimata andmekonstruktsioonid tuttavasse ja analüüsiks sobivasse tabelisse, kasutades paketti tidyr, mis kuulub tidyversetuumiku alla, ning selle funktsioonide seeriat unnest_*().

Sisukord

Kui teid huvitab andmeanalüüs, võivad teid huvitada minu telegram ja youtube kanalid, millel on suur osa sisu R keelele.

  1. Sissejuhatus
  2. GitHubi kasutajad
  3. GitHubi repositooriumid
  4. Game of Thrones tegelased
  5. Geokodeerimine Google'i kaudu
  6. Sharli Gelfandi diskograafia
  7. Kokkuvõte

Sissejuhatus

Rectangling (tõlkija märkus, ei leidnud adekvaatset tõlget, seega jätame selle nii nagu on.) — see on protsess, millega viidakse struktuureerimata andmed, mis sisaldavad sisemisi massiive, kahe mõõtmelisse tabelisse, mis koosneb tuttavatest ridadest ja veergudest. V tidyr on mitmeid funktsioone, mis aitavad teil avada sisemisi loendi veerge ja tuua andmed nelinurkse, tabeli vormi:

  • unnest_longer() võtab iga loendi veeru elemendi ja loob uue rea.
  • unnest_wider() võtab iga loendi veeru elemendi ja loob uue veeru.
  • unnest_auto() moodustab automaatselt, millist funktsiooni on kõige parem kasutada.
    unnest_longer() või unnest_wider().
  • hoist() on sarnane unnest_wider() aga valib ainult spetsiifilised komponendid ja võimaldab töötada mitme sisaldustaseme tasemega.

Enamik probleeme, mis on seotud struktuureerimata andmete viimisega kahe mõõtmelisse tabelisse mitme sisaldustaseme korral, saab lahendada, kombineerides eespool mainitud funktsioone dplyr-iga.

Selle tehnika demonstreerimiseks kasutame paketti repurrrsive, mis pakub mitmeid keerulisi, mitmetasandilisi loendeid, mis on saadud veebiteenustest.

library(tidyr)
library(dplyr)
library(repurrrsive)

GitHubi kasutajad

Alustame gh_users, loend, mis sisaldab teavet kuue GitHubi kasutaja kohta. Alustame loendi transformeerimist gh_users ja tibble raamiks:

users <- tibble( user = gh_users ) 

See tundub veidi loogikaväline: miks tuua nimekiri gh_users, keerukamasse andmestruktuuri? Kuid andmeraamistikul on suur eelis: see ühendab mitu vektorit, nii et kõik jälgitakse ühes objektis.

Iga objekti element users on nimetatud nimekiri, kus iga element esindab veergu.

names(users$user[[1]])
#>  [1] "login"               "id"                  "avatar_url"         
#>  [4] "gravatar_id"         "url"                 "html_url"           
#>  [7] "followers_url"       "following_url"       "gists_url"          
#> [10] "starred_url"         "subscriptions_url"   "organizations_url"  
#> [13] "repos_url"           "events_url"          "received_events_url"
#> [16] "type"                "site_admin"          "name"               
#> [19] "company"             "blog"                "location"           
#> [22] "email"               "hireable"            "bio"                
#> [25] "public_repos"        "public_gists"        "followers"          
#> [28] "following"           "created_at"          "updated_at"

On kaks viisi loetelu komponente veergudeks muuta. unnest_wider() võtab iga komponendi ja loob uue veeru:

users %>% unnest_wider(user)
#> # A tibble: 6 x 30
#>   login     id avatar_url gravatar_id url   html_url followers_url
#>   <chr>  <int> <chr>      <chr>       <chr> <chr>    <chr>        
#> 1 gabo… 6.60e5 https://a… ""          http… https:… https://api.…
#> 2 jenn… 5.99e5 https://a… ""          http… https:… https://api.…
#> 3 jtle… 1.57e6 https://a… ""          http… https:… https://api.…
#> 4 juli… 1.25e7 https://a… ""          http… https:… https://api.…
#> 5 leep… 3.51e6 https://a… ""          http… https:… https://api.…
#> 6 masa… 8.36e6 https://a… ""          http… https:… https://api.…
#> # … 23 rohkem muutujat: following_url <chr>, gists_url <chr>,
#> #   starred_url <chr>, subscriptions_url <chr>, organizations_url <chr>,
#> #   repos_url <chr>, events_url <chr>, received_events_url <chr>,
#> #   type <chr>, site_admin <lgl>, name <chr>, company <chr>, blog <chr>,
#> #   location <chr>, email <chr>, public_repos <int>, public_gists <int>,
#> #   followers <int>, following <int>, created_at <chr>, updated_at <chr>,
#> #   bio <chr>, hireable <lgl>

Selles olukorras saime tabeli, mis koosneb 30 veerust, ja enamik neist pole meile vajalikud, seega saame selle asemel unnest_wider() kasutama hoist(). hoist() võimaldab meil valida soovitud komponente, kasutades sama süntaksit, mis purrr::pluck():

kasutajad %>% hoist(user, 
  followers = "followers", 
  login = "login", 
  url = "html_url"
)
#> # Tibble: 6 x 4
#>   followers login       url                            user             
#>       <int> <chr>       <chr>                          <list>           
#> 1       303 gaborcsardi https://github.com/gaborcsardi <nimetud loend [27]>
#> 2       780 jennybc     https://github.com/jennybc     <nimetud loend [27]>
#> 3      3958 jtleek      https://github.com/jtleek      <nimetud loend [27]>
#> 4       115 juliasilge  https://github.com/juliasilge  <nimetud loend [27]>
#> 5       213 leeper      https://github.com/leeper      <nimetud loend [27]>
#> 6        34 masalmon    https://github.com/masalmon    <nimetud loend [27]>

hoist() eemaldab loendist veerud, mille nimed on määratud kasutaja, seega võite pidada hoist() sisemiste loendite elementide liigutamiseks andmepaketi ülevalt tasemele.

GitHubi repositooriumid

Loendite joondamine gh_repos alustame sarnasel viisil, muutes selle tibble:

repos <- tibble(repo = gh_repos)
repos
#> # Tibble: 6 x 1
#>   repo       
#>   <list>     
#> 1 <loend [30]>
#> 2 <loend [30]>
#> 3 <loend [30]>
#> 4 <loend [26]>
#> 5 <loend [30]>
#> 6 <loend [30]>

Seekord on elemendid kasutaja esindavad selle kasutaja kuuluvate repodega loendit. Iga reposte on eraldi vaatlus, seega vastavalt korralike andmete kontseptsioonile (nt. korralikud andmed) peavad nad muutuma uuteks ridadeks, seetõttu kasutame unnest_longer() ja mitte unnest_wider():

repos <- repos %>% unnest_longer(repo)
repos
#> # Tibble: 176 x 1
#>    repo             
#>    <list>           
#>  1 <nimetud loend [68]>
#>  2 <nimetud loend [68]>
#>  3 <nimetud loend [68]>
#>  4 <nimetud loend [68]>
#>  5 <nimetud loend [68]>
#>  6 <nimetud loend [68]>
#>  7 <nimetud loend [68]>
#>  8 <nimetud loend [68]>
#>  9 <nimetud loend [68]>
#> 10 <nimetud loend [68]>
#> # … 166 rida veel

Nüüd saame kasutada unnest_wider() või hoist() :

repos %>% hoist(repo, 
  login = c("owner", "login"), 
  name = "name",
  homepage = "homepage",
  watchers = "watchers_count"
)
#> # Tibble: 176 x 5
#>    login       name        homepage watchers repo             
#>    <chr>       <chr>       <chr>       <int> <list>           
#>  1 gaborcsardi after       <NA>            5 <nimetud loend [65]>
#>  2 gaborcsardi argufy      <NA>           19 <nimetud loend [65]>
#>  3 gaborcsardi ask         <NA>            5 <nimetud loend [65]>
#>  4 gaborcsardi baseimports <NA>            0 <nimetud loend [65]>
#>  5 gaborcsardi citest      <NA>            0 <nimetud loend [65]>
#>  6 gaborcsardi clisymbols  ""             18 <nimetud loend [65]>
#>  7 gaborcsardi cmaker      <NA>            0 <nimetud loend [65]>
#>  8 gaborcsardi cmark       <NA>            0 <nimetud loend [65]>
#>  9 gaborcsardi conditions  <NA>            0 <nimetud loend [65]>
#> 10 gaborcsardi crayon      <NA>           52 <nimetud loend [65]>
#> # … 166 rida veel

Pöörake tähelepanu kasutamisele c("owner", "login"): see võimaldab meil saada teise taseme väärtust sissetungitud loendist omanikAlternatiivne lähenemine on esmalt saada kogu nimekiri omanik ja seejärel kasutada funktsiooni unnest_wider() et paigutada iga selle element veergu:

repos %>% 
  hoist(repo, owner = "owner") %>% 
  unnest_wider(owner)
#> # A tibble: 176 x 18
#>    login     id avatar_url gravatar_id url   html_url followers_url
#>                                 
#>  1 gabo… 660288 https://a… ""          http… https:… https://api.…
#>  2 gabo… 660288 https://a… ""          http… https:… https://api.…
#>  3 gabo… 660288 https://a… ""          http… https:… https://api.…
#>  4 gabo… 660288 https://a… ""          http… https:… https://api.…
#>  5 gabo… 660288 https://a… ""          http… https:… https://api.…
#>  6 gabo… 660288 https://a… ""          http… https:… https://api.…
#>  7 gabo… 660288 https://a… ""          http… https:… https://api.…
#>  8 gabo… 660288 https://a… ""          http… https:… https://api.…
#>  9 gabo… 660288 https://a… ""          http… https:… https://api.…
#> 10 gabo… 660288 https://a… ""          http… https:… https://api.…
#> # … koos 166 rohkem rida ja 11 rohkem muutuja: following_url ,
#> #   gists_url , starred_url , subscriptions_url ,
#> #   organizations_url , repos_url , events_url ,
#> #   received_events_url , type , site_admin , repo

Kohapeal selle asemel, et mõelda vajaliku funktsiooni valimisele unnest_longer() või unnest_wider() saate kasutada unnest_auto(). See funktsioon kasutab mitmeid heuristilisi meetodeid, et leida kõige sobivam funktsioon andmete transformeerimiseks ja annab teate valitud meetodi kohta.

tibble(repo = gh_repos) %>% 
  unnest_auto(repo) %>% 
  unnest_auto(repo)
#> Kasutame `unnest_longer(repo)`; ühelgi elemendil ei ole nimesid
#> Kasutame `unnest_wider(repo)`; elementidel on 68 nime ühiselt
#> # Tibble: 176 x 67
#>        id nimi  täis_nimi omanik privaatne html_url kirjeldus fork  url  
#>                            
#>  1 6.12e7 pärast gaborcsa…   2 4.05e7 argu… gaborcsa…   3 3.64e7 küsige   gaborcsa…   4 3.49e7 baas… gaborcsa…   5 6.16e7 tsiteeri… gaborcsa…   6 3.39e7 clis… gaborcsa…   7 3.72e7 cmak… gaborcsa…   8 6.80e7 cmark gaborcsa…   9 6.32e7 cond… gaborcsa… <nam… FALSE   https:…         TRUE  http…
#> 10 2.43e7 cray… gaborcsa…  # … veel 166 rida ja 58 rohkem muutujaid: forks_url ,
#> #   keys_url , collaborators_url , teams_url ,
#> #   hooks_url , issue_events_url , events_url ,
#> #   assignees_url , branches_url , tags_url ,
#> #   blobs_url , git_tags_url , git_refs_url ,
#> #   trees_url , statuses_url , languages_url ,
#> #   stargazers_url , contributors_url , subscribers_url ,
#> #   subscription_url , commits_url , git_commits_url ,
#> #   comments_url , issue_comment_url , contents_url ,
#> #   compare_url , merges_url , archive_url ,
#> #   downloads_url , issues_url , pulls_url ,
#> #   milestones_url , notifications_url , labels_url ,
#> #   releases_url , deployments_url , created_at ,
#> #   updated_at , pushed_at , git_url , ssh_url ,
#> #   clone_url , svn_url , size , stargazers_count ,
#> #   watchers_count , keel , has_issues ,
#> #   has_downloads , has_wiki , has_pages ,
#> #   forks_count , open_issues_count , forks ,
#> #   open_issues , watchers , vaikimisi_haru ,
#> #   kodu_leht

Game of Thrones tegelased

saamiskarakterid on sama struktuuriga nagu gh_users: see on nimetatud loendite kogum, kus iga sisemise loendi element kirjeldab mõnda atribuutis mängust "Troonide mäng". Koonde toomine saamiskarakterid tabelivormingusse, alustame andframe'i loomisega, nagu varem esitatud näidetes, ja seejärel teisendame iga elemendi eraldi veeruks:

chars  # A tibble: 30 x 1
#>    char             
#>               
#>  1 
#>  2 
#>  3 
#>  4 
#>  5 
#>  6 
#>  7 
#>  8 
#>  9 
#> 10 
#> # … with 20 more rows

chars2 % unnest_wider(char)
chars2
#> # A tibble: 30 x 18
#>    url      id name  gender culture born  died  alive titles aliases father
#>     <int> <chr> <chr>  <chr>   <chr> <chr> <lgl> <list> <list>  <chr> 
#>  1 http…  1022 Theo… Male   Ironbo… In 2… ""    TRUE  <chr …   2 http…  1052 Tyri… Male   ""      In 2… ""    TRUE  <chr …   3 http…  1074 Vict… Male   Ironbo… In 2… ""    TRUE  <chr …   4 http…  1109 Will  Male   ""      ""    In 2… FALSE <chr …   5 http…  1166 Areo… Male   Norvos… In 2… ""    TRUE  <chr …   6 http…  1267 Chett Male   ""      At H… In 2… FALSE <chr …   7 http…  1295 Cres… Male   ""      In 2… In 2… FALSE <chr …   8 http…   130 Aria… Female Dornish In 2… ""    TRUE  <chr …   9 http…  1303 Daen… Female Valyri… In 2… ""    TRUE  <chr …  10 http…  1319 Davo… Male   Wester… In 2… ""    TRUE  <chr …  # … with 20 more rows, and 7 more variables: mother <chr>, spouse  #   allegiances <list>, books <list>, povBooks <list>, tvSeries  #   playedBy <list>

Struktuur saamiskarakterid natuke keerulisem, kui gh_users, kuna mõned loendi komponendid char omaette on loendid, mille tulemusena saame veerud — loendid:

chars2 %>% select_if(is.list)
#> # A tibble: 30 x 7
#>    titles    aliases    allegiances books     povBooks  tvSeries  playedBy 
#>                                  
#>  1          
#>  2         
#>  3          
#>  4    <???>          
#>  5          
#>  6    <???>          
#>  7    <???>          
#>  8          
#>  9         
#> 10          
#> # … with 20 more rows

Teie edasised tegevused sõltuvad analüüsi eesmärkidest. Võib-olla peate ridadele märkima teavet iga raamatu ja seriaali kohta, kus tegelane esineb:

chars2 %>% 
  select(name, books, tvSeries) %>% 
  pivot_longer(c(books, tvSeries), names_to = "media", values_to = "value") %>% 
  unnest_longer(value)
#> # A tibble: 180 x 3
#>    name             media    value            
#>                                
#>  1 Theon Greyjoy    books    A Game of Thrones
#>  2 Theon Greyjoy    books    A Storm of Swords
#>  3 Theon Greyjoy    books    A Feast for Crows
#>  4 Theon Greyjoy    tvSeries Season 1         
#>  5 Theon Greyjoy    tvSeries Season 2         
#>  6 Theon Greyjoy    tvSeries Season 3         
#>  7 Theon Greyjoy    tvSeries Season 4         
#>  8 Theon Greyjoy    tvSeries Season 5         
#>  9 Theon Greyjoy    tvSeries Season 6         
#> 10 Tyrion Lannister books    A Feast for Crows
#> # … with 170 more rows

Või soovite võib-olla luua tabeli, mis võimaldab teil siduda tegelase ja teose:

chars2 %>% 
  select(name, title = titles) %>% 
  unnest_longer(title)
#> # A tibble: 60 x 2
#>    name              title                                               
#>                                                                
#>  1 Theon Greyjoy     Prince of Winterfell                                
#>  2 Theon Greyjoy     Captain of Sea Bitch                                
#>  3 Theon Greyjoy     Lord of the Iron Islands (by law of the green lands)
#>  4 Tyrion Lannister  Acting Hand of the King (former)                    
#>  5 Tyrion Lannister  Master of Coin (former)                             
#>  6 Victarion Greyjoy Lord Captain of the Iron Fleet                      
#>  7 Victarion Greyjoy Master of the Iron Victory                          
#>  8 Will              ""                                                  
#>  9 Areo Hotah        Captain of the Guard at Sunspear                    
#> 10 Chett             ""                                                  
#> # … with 50 more rows

(Pange tähele, et tühjad väärtused "" väljal title, see on seotud andmete sisestamisel tehtud vigadega saamiskarakterid: tegelikult peaksid tegelased, kellel pole vastavaid raamatute ja sarjade pealkirju, olema title vektor, mille pikkus on 0, mitte vektor, mille pikkus on 1 ja mis sisaldab tühja rida.)

Saame ülaltoodud näite ümber kirjutada, kasutades funktsiooni unnest_auto(). See lähenemine on mugav ühekordseks analüüsiks, kuid ei tohiks tugineda unnest_auto() püsivalt kasutamiseks. Asi on selles, et kui teie andmestruktuur muutub, unnest_auto() võib vahetuda valitud andmete teisendamise mehhanism, kui algselt töötas see välja loendite veerge ridadeks, kasutades unnest_longer(), siis andmete sisendi struktuuri muutmisel võib loogika muutuda ja eelistada unnest_wider(), ning sellise lähenemise pidev kasutamine võib põhjustada ettenägematuid vigu.

tibble(char = got_chars) %>% 
  unnest_auto(char) %>% 
  select(name, title = titles) %>% 
  unnest_auto(title)
#> Kasutades `unnest_wider(char)`; elementidel on 18 ühist nime
#> Kasutades `unnest_longer(title)`; ühelgi elemendil ei ole nimesid
#> # Tabel: 60 x 2
#>    name              title                                               
#>                                                                
#>  1 Theon Greyjoy     Winterfelli prints                                  
#>  2 Theon Greyjoy     Meremees Bitch                                    
#>  3 Theon Greyjoy     Rauasaare isand (roheliste maade seaduse järgi)  
#>  4 Tyrion Lannister  Asekuningas (endine)                              
#>  5 Tyrion Lannister  Rahanduse meister (endine)                        
#>  6 Victarion Greyjoy Raualaeva admiral                               
#>  7 Victarion Greyjoy Rauavõidu meister                               
#>  8 Will              ""                                                  
#>  9 Areo Hotah        Sunspeari guardaadmiral                           
#> 10 Chett             ""                                                  
#> # … veel 50 rida

Geokodeerimine Google'i kaudu

Jätkame keerukamate andmestruktuuride arutamist, mida saame Google'i geokodeerimise teenusest. Google Maps API-ga töötamisel on võtme salvestamine keskmistes muutujaates vastuolus kasutustingimustega, seega kirjutan kõigepealt lihtsa API vahekihiga. See põhineb Google Maps API võtme salvestamisel keskkonnamuutujas; kui teie keskkonnamuutujates ei ole salvestatud võtme, ei käivitu selles osas esitatud koodijupid.

has_key <- !identical(Sys.getenv("GOOGLE_MAPS_API_KEY"), "")
if (!has_key) {
  message("Google Maps API võtit ei leitud; koodijupid ei käivitu")
}

# https://developers.google.com/maps/documentation/geocoding
geocode <- function(address, api_key = Sys.getenv("GOOGLE_MAPS_API_KEY")) {
  url <- "https://maps.googleapis.com/maps/api/geocode/json"
  url <- paste0(url, "?address=", URLencode(address), "&key=", api_key)

  jsonlite::read_json(url)
}

Selle funktsiooni tagastatud nimekiri on üsna keeruline:

houston  Loend: 2
#>  $ tulemused: Loend: 1
#>   ..$ : Loend: 5
#>   .. ..$ aadressikomponendid: Loend: 4
#>   .. .. ..$ : Loend: 3
#>   .. .. .. ..$ pikk_nimi : chr "Houston"
#>   .. .. .. ..$ lühinimi: chr "Houston"
#>   .. .. .. ..$ tüübid     : Loend: 2
#>   .. .. .. .. ..$ : chr "asula"
#>   .. .. .. .. ..$ : chr "poliitiline"
#>   .. .. ..$ : Loend: 3
#>   .. .. .. ..$ pikk_nimi : chr "Harris County"
#>   .. .. .. ..$ lühinimi: chr "Harris County"
#>   .. .. .. ..$ tüübid     : Loend: 2
#>   .. .. .. .. ..$ : chr "administratiivne_ala_tase_2"
#>   .. .. .. .. ..$ : chr "poliitiline"
#>   .. .. ..$ : Loend: 3
#>   .. .. .. ..$ pikk_nimi : chr "Texas"
#>   .. .. .. ..$ lühinimi: chr "TX"
#>   .. .. .. ..$ tüübid     : Loend: 2
#>   .. .. .. .. ..$ : chr "administratiivne_ala_tase_1"
#>   .. .. .. .. ..$ : chr "poliitiline"
#>   .. .. ..$ : Loend: 3
#>   .. .. .. ..$ pikk_nimi : chr "Ameerika Ühendriigid"
#>   .. .. .. ..$ lühinimi: chr "US"
#>   .. .. .. ..$ tüübid     : Loend: 2
#>   .. .. .. .. ..$ : chr "riik"
#>   .. .. .. .. ..$ : chr "poliitiline"
#>   .. ..$ vormindatud_aadress : chr "Houston, TX, USA"
#>   .. ..$ geomeetria          : Loend: 4
#>   .. .. ..$ piirid       : Loend: 2
#>   .. .. .. ..$ kirdesuunas: Loend: 2
#>   .. .. .. .. ..$ lat: num 30.1
#>   .. .. .. .. ..$ lng: num -95
#>   .. .. .. ..$ lääneosas: Loend: 2
#>   .. .. .. .. ..$ lat: num 29.5
#>   .. .. .. .. ..$ lng: num -95.8
#>   .. .. ..$ asukoht     : Loend: 2
#>   .. .. .. ..$ lat: num 29.8
#>   .. .. .. ..$ lng: num -95.4
#>   .. .. ..$ asukoha_tüüp: chr "KUIDAS"
#>   .. .. ..$ vaade     : Loend: 2
#>   .. .. .. ..$ kirdesuunas: Loend: 2
#>   .. .. .. .. ..$ lat: num 30.1
#>   .. .. .. .. ..$ lng: num -95
#>   .. .. .. ..$ lääneosas: Loend: 2
#>   .. .. .. .. ..$ lat: num 29.5
#>   .. .. .. .. ..$ lng: num -95.8
#>   .. ..$ koht_id          : chr "ChIJAYWNSLS4QIYROwVl894CDco"
#>   .. ..$ tüübid             : Loend: 2
#>   .. .. ..$ : chr "asula"
#>   .. .. ..$ : chr "poliitiline"
#>  $ seisund : chr "OK"

Õnneks saame samaaegselt lahendada probleemi, muutes need andmed tabeli vormi, kasutades funktsioone tidyr. Et ülesannet veidi keerulisemaks ja realistlikumaks teha, alustan mitme linna geokodeerimisega:

  city <- c("Houston", "LA", "New York", "Chicago", "Springfield") city_geo <- purrr::map(city, geocode) 

Saadud tulemuse muudan ma tibble, mugavuse huvides lisades vastava linna nime veeru.

loc  # A tibble: 5 x 2
#>   linn        json            
#>   <chr>       <list>          
#> 1 Houston     <nimeline loend [2]>
#> 2 LA          <nimeline loend [2]>
#> 3 New York    <nimeline loend [2]>
#> 4 Chicago     <nimeline loend [2]>
#> 5 Springfield <nimeline loend [2]>

Esimene tase sisaldab komponente staatus ja result, mille saame avada kasutades unnest_wider() :

loc %>%
  unnest_wider(json)
#> # A tibble: 5 x 3
#>   linn        tulemused    seisund
#>   <chr>       <list>     <chr> 
#> 1 Houston     <loend [1]> OK    
#> 2 LA          <loend [1]> OK    
#> 3 New York    <loend [1]> OK    
#> 4 Chicago     <loend [1]> OK    
#> 5 Springfield <loend [1]> OK

Pange tähele, et tulemused on mitmekihiline loend. Enamikul linnadest on 1 element (mis esindab ainulaadset väärtust, mis vastab geokoodimise API-le), kuid Springfieldis on neid kaks. Saame need eraldi ridadeks välja tõmmata, kasutades unnest_longer() :

loc %>%
  unnest_wider(json) %>% 
  unnest_longer(results)
#> # A tibble: 5 x 3
#>   city        results          status
#>                      
#> 1 Houston      OK    
#> 2 LA           OK    
#> 3 New York     OK    
#> 4 Chicago      OK    
#> 5 Springfield  OK

Nüüd on neil kõigil samad komponendid, millele saab veenduda, kasutades unnest_wider():

loc %>%
  unnest_wider(json) %>% 
  unnest_longer(results) %>% 
  unnest_wider(results)
#> # A tibble: 5 x 7
#>   city   address_componen… formatted_addre… geometry place_id  types status
#>                                       
#> 1 Houst…         Houston, TX, USA <named … ChIJAYWN…  OK    
#> 2 LA             Los Angeles, CA… <named … ChIJE9on…  OK    
#> 3 New Y…         New York, NY, U… <named … ChIJOwg_…  OK    
#> 4 Chica…         Chicago, IL, USA <named … ChIJ7cv0…  OK    
#> 5 Sprin…         Springfield, MO… <named … ChIJP5jI…  OK

Saame leida iga linna laius- ja pikkuskraadid, avades loendi geometry:

loc %>%
  unnest_wider(json) %>% 
  unnest_longer(results) %>% 
  unnest_wider(results) %>% 
  unnest_wider(geometry)
#> # A tibble: 5 x 10
#>   city  address_compone… formatted_addre… bounds location location_type
#>                                       
#> 1 Hous…        Houston, TX, USA <name…  2 LA           Los Angeles, CA… <name…  3 New …        New York, NY, U… <name…  4 Chic…        Chicago, IL, USA <name…  5 Spri…        Springfield, MO… <name…  # … with 4 more variables: viewport , place_id , types ,
#> #   status

Ja seejärel asukoht, milleks on vajalik loendi avamine asukoht:

loc %>%
  unnest_wider(json) %>%
  unnest_longer(results) %>%
  unnest_wider(results) %>%
  unnest_wider(geometry) %>%
  unnest_wider(location)
#> # A tibble: 5 x 11
#>   city  address_compone… formatted_addre… bounds   lat    lng location_type
#>                                        
#> 1 Hous…        Houston, TX, USA  2 LA           Los Angeles, CA…  3 New …        New York, NY, U…  4 Chic…        Chicago, IL, USA  5 Spri…        Springfield, MO…  # … with 4 more variables: viewport , place_id , types ,
#> #   status

Jällegi, unnest_auto() lihtsustab kirjeldatud operatsiooni, kuid võib esineda teatud riske, mis võivad tuleneda sissetuleva andmestruktuuri muutumisest:

loc %>%
  unnest_auto(json) %>%
  unnest_auto(results) %>%
  unnest_auto(results) %>%
  unnest_auto(geometry) %>%
  unnest_auto(location)
#> Using `unnest_wider(json)`; elements have 2 names in common
#> Using `unnest_longer(results)`; no element has names
#> Using `unnest_wider(results)`; elements have 5 names in common
#> Using `unnest_wider(geometry)`; elements have 4 names in common
#> Using `unnest_wider(location)`; elements have 2 names in common
#> # A tibble: 5 x 11
#>   city  address_compone… formatted_addre… bounds   lat    lng location_type
#>                                        
#> 1 Hous…        Houston, TX, USA  2 LA           Los Angeles, CA…  3 New …        New York, NY, U…  4 Chic…        Chicago, IL, USA  5 Spri…        Springfield, MO…  # … with 4 more variables: viewport , place_id , types ,
#> #   status

Saame samuti lihtsalt vaadata igas linnas esimest aadressi:

loc %>%
  unnest_wider(json) %>%
  hoist(results, first_result = 1) %>%
  unnest_wider(first_result) %>%
  unnest_wider(geometry) %>%
  unnest_wider(location)
#> # A tibble: 5 x 11
#>   city  address_compone… formatted_addre… bounds   lat    lng location_type
#>                                        
#> 1 Hous…        Houston, TX, USA  2 LA           Los Angeles, CA…  3 New …        New York, NY, U…  4 Chic…        Chicago, IL, USA  5 Spri…        Springfield, MO…  # … with 4 more variables: viewport , place_id , types ,
#> #   status

Või kasutada hoist() mitmeastmelise süva-uuringu jaoks, et liikuda otse lat ja lng.

loc %>%
  hoist(json,
    lat = list("results", 1, "geometry", "location", "lat"),
    lng = list("results", 1, "geometry", "location", "lng")
  )
#> # A tibble: 5 x 4
#>   city          lat    lng json            
#>                       
#> 1 Houston      29.8  -95.4 
#> 2 LA           34.1 -118.  
#> 3 New York     40.7  -74.0 
#> 4 Chicago      41.9  -87.6 
#> 5 Springfield  37.2  -93.3

Sharli Gelfandi diskograafia

Lõpetuseks vaatame kõige keerulisemat konstruktsiooni - Sharla Gelfandi diskograafiat. Nagu eelnevalt toodud näidetes, alustame nimekirja konverteerimisest andmeraamiks ühe veeruga ja laiendame seda hiljem, et iga komponent oleks eraldi veerus. Samuti muudab ma veeru date_added vastavaks kuupäeva ja kellaaja formaadiks R-is.

discs % 
  unnest_wider(disc) %>% 
  mutate(date_added = as.POSIXct(strptime(date_added, "%Y-%m-%dT%H:%M:%S"))) 
discs
#> # A tibble: 155 x 5
#>    instance_id date_added          basic_information       id rating
#>                                          
#>  1   354823933 2019-02-16 17:48:59   7496378      0
#>  2   354092601 2019-02-13 14:13:11   4490852      0
#>  3   354091476 2019-02-13 14:07:23   9827276      0
#>  4   351244906 2019-02-02 11:39:58   9769203      0
#>  5   351244801 2019-02-02 11:39:37   7237138      0
#>  6   351052065 2019-02-01 20:40:53  13117042      0
#>  7   350315345 2019-01-29 15:48:37   7113575      0
#>  8   350315103 2019-01-29 15:47:22  10540713      0
#>  9   350314507 2019-01-29 15:44:08  11260950      0
#> 10   350314047 2019-01-29 15:41:35  11726853      0
#> # … with 145 more rows

Siin tasemel saime teavet, millal iga plaat Sharla diskograafiasse lisati, kuid me ei näe siiski mingit teavet nende plaatide kohta. Selleks peame laiendama veeru basic_information:

discs %>% unnest_wider(basic_information)
#> Veeru nimi `id` ei tohi olla dubleeritud.
#> Kasutamine .name_repair, et määrata remont.

Kahjuks saame vea, kuna nimekirjas basic_information on samanimeline veerg basic_information. Sellise vea korral saab selle põhjuse kiireks määramiseks kasutada names_repair = "unique":

ketta %>% unnest_wider(basic_information, names_repair = "unique")
#> Uued nimed:
#> * id -> id...6
#> * id -> id...14
#> # Tibble: 155 x 15
#>    instance_id kuupäev_lisatud      sildid  aasta artistid id...6 thumb pealkiri
#>                                
#>  1   354823933 2019-02-16 17:48:59 <list…  2015   2   354092601 2019-02-13 14:13:11 <list…  2013   3   354091476 2019-02-13 14:07:23 <list…  2017   4   351244906 2019-02-02 11:39:58 <list…  2017   5   351244801 2019-02-02 11:39:37 <list…  2015   6   351052065 2019-02-01 20:40:53 <list…  2019   7   350315345 2019-01-29 15:48:37 <list…  2014   8   350315103 2019-01-29 15:47:22 <list…  2015   9   350314507 2019-01-29 15:44:08 <list…  2017  10   350314047 2019-01-29 15:41:35 <list…  2017  # … kokku 145 rida ja 7 muutuvat: formaadid ,
#> #   kaanepilt , ressursi_url , master_id ,
#> #   master_url , id...14 , reiting

Probleem on selles, et basic_information kordab id veergu, mis on samuti tippu salvestatud, seega saame selle lihtsalt eemaldada:

ketta %>% 
  select(-id) %>% 
  unnest_wider(basic_information)
#> # Tibble: 155 x 14
#>    instance_id kuupäev_lisatud      sildid  aasta artistid     id thumb pealkiri
#>                                
#>  1   354823933 2019-02-16 17:48:59 <list…  2015   2   354092601 2019-02-13 14:13:11 <list…  2013   3   354091476 2019-02-13 14:07:23 <list…  2017   4   351244906 2019-02-02 11:39:58 <list…  2017   5   351244801 2019-02-02 11:39:37 <list…  2015   6   351052065 2019-02-01 20:40:53 <list…  2019   7   350315345 2019-01-29 15:48:37 <list…  2014   8   350315103 2019-01-29 15:47:22 <list…  2015   9   350314507 2019-01-29 15:44:08 <list…  2017  10   350314047 2019-01-29 15:41:35 <list…  2017  # … kokku 145 rida ja 6 muutuvat: formaadid ,
#> #   kaanepilt , ressursi_url , master_id ,
#> #   master_url , reiting

Alternatiivina oleksime võinud kasutada hoist():

plaadid %>% 
  hoist(basic_information,
    title = "title",
    year = "year",
    label = list("labels", 1, "name"),
    artist = list("artists", 1, "name")
  )
#> # A tibble: 155 x 9
#>    instance_id date_added          title  year label artist
#>                             
#>  1   354823933 2019-02-16 17:48:59 Demo   2015 Tobi… Mollot
#>  2   354092601 2019-02-13 14:13:11 Obse…  2013 La V… Una B…
#>  3   354091476 2019-02-13 14:07:23 I      2017 La V… S.H.I…
#>  4   351244906 2019-02-02 11:39:58 Oído…  2017 La V… Rata …
#>  5   351244801 2019-02-02 11:39:37 A Ca…  2015 Kato… Ivy (…
#>  6   351052065 2019-02-01 20:40:53 Tash…  2019 High… Tashme
#>  7   350315345 2019-01-29 15:48:37 Demo   2014 Mind… Desgr…
#>  8   350315103 2019-01-29 15:47:22 Let …  2015 Not … Phant…
#>  9   350314507 2019-01-29 15:44:08 Sub …  2017 Not … Sub S…
#> 10   350314047 2019-01-29 15:41:35 Demo   2017 Pres… Small…
#> # … 145 rohkem rida, ja 3 rohkem muutujat: basic_information ,
#> #   id , rating

Siin kogun ma kiiresti esimese plaadi ja esineja nime indeksi kaudu, sukeldudes sisemisse loendisse.

Süsteemsem lähenemine on luua eraldi tabelid esineja ja plaadi jaoks:

plaadid %>% 
  hoist(basic_information, artist = "artists") %>% 
  select(disc_id = id, artist) %>% 
  unnest_longer(artist) %>% 
  unnest_wider(artist)
#> # A tibble: 167 x 8
#>     disc_id join  name        anv   tracks role  resource_url            id
#>                                    
#>  1  7496378 ""    Mollot      ""    ""     ""    https://api.discog… 4.62e6
#>  2  4490852 ""    Una Bèstia… ""    ""     ""    https://api.discog… 3.19e6
#>  3  9827276 ""    S.H.I.T. (… ""    ""     ""    https://api.discog… 2.77e6
#>  4  9769203 ""    Rata Negra  ""    ""     ""    https://api.discog… 4.28e6
#>  5  7237138 ""    Ivy (18)    ""    ""     ""    https://api.discog… 3.60e6
#>  6 13117042 ""    Tashme      ""    ""     ""    https://api.discog… 5.21e6
#>  7  7113575 ""    Desgraciad… ""    ""     ""    https://api.discog… 4.45e6
#>  8 10540713 ""    Phantom He… ""    ""     ""    https://api.discog… 4.27e6
#>  9 11260950 ""    Sub Space … ""    ""     ""    https://api.discog… 5.69e6
#> 10 11726853 ""    Small Man … ""    ""     ""    https://api.discog… 6.37e6
#> # … 157 rohkem rida

plaadid %>% 
  hoist(basic_information, format = "formats") %>% 
  select(disc_id = id, format) %>% 
  unnest_longer(format) %>% 
  unnest_wider(format) %>% 
  unnest_longer(descriptions)
#> # A tibble: 280 x 5
#>     disc_id descriptions text  name     qty  
#>                     
#>  1  7496378 Numbered     Black Cassette 1    
#>  2  4490852 LP             Vinyl    1    
#>  3  9827276 "7""          Vinyl    1    
#>  4  9827276 45 RPM         Vinyl    1    
#>  5  9827276 EP             Vinyl    1    
#>  6  9769203 LP             Vinyl    1    
#>  7  9769203 Album          Vinyl    1    
#>  8  7237138 "7""          Vinyl    1    
#>  9  7237138 45 RPM         Vinyl    1    
#> 10 13117042 "7""          Vinyl    1    
#> # … 270 rohkem rida

Seejärel saate need vajadusel originaalandmestikuga uuesti ühendada.

Kokkuvõte

Raamatukogu tuum tidyverse kätkeb endas mitmeid kasulikke pakette, mis on ühendatud andmete töötlemise ühtse filosoofiaga.

Selles artiklis käsitlesime funktsioonide peret unnest_*(), mis on suunatud elementide väljavõtmisele pesakondadest. Antud pakett sisaldab mitmeid teisi kasulikke funktsioone, mis lihtsustavad andmete muutmist vastavalt kontseptsioonile Korrastatud Andmed.

Allikas: habr.com

Osta usaldusväärne hostimine veebilehtede jaoks DDoS-i kaitsega, VPS VDS serverid 🔥 Osta usaldusväärne hostimine veebilehtede jaoks DDoS-i kaitsega, VPS VDS serverid | ProHoster