Lahtime toetatud veerud — loendid R keele abil (pakett tidyr ja funktsioonide unnest perekond)

Enamikul juhtudel, töötades vastusega API-st või muude keeruliste puustruktuuriga andmetega, saate kokku puutuda JSON ja XML formaatidega.

Nendel formaatidel on palju eeliseid: need salvestavad andmeid piisavalt kompaktselt ja võimaldavad vältida liigset teabe dubleerimist.

Kuid nende formaatide miinuseks on andmete töötlemise ja analüüsi keerukus. Struktureerimata andmeid ei saa kasutada arvutustes ega nende põhjal visualiseerimist luua.

Lahtime toetatud veerud — loendid R keele abil (pakett tidyr ja funktsioonide unnest perekond)

See artikkel on loogiline jätk väljaandele "R pakett tidyr ja selle uued funktsioonid pivot_longer ja pivot_wider". See aitab teil muuta struktureerimata andmekonstruktsioonid tuttavaks ja analüüsiks sobivaks tabelivorminguks, kasutades paketti tidyr, mis kuulub raamatukogu tuumikeskkonda tidyverse, ja selle unnest_*() funktsioone. GitHubi kasutajad.

Sisu

Kui teid huvitab andmeanalüüs, siis võivad teile huvi pakkuda minu telegram ja youtube kanalid, mille suurem osa sisust on pühendatud R keelele.

  1. Sissejuhatus
  2. Githubi hoidlad
  3. Troonide mängu karakterid
  4. Geokodeerimine Google'i abil
  5. Sharly Gelfandi diskograafia
  6. Klambriteks
  7. Kokkuvõte

Sissejuhatus

Rectangling (tõlke märkuseks, ei leidnud selle termini jaoks adekvaatseid tõlkeid, seetõttu jätame selle nii nagu on.) — on protsess, millega struktureerimata andmed, mis sisaldavad sisemisi massiive, muudetakse kahemõõtmeliseks tabeliks, mis koosneb meile tuttavatest ridadest ja veergudest. Selles tidyr on mitu funktsiooni, mis aitavad teil avada sisemisi veergu-loendeid ja muuta andmed ristkülikukujuliseks, tabelikujuliseks vormiks:

  • unnest_longer() võtab iga loende elementi ja loob uue rea.
  • unnest_wider() võtab iga loende elementi ja loob uue veeru.
  • unnest_auto() määrab automaatselt, millist funktsiooni on parem kasutada,
    unnest_longer() või unnest_wider().
  • hoist() on sarnane unnest_wider() kuid valib ainult määratud komponendid ja võimaldab töötada mitme taseme süvenemisega.

Enamik probleeme, mis on seotud struktureerimata andmete viimisega mitme taseme süvenemisega kahemõõtmelisse tabelisse, saab lahendada, kombineerides loetletud funktsioone dplyr-iga.

Nende meetodite demonstreerimiseks kasutame paketti repurrrsive, mis pakub mitmeid keerukaid, mitmeastmelisi loendeid, saadud veeb-API-st.

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

Githubi hoidlad

Alustame gh_users, loend, mis sisaldab teavet kuue GitHubi kasutaja kohta. Alustame loendi konverteerimist gh_users ühes tibble raam:

kasutajad <- tibble(user = gh_users) 

See tundub veidi vastuolus olevat: miks konverteerida loend gh_users, keerulisemaks andmestruktuuriks? Kuid andmeraamil on suur eelis: see ühendab mitu vektorit, nii et kõik jälgitakse ühes objektis.

Iga objekti element users on nimetatud loend, 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, kuidas muuta loendi komponente veergudeks. unnest_wider() võtab iga komponendi ja loob uue veeru:

kasutajad %>% unnest_wider(user)
#> # Tibble: 6 x 30
#>   login     id avatar_url gravatar_id url   html_url followers_url
#>                                
#> 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 muutujaid: following_url , gists_url ,
#> #   starred_url , subscriptions_url , organizations_url ,
#> #   repos_url , events_url , received_events_url ,
#> #   type , site_admin , name , company , blog ,
#> #   location , email , public_repos , public_gists ,
#> #   followers , following , created_at , updated_at ,
#> #   bio , hireable

Selles olukorras saime 30 veerust sisaldava tabeli, ja enamik neist ei ole meile vajalikud, seega saame selle asemel unnest_wider() kasutada hoist(). hoist() võimaldab meil valida komponente, kasutades sama süntaksit nagu purrr::pluck():

kasutajad %> hoist(kasutaja, 
  jälgijad = "jälgijad", 
  sisselogimine = "sisselogimine", 
  url = "html_url"
)
#> # A tibble: 6 x 4
#>   jälgijad sisselogimine       url                            kasutaja             
#>                                                    
#> 1       303 gaborcsardi https://github.com/gaborcsardi 
#> 2       780 jennybc     https://github.com/jennybc     
#> 3      3958 jtleek      https://github.com/jtleek      
#> 4       115 juliasilge  https://github.com/juliasilge  
#> 5       213 leeper      https://github.com/leeper      
#> 6        34 masalmon    https://github.com/masalmon

hoist() eemaldab nimetatud komponente veerg-loendist kasutaja, seega võite käsitleda hoist() nagu komponentide liikumist and frame'i sisemisest loendist selle ülemisse tasemesse.

Troonide mängu karakterid

Loendi joondamine gh_repos alustame sarnaselt, muutes selle tibble:

repos  # A tibble: 6 x 1
#>   repo       
#>        
#> 1 
#> 2 
#> 3 
#> 4 
#> 5 
#> 6

Seekord elemendid kasutaja esindavad selle kasutaja omad repositories. Iga repos on eraldi vaatluse all, mistõttu vastab see korralike andmete konseptsioonile (märkus: tidy data) need to be new lines, for which we use unnest_longer() rather than unnest_wider():

repos % unnest_longer(repo)
repos
#> # A tibble: 176 x 1
#>    repo             
#>               
#>  1 
#>  2 
#>  3 
#>  4 
#>  5 
#>  6 
#>  7 
#>  8 
#>  9 
#> 10 
#> # … with 166 more rows

Now we can use unnest_wider() või hoist() :

repos %>% hoist(repo, 
  login = c("owner", "login"), 
  name = "name",
  homepage = "homepage",
  watchers = "watchers_count"
)
#> # A tibble: 176 x 5
#>    login       name        homepage watchers repo             
#>                                     
#>  1 gaborcsardi after                   5 
#>  2 gaborcsardi argufy                 19 
#>  3 gaborcsardi ask                     5 
#>  4 gaborcsardi baseimports             0 
#>  5 gaborcsardi citest                  0 
#>  6 gaborcsardi clisymbols  ""             18 
#>  7 gaborcsardi cmaker                  0 
#>  8 gaborcsardi cmark                   0 
#>  9 gaborcsardi conditions              0 
#> 10 gaborcsardi crayon                 52 
#> # … with 166 more rows

Pange tähele, et kasutatakse c("owner", "login"): this allows us to obtain the second-level value from the nested list omanik. Alternatiivne lähenemisviis on saada kogu nimekiri omanik ja seejärel kasutada funktsiooni unnest_wider() kandmiseks iga 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.…
#>% # … kokku 166 rida, ja 11 rohkem muutujat: following_url ,
#>% #   gists_url , starred_url , subscriptions_url ,
#>% #   organizations_url , repos_url , events_url ,
#>% #   received_events_url , type , site_admin , repo

Selle asemel, et mõelda sobiva funktsiooni valimisele unnest_longer() või unnest_wider() võite kasutada unnest_auto(). See funktsioon kasutab mitmeid heuristilisi meetodeid andmete transformatsiooni sobivaima funktsiooni leidmiseks ja kuvab valitud meetodi kohta teate.

tibble(repo = gh_repos) %>% 
  unnest_auto(repo) %>% 
  unnest_auto(repo)
#> Kasutatakse `unnest_longer(repo)`; ühelgi elemendil pole nimesid
#> Kasutatakse `unnest_wider(repo)`; elementidel on 68 nime ühiselt
#> # A tibble: 176 x 67
#>        id name  full_name owner private html_url description fork  url  
#>                            
#>  1 6.12e7 pärast gaborcsa…   2 4.05e7 argu… gaborcsa…   3 3.64e7 küsi   gaborcsa…   4 3.49e7 baasi… gaborcsa…   5 6.16e7 tsitee… 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 muutujat: 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 , language , has_issues ,
#> #   has_downloads , has_wiki , has_pages ,
#> #   forks_count , open_issues_count , forks ,
#> #   open_issues , watchers , default_branch ,
#> #   homepage

Geokodeerimine Google'i abil

sai_char on om identse struktuuriga gh_users: see on nimetatud loendite kogum, kus iga sisemise loendi element kirjeldab mingit omadust Troonimängu tegelasest. Toome sai_char tabeli kujule, alustame andmeframe'i loomisega, nagu eelnevalt toodud näidetes, ja seejärel teisendame iga elemendi eraldi veergu:

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 … <chr [… ""    
#>  2 http…  1052 Tyri… Male   ""      In 2… ""    TRUE  <chr … <chr [… ""    
#>  3 http…  1074 Vict… Male   Ironbo… In 2… ""    TRUE  <chr … <chr [… ""    
#>  4 http…  1109 Will  Male   ""      ""    In 2… FALSE <chr … <chr [… ""    
#>  5 http…  1166 Areo… Male   Norvos… In 2… ""    TRUE  <chr … <chr [… ""    
#>  6 http…  1267 Chett Male   ""      At H… In 2… FALSE <chr … <chr [… ""    
#>  7 http…  1295 Cres… Male   ""      In 2… In 2… FALSE <chr … <chr [… ""    
#>  8 http…   130 Aria… Female Dornish In 2… ""    TRUE  <chr … <chr [… ""    
#>  9 http…  1303 Daen… Female Valyri… In 2… ""    TRUE  <chr … <chr [… ""    
#> 10 http…  1319 Davo… Male   Wester… In 2… ""    TRUE  <chr … <chr [… ""    
#> # … with 20 more rows, and 7 more variables: mother , spouse ,
#> #   allegiances , books , povBooks , tvSeries ,
#> #   playedBy

Struktuur sai_char natuke keerulisem kui gh_users, kuna mõned loendi komponendid char on endid loendid, mistõttu 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          
#> # … kokku veel 20 rida

Teie järgmised sammud sõltuvad analüüsi eesmärkidest. Võib-olla on teil vaja iga raamatu ja telesarja kohta, milles tegelane esineb, lisada ridadesse teavet:

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 võib-olla soovite luua tabeli, mis võimaldaks teil seostada tegelase ja teose:

chars2 %>% 
  select(name, title = titles) %>% 
  unnest_longer(title)
#> # A tibble: 60 x 2
#>    name              title                                               
#>                                                                
#>  1 Theon Greyjoy     Talviku prints
#>  2 Theon Greyjoy     Meretähi kapten 
#>  3 Theon Greyjoy     Raudsaare isanda (roheliste maade seaduse kohaselt)
#>  4 Tyrion Lannister  Kuningate käe asendus (endine)
#>  5 Tyrion Lannister  Raha ülem (endine)
#>  6 Victarion Greyjoy Raudflööti admiral 
#>  7 Victarion Greyjoy Raudvõidu ülem
#>  8 Will              ""                                                  
#>  9 Areo Hotah        Sunspeari kaardiväe kapten                      
#> 10 Chett             ""                                                  
#> # … 50 rohkem rida

(Pange tähele, et tühjad väärtused "" väljal aadress, see on seotud andmete sisestamisel tehtud vigadega sai_char: tegelikult peaksid karakterid, millele ei vasta raamatute ja sarjade pealkirjad, olema aadress vektor pikkusega 0, mitte vektor pikkusega 1, mis sisaldab tühja rida.)

Me võime ülaltoodud näite ümber kirjutada, kasutades funktsiooni unnest_auto(). See lähenemine on mugav ühekordseks analüüsiks, kuid ei tasu loota unnest_auto() regulaarsel kasutamisel. Probleem on selles, et kui teie andmestruktuur muutub unnest_auto() võib muuta valitud andmete teisendamise mehanismi, kui algselt teisendati veerulistes nimekirjades readeks kasutades unnest_longer(), seega andmestruktuuri muutmisel võib loogika muutuda eeliste nimel unnest_wider(), ja sellise lähenemise pidev kasutamine võib kaasa tuua ettenägematuid vigu.

tibble(char = got_chars) %>% 
  unnest_auto(char) %>% 
  select(name, title = titles) %>% 
  unnest_auto(title)
#> Using `unnest_wider(char)`; elements have 18 names in common
#> Using `unnest_longer(title)`; no element has names
#> # 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

Sharly Gelfandi diskograafia

Edasi vaatame keerulisemat andmestruktuuri, mida Google'i geokodeerimisteenus tagastab. Google Maps API kasutuse kohta andmete vahemällu salvestamine on vastupidine nende tingimustega, seega kirjutan kõigepealt API lihtsa wrapperi. See põhineb Google'i kaarditeenuse API võtme säilitamisel keskkonnamuutujas; kui teie keskkonnamuutujates ei ole Google Maps API võtme jaoks salvestatud väärtust, siis selles osas esitatud koodifragmendid ei tööta.

has_key <- !identical(Sys.getenv("GOOGLE_MAPS_API_KEY"), "")
if (!has_key) {
  message("No Google Maps API key found; code chunks will not be run")
}

# 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)
}

See funktsioon tagastab üsna keerulise nimekirja:

houston  geocode("Houston TX")
str(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 "haldusala_tase_2"
#>   .. .. .. .. ..$ : chr "poliitiline"
#>   .. .. ..$ :Loend 3
#>   .. .. .. ..$ pikk_nimi : chr "Texas"
#>   .. .. .. ..$ lühinimi: chr "TX"
#>   .. .. .. ..$ tüübid     :Loend 2
#>   .. .. .. .. ..$ : chr "haldusala_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õunasuunas: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 "KUIDAGI"
#>   .. .. ..$ vaade     :Loend 2
#>   .. .. .. ..$ kirdesuunas:Loend 2
#>   .. .. .. .. ..$ lat: num 30.1
#>   .. .. .. .. ..$ lng: num -95
#>   .. .. .. ..$ lõunasuunas: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 selle andmete tabelisse konverteerimise probleemi samm-sammult lahendada funktsioonide abil tidyr. Et ülesanne oleks veidi keerulisem ja reaalsem, alustan mõne linna geokodeerimisest:

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

Saadud tulemuse konverteerin tibble, mugavuse huvides lisan vastava linna nimega veeru.

loc  # A tibble: 5 x 2
#>   city        json            
#>                    
#> 1 Houston     
#> 2 LA          
#> 3 New York    
#> 4 Chicago     
#> 5 Springfield

Esimene tase sisaldab komponente status ja tulemus, mida saame avada, kasutades unnest_wider() :

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

Pange tähele, et results on mitmetasandiline loend. Enamikul linnadest on 1 element (mis esindab unikaalset väärtust, mis vastab geokodeerimise API-le), kuid Springfieldil on neid kaks. Saame neid eraldi ridadele 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, milles saab veenduda 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… % 2 LA             Los Angeles, CA… <named … ChIJE9on… % 3 New Y…         New York, NY, U… <named … ChIJOwg_… % 4 Chica…         Chicago, IL, USA <named … ChIJ7cv0… % 5 Sprin…         Springfield, MO… <named … ChIJP5jI… <lis… OK

Me 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

Seejärel on vajalik asukoht, millega tuleb arvestada asukohta:

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
#>                            <dbl>  <dbl> <chr>        
#> 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

Taaskord, unnest_auto() lihtsustab kirjeldatud operatsiooni teatud riskidega, mis võivad tuleneda sisendandmete struktuuri muutumisest:

loc %>%
  unnest_auto(json) %>%
  unnest_auto(results) %>%
  unnest_auto(results) %>%
  unnest_auto(geometry) %>%
  unnest_auto(location)
#>% Kasutades `unnest_wider(json)`; elementidel on 2 ühistsõna
#>% Kasutades `unnest_longer(results)`; ühelgi elemendil ei ole nimesid
#>% Kasutades `unnest_wider(results)`; elementidel on 5 ühistsõna
#>% Kasutades `unnest_wider(geometry)`; elementidel on 4 ühistsõna
#>% Kasutades `unnest_wider(location)`; elementidel on 2 ühistsõna
#>% # Tibble: 5 x 11
#>%   linn  aadressi_kompon… vormindatud_aadress… piirid   lat    lng asukoha_tüüp
#>%                                            
#>% 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… % # … koos 4 rohkem muutuja: vaateaken , place_id , tüübid ,
#>% #   olek

Saame samuti lihtsalt vaadata iga linna 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
#>                            <dbl>  <dbl> <chr>
#> 1 Hous…        Houston, TX, USA <name…  29.8  -95.4 APPROXIMATE
#> 2 LA           Los Angeles, CA… <name…  34.1 -118.  APPROXIMATE
#> 3 New …        New York, NY, U… <name…  40.7  -74.0 APPROXIMATE
#> 4 Chic…        Chicago, IL, USA <name…  41.9  -87.6 APPROXIMATE
#> 5 Spri…        Springfield, MO… <name…  37.2  -93.3 APPROXIMATE
#> # … with 4 more variables: viewport , place_id , types ,
#> #   status

Või kasutada hoist() multi-level süvenemiseks, et minna 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

Klambriteks

Kokkuvõtteks vaatleme kõige keerukamat struktuuri – Šarla Gelfandi diskograafiat. Nagu eelnevalt toodud näidetes, alustame nimekirja konverteerimist ühe veeruga andmeframe-iks, seejärel laiendame seda, et iga komponent oleks eraldi veerus. Samuti muudan veeru date_added vastavaks kuupäeva ja kellaaja formaadiks R-s.

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

Sellel tasemel saime teavet selle kohta, millal iga plaat lisati Sharly diskograafiasse, kuid meil puuduvad nende plaatide andmed. Nende andmete saamiseks peame veergu laiendama basic_information:

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

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

diskid %>% unnest_wider(basic_information, names_repair = "unique")
#> Uued nimed:
#> * id -> id...6
#> * id -> id...14
#> # Tibble: 155 x 15
#>    instance_id date_added          labels  year artists id...6 thumb title
#>          <int> <dttm>              <list> <int> <list>   <int> <chr> <chr>
#>  1   354823933 2019-02-16 17:48:59 <list…  2015 <list … 7.50e6 http… Demo 
#>  2   354092601 2019-02-13 14:13:11 <list…  2013 <list … 4.49e6 http… Obse…
#>  3   354091476 2019-02-13 14:07:23 <list…  2017 <list … 9.83e6 http… I    
#>  4   351244906 2019-02-02 11:39:58 <list…  2017 <list … 9.77e6 http… Oído…
#>  5   351244801 2019-02-02 11:39:37 <list…  2015 <list … 7.24e6 http… A Ca…
#>  6   351052065 2019-02-01 20:40:53 <list…  2019 <list … 1.31e7 http… Tash…
#>  7   350315345 2019-01-29 15:48:37 <list…  2014 <list … 7.11e6 http… Demo 
#>  8   350315103 2019-01-29 15:47:22 <list…  2015 <list … 1.05e7 http… Let …
#>  9   350314507 2019-01-29 15:44:08 <list…  2017 <list … 1.13e7 ""    Sub …
#> 10   350314047 2019-01-29 15:41:35 <list…  2017 <list … 1.17e7 http… Demo 
#> # … kokku 145 rida, ja 7 muutujat: formats <list>,
#> #   cover_image <chr>, resource_url <chr>, master_id <int>,
#> #   master_url <chr>, id...14 <int>, rating <int>

Probleem on see, et basic_information see kordab ülespoole salvestatud id veergu, seega võime selle lihtsalt eemaldada:

plaadid %>% 
  select(-id) %>% 
  unnest_wider(basic_information)
#> # Tibble: 155 x 14
#>    instance_id kuupäev_lisatud      sildid  aasta artistid     id pilt 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 rohkem muutujat: formaadid ,
#> #   kaanepilt , ressurssi_url , master_id ,
#> #   master_url , hinnang

Alternatiivselt võime kasutada hoist():

diskid %>% 
  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…
#>% # … with 145 more rows, and 3 more variables: basic_information ,
#>% #   id , rating

Siin ekstraktin kiiresti esimese sildi ja artisti nime indeksi kaudu, süvenedes sisse viidud nimekirja.

Süsteemsem lähenemine seisneb eraldi tabelite loomises artisti ja sildi jaoks:

plaadid %>% 
  hoist(basic_information, artist = "artists") %>% 
  select(disc_id = id, artist) %>% 
  unnest_longer(artist) %>% 
  unnest_wider(artist)
#> # Tibble: 167 x 8
#>     disc_id join  nimi       anv   lood  roll  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
#> # … veel 157 rida

plaadid %>% 
  hoist(basic_information, format = "formats") %>% 
  select(disc_id = id, format) %>% 
  unnest_longer(format) %>% 
  unnest_wider(format) %>% 
  unnest_longer(descriptions)
#> # Tibble: 280 x 5
#>     disc_id kirjeldused tekst  nimi     qty  
#>                    
#>  1  7496378 Numbered    Must kassett 1    
#>  2  4490852 LP            Virland  1    
#>  3  9827276 "7""         Virland  1    
#>  4  9827276 45 RPM        Virland  1    
#>  5  9827276 EP            Virland  1    
#>  6  9769203 LP            Virland  1    
#>  7  9769203 Album         Virland  1    
#>  8  7237138 "7""         Virland  1    
#>  9  7237138 45 RPM        Virland  1    
#> 10 13117042 "7""         Virland  1    
#> # … veel 270 rida

Seejärel saate need vajaduse korral taas originaalsete andmehulkadega ühendada.

Kokkuvõte

Raamatukogude põhikomponent tidyverse koosneb paljusid kasulikest paketidest, mis jagavad ühist andmete töötlemise filosoofiat.

Selles artiklis käsitleme funktsioonide perekonda GitHubi kasutajad, mis on suunatud sisemiste loendite elementide väljavõtmisega tegelemisele. See paket sisaldab palju muid kasulikke funktsioone, mis lihtsustavad andmete transformeerimist vastavalt kontseptsioonile Tidy Data.

Allikas: habr.com

Osta usaldusväärne veebihosting DDoS kaitsega, VPS VDS serverid 🔥 Osta usaldusväärne veebihosting DDoS kaitsega, VPS VDS serverid | ProHoster