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.

See artikkel on loogiline jätk avaldamisele . 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 ja kanalid, millel on suur osa sisu R keelele.
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õiunnest_wider().hoist()on sarnaneunnest_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 veelNüü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 veelPöö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 , repoKohapeal 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_lehtGame 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 rowsTeie 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 rowsVõ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 ridaGeokodeerimine 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]> OKPange 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 OKNüü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… OKSaame 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 ,
#> # statusJa 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 ,
#> # statusJä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 ,
#> # statusSaame 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 ,
#> # statusVõ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.3Sharli 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 rowsSiin 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 , reitingProbleem 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 , reitingAlternatiivina 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 , ratingSiin 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 ridaSeejä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
