ProHoster > блог > адміністраванне > Разгортваем укладзеныя слупкі - спісы з дапамогай мовы R (пакет tidyr і функцыі сямейства unnest)
Разгортваем укладзеныя слупкі - спісы з дапамогай мовы R (пакет tidyr і функцыі сямейства unnest)
У большасці выпадкаў пры працы з адказам атрыманым ад API, ці з любымі іншымі дадзенымі якія маюць складаную дрэвападобную структуру, вы сутыкаецеся з фарматамі JSON і XML.
Гэтыя фарматы маюць мноства пераваг: яны дастаткова кампактна захоўваюць дадзеныя і дазваляюць пазбегнуць залішняга дубліравання інфармацыі.
Мінусам гэтых фарматаў з'яўляецца складанасць іх апрацоўкі і аналізу. Неструктураваныя дадзеныя немагчыма выкарыстоўваць у вылічэннях і нельга будаваць на іх аснове візуалізацыю.
Гэты артыкул з'яўляецца лагічным працягам публікацыі. "R пакет tidyr і яго новыя функцыі pivot_longer і pivot_wider". Яна дапаможа вам прывесці неструктураваныя канструкцыі дадзеных да звыклага, і прыдатнага для аналізу таблічнага выгляду з дапамогай пакета tidyr, якое ўваходзіць у ядро бібліятэкі tidyverse, і яго функцый сямейства unnest_*().
Змест
Калі вы цікавіцеся аналізам дадзеных магчыма вам будуць цікавыя мае тэлеграма и YouTube каналы. Большая частка кантэнту якіх прысвечаны мове R.
Rectangling(заўв. перакладніка, не знайшоў адэкватных варыянтаў перакладу гэтага тэрміна, таму пакінем яго як ёсць.) - Гэта працэс прывядзення не структураваных дадзеных з укладзенымі масівамі да двухмернай табліцы, якая складаецца з звыклых нам радкоў і слупкоў. У tidyr ёсць некалькі функцый, якія дапамогуць вам разгарнуць укладзеныя слупкі-спісы і прывесці дадзеныя да прастакутнай, таблічнай форме:
unnest_longer() бярэ кожны элемент спісу-слупка і стварае новы радок.
unnest_wider() бярэ кожны элемент спісу-слупка і стварае новы слупок.
unnest_auto() аўтаматычна вызначае якую з функцый лепш выкарыстоўваць unnest_longer() або unnest_wider().
hoist() падобная на unnest_wider() але адбірае толькі паказаныя кампаненты і дазваляе працаваць з некалькімі ўзроўнямі ўкладзенасці.
Большасць праблем злучаных з прывядзеннем не структураваных дадзеных з некалькімі ўзроўнямі ўкладзенасці да двухмернай табліцы можна вырашыць, камбінуючы пералічаныя функцыі з dplyr.
Для дэманстрацыі гэтых прыёмаў, мы будзем выкарыстоўваць пакет repurrrsive, які дае некалькі складаных, шматузроўневых спісаў, атрыманых з вэб-API.
Пачнем з gh_users, спісу, які змяшчае інфармацыю аб шасці карыстальніках GitHub. Для пачатку пераўтворым спіс gh_users в tibble фрэйм.:
users <- tibble( user = gh_users )
Гэта здаецца крыху нелагічным: навошта прыводзіць спіс gh_users, да больш складанай структуры дадзеных? Але ў дата фрэйма ёсць вялікая перавага: ён аб'ядноўвае некалькі вектараў, так што ўсё адсочваецца ў адным аб'екце.
Кожны элемент аб'екта users уяўляе сабой найменны спіс, у якім кожны элемент уяўляе слупок.
У гэтым выпадку мы атрымалі табліцу якая складаецца з 30 слупкоў, і большасць з іх нам не спатрэбяцца, таму мы можам замест unnest_wider() выкарыстоўваць hoist(). hoist() дазваляе нам здабываць абраныя кампаненты, выкарыстоўваючы той жа сінтаксіс, што і purrr::pluck():
users %>% hoist(user,
followers = "followers",
login = "login",
url = "html_url"
)
#> # A tibble: 6 x 4
#> followers login url user
#> <int> <chr> <chr> <list>
#> 1 303 gaborcsardi https://github.com/gaborcsardi <named list [27]>
#> 2 780 jennybc https://github.com/jennybc <named list [27]>
#> 3 3958 jtleek https://github.com/jtleek <named list [27]>
#> 4 115 juliasilge https://github.com/juliasilge <named list [27]>
#> 5 213 leeper https://github.com/leeper <named list [27]>
#> 6 34 masalmon https://github.com/masalmon <named list [27]>
hoist() выдаляе названыя найменныя кампаненты са спісу-слупка карыстальнік, таму вы можаце разглядаць hoist() як перасоўванне кампанентаў з унутранага спісу дата фрэйма да яго верхняга ўзроўня.
Рэпазітары Github
Выраўноўванне спісу gh_repos мы пачынаем аналагічна, пераўтворачы яго ў tibble:
На гэты раз элементы карыстальнік уяўляюць сабой спіс рэпазітараў, якія належаць гэтаму карыстачу. Кожны рэпазітар з'яўляецца асобным назіраннем, таму паводле канцэпцыі акуратных дадзеных (заўв. tidy data) яны павінны стаць новымі радкамі, у сувязі з чым мы выкарыстоўваем unnest_longer() а ня unnest_wider():
repos <- repos %>% unnest_longer(repo)
repos
#> # A tibble: 176 x 1
#> repo
#> <list>
#> 1 <named list [68]>
#> 2 <named list [68]>
#> 3 <named list [68]>
#> 4 <named list [68]>
#> 5 <named list [68]>
#> 6 <named list [68]>
#> 7 <named list [68]>
#> 8 <named list [68]>
#> 9 <named list [68]>
#> 10 <named list [68]>
#> # … with 166 more rows
Цяпер мы можам выкарыстоўваць unnest_wider() або 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
#> <chr> <chr> <chr> <int> <list>
#> 1 gaborcsardi after <NA> 5 <named list [65]>
#> 2 gaborcsardi argufy <NA> 19 <named list [65]>
#> 3 gaborcsardi ask <NA> 5 <named list [65]>
#> 4 gaborcsardi baseimports <NA> 0 <named list [65]>
#> 5 gaborcsardi citest <NA> 0 <named list [65]>
#> 6 gaborcsardi clisymbols "" 18 <named list [65]>
#> 7 gaborcsardi cmaker <NA> 0 <named list [65]>
#> 8 gaborcsardi cmark <NA> 0 <named list [65]>
#> 9 gaborcsardi conditions <NA> 0 <named list [65]>
#> 10 gaborcsardi crayon <NA> 52 <named list [65]>
#> # … with 166 more rows
Звярніце ўвагу на выкарыстанне c("owner", "login"): гэта дазваляе нам атрымаць значэнне другога ўзроўню з укладзенага спісу owner. Альтэрнатыўны падыход складаецца ў тым, каб атрымаць увесь спіс owner і затым з дапамогай функцыі unnest_wider() змясціць кожны яго элемент у слупок:
Замест таго, каб разважаць над выбарам патрэбнай функцыі unnest_longer() або unnest_wider() Вы можаце выкарыстоўваць unnest_auto(). Гэтая функцыя выкарыстоўвае некалькі эўрыстычных метадаў для падбору найболей падыходнай функцыі для трансфармацыі дадзеных, і выводзіць паведамленне аб абраным спосабе.
got_chars мае ідэнтычную структуру з gh_users: гэта набор найменных спісаў, дзе кожны элемент унутранага спісу апісвае некаторы атрыбут персанажа Гульні Прастолаў. Прывядзенне got_chars да таблічнага ўвазе мы пачынаем са стварэння дата фрэйма, гэтак жа як і ў прыведзеных раней прыкладах, а затым перавядзем кожны элемент у асобны слупок:
chars <- tibble(char = got_chars)
chars
#> # A tibble: 30 x 1
#> char
#> <list>
#> 1 <named list [18]>
#> 2 <named list [18]>
#> 3 <named list [18]>
#> 4 <named list [18]>
#> 5 <named list [18]>
#> 6 <named list [18]>
#> 7 <named list [18]>
#> 8 <named list [18]>
#> 9 <named list [18]>
#> 10 <named list [18]>
#> # … with 20 more rows
chars2 <- chars %>% unnest_wider(char)
chars2
#> # A tibble: 30 x 18
#> url id name gender culture born died alive titles aliases father
#> <chr> <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 <chr>, spouse <chr>,
#> # allegiances <list>, books <list>, povBooks <list>, tvSeries <list>,
#> # playedBy <list>
Структура got_chars некалькі складаней, чым gh_users, т.я. некаторыя кампаненты спісу char самі па сабе з'яўляюцца спісам, у выніку мы атрымліваем слупы - спісы:
Вашы далейшыя дзеянні залежаць ад мэт аналізу. Магчыма, вам неабходна змясціць у радкі інфармацыю па кожнай кнізе і серыяле, у якім з'яўляецца персанаж:
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
#> <chr> <chr> <chr>
#> 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
Ці, магчыма, вы хочаце стварыць табліцу, якая дазволіць вам супаставіць персанажа і твор:
chars2 %>%
select(name, title = titles) %>%
unnest_longer(title)
#> # A tibble: 60 x 2
#> name title
#> <chr> <chr>
#> 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
(Звярніце ўвагу, на пустыя значэння "" ў полі title, гэта звязана з памылкамі дапушчанымі пры ўводзе дадзеных у got_chars: насамрэч персанажы для якіх няма адпаведных загалоўкаў кніг і серыялаў у полі title павінны мець вектар даўжыні 0, а не вектар даўжыні 1, які змяшчае пусты радок.)
Мы можам перапісаць прыведзены вышэй прыклад выкарыстоўваючы функцыю unnest_auto(). Гэты падыход зручны для разавага аналізу, але не варта спадзявацца на unnest_auto() для выкарыстання на рэгулярнай аснове. Справа ў тым, што калі ваша структура дадзеных зменіцца unnest_auto() можа памяняць абраны механізм пераўтварэння дадзеных, калі першапачаткова ён разгортваў слупкі-спісы ў радкі выкарыстоўваючы unnest_longer(), то пры змене структуры ўваходзяць дадзеных логіка можа быць зменена на карысць unnest_wider(), і выкарыстанне такога падыходу на пастаяннай аснове можа прывесці да непрадбачаных памылак.
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
#> <chr> <chr>
#> 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
Геакадаванне з дапамогай Google
Далей мы разгледзім больш складаную структуру дадзеных, якія атрымліваюцца ад службы геокодирования Google. Кэшаванне ўліковых дадзеных супярэчыць умовам працы з API Google maps, таму я спачатку напішу простую абалонку да API. Якая заснавана на захоўванні ключа API Google карт у зменным асяроддзі; калі ў зменных асяроддзі ў вас не захаваны ключ для працы з API Google Maps, фрагменты кода прадстаўленыя ў гэтым падзеле выконвацца не будуць.
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)
}
На шчасце, мы можам пакрокава вырашыць праблему пераўтварэння гэтых дадзеных у таблічны выгляд з дапамогай функцый tidyr. Каб зрабіць задачу крыху больш складанай і рэалістычнай, я пачну з геакадавання некалькіх гарадоў:
city <- c ( "Houston" , "LA" , "New York" , "Chicago" , "Springfield" ) city_geo <- purrr::map (city, geocode)
Атрыманы вынік я пераўтвору ў tibble, для зручнасці дадам слупок з адпаведнай назвай горада.
loc <- tibble(city = city, json = city_geo)
loc
#> # A tibble: 5 x 2
#> city json
#> <chr> <list>
#> 1 Houston <named list [2]>
#> 2 LA <named list [2]>
#> 3 New York <named list [2]>
#> 4 Chicago <named list [2]>
#> 5 Springfield <named list [2]>
Першы ўзровень змяшчае кампаненты status и result, які мы можам разгарнуць з дапамогай unnest_wider() :
loc %>%
unnest_wider(json)
#> # A tibble: 5 x 3
#> city results status
#> <chr> <list> <chr>
#> 1 Houston <list [1]> OK
#> 2 LA <list [1]> OK
#> 3 New York <list [1]> OK
#> 4 Chicago <list [1]> OK
#> 5 Springfield <list [1]> OK
Звярніце ўвагу, што results з'яўляецца шматузроўневым спісам. У большасці гарадоў ёсць 1 элемент (які прадстаўляе ўнікальнае значэнне, якое адпавядае API геокодирования), але ў Спрынгфілда іх два. Мы можам выцягнуць іх у асобныя радкі з дапамогай unnest_longer() :
loc %>%
unnest_wider(json) %>%
unnest_longer(results)
#> # A tibble: 5 x 3
#> city results status
#> <chr> <list> <chr>
#> 1 Houston <named list [5]> OK
#> 2 LA <named list [5]> OK
#> 3 New York <named list [5]> OK
#> 4 Chicago <named list [5]> OK
#> 5 Springfield <named list [5]> OK
Цяпер усе яны маюць аднолькавыя кампаненты, у чым можна пераканацца з дапамогай 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
#> <chr> <list> <chr> <list> <chr> <lis> <chr>
#> 1 Houst… <list [4]> Houston, TX, USA <named … ChIJAYWN… <lis… OK
#> 2 LA <list [4]> Los Angeles, CA… <named … ChIJE9on… <lis… OK
#> 3 New Y… <list [3]> New York, NY, U… <named … ChIJOwg_… <lis… OK
#> 4 Chica… <list [4]> Chicago, IL, USA <named … ChIJ7cv0… <lis… OK
#> 5 Sprin… <list [5]> Springfield, MO… <named … ChIJP5jI… <lis… OK
Мы можам знайсці каардынаты шыраты і даўгаты кожнага горада разгарнуўшы спіс 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
#> <chr> <list> <chr> <list> <list> <chr>
#> 1 Hous… <list [4]> Houston, TX, USA <name… <named … APPROXIMATE
#> 2 LA <list [4]> Los Angeles, CA… <name… <named … APPROXIMATE
#> 3 New … <list [3]> New York, NY, U… <name… <named … APPROXIMATE
#> 4 Chic… <list [4]> Chicago, IL, USA <name… <named … APPROXIMATE
#> 5 Spri… <list [5]> Springfield, MO… <name… <named … APPROXIMATE
#> # … with 4 more variables: viewport <list>, place_id <chr>, types <list>,
#> # status <chr>
А затым месцазнаходжанне, для чаго трэба разгарнуць location:
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
#> <chr> <list> <chr> <list> <dbl> <dbl> <chr>
#> 1 Hous… <list [4]> Houston, TX, USA <name… 29.8 -95.4 APPROXIMATE
#> 2 LA <list [4]> Los Angeles, CA… <name… 34.1 -118. APPROXIMATE
#> 3 New … <list [3]> New York, NY, U… <name… 40.7 -74.0 APPROXIMATE
#> 4 Chic… <list [4]> Chicago, IL, USA <name… 41.9 -87.6 APPROXIMATE
#> 5 Spri… <list [5]> Springfield, MO… <name… 37.2 -93.3 APPROXIMATE
#> # … with 4 more variables: viewport <list>, place_id <chr>, types <list>,
#> # status <chr>
Зноў жа, unnest_auto() спрашчае апісаную аперацыю з некаторымі рызыкамі, якія могуць быць выкліканыя зменай структуры ўваходзяць дадзеных:
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
#> <chr> <list> <chr> <list> <dbl> <dbl> <chr>
#> 1 Hous… <list [4]> Houston, TX, USA <name… 29.8 -95.4 APPROXIMATE
#> 2 LA <list [4]> Los Angeles, CA… <name… 34.1 -118. APPROXIMATE
#> 3 New … <list [3]> New York, NY, U… <name… 40.7 -74.0 APPROXIMATE
#> 4 Chic… <list [4]> Chicago, IL, USA <name… 41.9 -87.6 APPROXIMATE
#> 5 Spri… <list [5]> Springfield, MO… <name… 37.2 -93.3 APPROXIMATE
#> # … with 4 more variables: viewport <list>, place_id <chr>, types <list>,
#> # status <chr>
Мы таксама можам проста паглядзець на першы адрас для кожнага горада:
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
#> <chr> <list> <chr> <list> <dbl> <dbl> <chr>
#> 1 Hous… <list [4]> Houston, TX, USA <name… 29.8 -95.4 APPROXIMATE
#> 2 LA <list [4]> Los Angeles, CA… <name… 34.1 -118. APPROXIMATE
#> 3 New … <list [3]> New York, NY, U… <name… 40.7 -74.0 APPROXIMATE
#> 4 Chic… <list [4]> Chicago, IL, USA <name… 41.9 -87.6 APPROXIMATE
#> 5 Spri… <list [5]> Springfield, MO… <name… 37.2 -93.3 APPROXIMATE
#> # … with 4 more variables: viewport <list>, place_id <chr>, types <list>,
#> # status <chr>
Або выкарыстоўваць hoist() для шматузроўневага апускання, каб перайсці непасрэдна да lat и 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
#> <chr> <dbl> <dbl> <list>
#> 1 Houston 29.8 -95.4 <named list [2]>
#> 2 LA 34.1 -118. <named list [2]>
#> 3 New York 40.7 -74.0 <named list [2]>
#> 4 Chicago 41.9 -87.6 <named list [2]>
#> 5 Springfield 37.2 -93.3 <named list [2]>
Дыскаграфія Шарлы Гельфанд
У завяршэнні мы разгледзім самую складаную канструкцыю - дыскаграфію Шарлы Гельфанд. Як і ў прыведзеных вышэй прыкладах, мы пачынаем з канвертавання спісу ў дата фрэйм з адным слупком, а затым пашырым яго, каб кожны кампанент быў асобным слупком. Таксама я пераўтвору слупок date_added у адпаведны фармат даты і часу ў R.
discs <- tibble(disc = discog) %>%
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
#> <int> <dttm> <list> <int> <int>
#> 1 354823933 2019-02-16 17:48:59 <named list [11]> 7496378 0
#> 2 354092601 2019-02-13 14:13:11 <named list [11]> 4490852 0
#> 3 354091476 2019-02-13 14:07:23 <named list [11]> 9827276 0
#> 4 351244906 2019-02-02 11:39:58 <named list [11]> 9769203 0
#> 5 351244801 2019-02-02 11:39:37 <named list [11]> 7237138 0
#> 6 351052065 2019-02-01 20:40:53 <named list [11]> 13117042 0
#> 7 350315345 2019-01-29 15:48:37 <named list [11]> 7113575 0
#> 8 350315103 2019-01-29 15:47:22 <named list [11]> 10540713 0
#> 9 350314507 2019-01-29 15:44:08 <named list [11]> 11260950 0
#> 10 350314047 2019-01-29 15:41:35 <named list [11]> 11726853 0
#> # … with 145 more rows
На гэтым узроўні мы атрымалі інфармацыю аб тым, калі кожны дыск быў дададзены ў дыскаграфію Шарлы, але пры гэтым не бачым ніякіх дадзеных аб гэтых дысках. Для гэтага нам трэба пашырыць слупок basic_information:
discs %>% unnest_wider(basic_information)
#> Column name `id` must not be duplicated.
#> Use .name_repair to specify repair.
Нажаль мы атрымаем памылку, т.к. ўнутры спісу basic_information ёсць аднайменны слупок basic_information. Пры ўзнікненні падобнай памылкі, для таго, каб хутка вызначыць яе прычыну можна выкарыстоўваць names_repair = "unique":
Затым вы можаце далучыць іх зваротна да зыходнага набору дадзеных па меры неабходнасці.
Заключэнне
У ядро бібліятэкі tidyverse уваходзяць мноства карысных пакетаў аб'яднаныя агульнай філасофіяй апрацоўкі дадзеных.
У гэтым артыкуле мы разабралі сямейства функцый unnest_*(), Якія накіраваны на працу з выманне элементаў з укладзеных спісаў. Дадзены пакет утрымоўвае мноства іншых карысных функцый, якія спрашчаюць пераўтварэнне дадзеных паводле канцэпцыі. Tidy Data.