Π Π°Π·Π²ΠΎΡ€Π°Ρ‡ΠΈΠ²Π°Π΅ΠΌ Π²Π»ΠΎΠΆΠ΅Π½Π½Ρ‹Π΅ столбцы β€” списки с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ языка R (ΠΏΠ°ΠΊΠ΅Ρ‚ tidyr ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ сСмСйства unnest)

Π’ Π±ΠΎΠ»ΡŒΡˆΠΈΠ½ΡΡ‚Π²Π΅ случаСв ΠΏΡ€ΠΈ Ρ€Π°Π±ΠΎΡ‚Π΅ с ΠΎΡ‚Π²Π΅Ρ‚ΠΎΠΌ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½Π½Ρ‹ΠΌ ΠΎΡ‚ API, ΠΈΠ»ΠΈ с Π»ΡŽΠ±Ρ‹ΠΌΠΈ Π΄Ρ€ΡƒΠ³ΠΈΠΌΠΈ Π΄Π°Π½Π½Ρ‹ΠΌΠΈ ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΈΠΌΠ΅ΡŽΡ‚ ΡΠ»ΠΎΠΆΠ½ΡƒΡŽ Π΄Ρ€Π΅Π²ΠΎΠ²ΠΈΠ΄Π½ΡƒΡŽ структуру, Π²Ρ‹ ΡΡ‚Π°Π»ΠΊΠΈΠ²Π°Π΅Ρ‚Π΅ΡΡŒ с Ρ„ΠΎΡ€ΠΌΠ°Ρ‚Π°ΠΌΠΈ JSON ΠΈ XML.

Π­Ρ‚ΠΈ Ρ„ΠΎΡ€ΠΌΠ°Ρ‚Ρ‹ ΠΈΠΌΠ΅ΡŽΡ‚ мноТСство прСимущСств: ΠΎΠ½ΠΈ достаточно ΠΊΠΎΠΌΠΏΠ°ΠΊΡ‚Π½ΠΎ хранят Π΄Π°Π½Π½Ρ‹Π΅ ΠΈ ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡŽΡ‚ ΠΈΠ·Π±Π΅ΠΆΠ°Ρ‚ΡŒ излишнСго дублирования ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠΈ.

ΠœΠΈΠ½ΡƒΡΠΎΠΌ Π΄Π°Π½Π½Ρ‹Ρ… Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ΠΎΠ² являСтся ΡΠ»ΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ ΠΈΡ… ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ ΠΈ Π°Π½Π°Π»ΠΈΠ·Π°. НСструктурированныС Π΄Π°Π½Π½Ρ‹Π΅ Π½Π΅Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π² вычислСниях ΠΈ нСльзя ΡΡ‚Ρ€ΠΎΠΈΡ‚ΡŒ Π½Π° ΠΈΡ… основС Π²ΠΈΠ·ΡƒΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΡŽ.

Π Π°Π·Π²ΠΎΡ€Π°Ρ‡ΠΈΠ²Π°Π΅ΠΌ Π²Π»ΠΎΠΆΠ΅Π½Π½Ρ‹Π΅ столбцы — списки с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ языка R (ΠΏΠ°ΠΊΠ΅Ρ‚ tidyr ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ сСмСйства unnest)

Данная ΡΡ‚Π°Ρ‚ΡŒΡ являСтся логичСским ΠΏΡ€ΠΎΠ΄ΠΎΠ»ΠΆΠ΅Π½ΠΈΠ΅ΠΌ ΠΏΡƒΠ±Π»ΠΈΠΊΠ°Ρ†ΠΈΠΈ "R ΠΏΠ°ΠΊΠ΅Ρ‚ tidyr ΠΈ Π΅Π³ΠΎ Π½ΠΎΠ²Ρ‹Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ pivot_longer ΠΈ pivot_wider". Она ΠΏΠΎΠΌΠΎΠΆΠ΅Ρ‚ Π²Π°ΠΌ привСсти нСструктурированныС конструкции Π΄Π°Π½Π½Ρ‹Ρ… ΠΊ ΠΏΡ€ΠΈΠ²Ρ‹Ρ‡Π½ΠΎΠΌΡƒ, ΠΈ ΠΏΡ€ΠΈΠ³ΠΎΠ΄Π½ΠΎΠΌΡƒ для Π°Π½Π°Π»ΠΈΠ·Π° Ρ‚Π°Π±Π»ΠΈΡ‡Π½ΠΎΠΌΡƒ Π²ΠΈΠ΄Ρƒ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΠΏΠ°ΠΊΠ΅Ρ‚Π° tidyr, входящСго Π² ядро Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ tidyverse, ΠΈ Π΅Π³ΠΎ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ сСмСйства unnest_*().

Π‘ΠΎΠ΄Π΅Ρ€ΠΆΠ°Π½ΠΈΠ΅

Если Π²Ρ‹ ΠΈΠ½Ρ‚Π΅Ρ€Π΅ΡΡƒΠ΅Ρ‚Π΅ΡΡŒ Π°Π½Π°Π»ΠΈΠ·ΠΎΠΌ Π΄Π°Π½Π½Ρ‹Ρ… Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ Π²Π°ΠΌ Π±ΡƒΠ΄ΡƒΡ‚ интСрСсны ΠΌΠΎΠΈ telegram ΠΈ youtube ΠΊΠ°Π½Π°Π»Ρ‹. Π‘ΠΎΠ»ΡŒΡˆΠ°Ρ Ρ‡Π°ΡΡ‚ΡŒ ΠΊΠΎΠ½Ρ‚Π΅Π½Ρ‚Π° ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… посвящСны языку R.

  1. Π’Π²Π΅Π΄Π΅Π½ΠΈΠ΅
  2. ΠŸΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΠΈ GitHub
  3. Π Π΅ΠΏΠΎΠ·ΠΈΡ‚ΠΎΡ€ΠΈΠΈ Github
  4. ΠŸΠ΅Ρ€ΡΠΎΠ½Π°ΠΆΠΈ Π˜Π³Ρ€Ρ‹ ΠŸΡ€Π΅ΡΡ‚ΠΎΠ»ΠΎΠ²
  5. Π“Π΅ΠΎΠΊΠΎΠ΄ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Google
  6. Дискография Π¨Π°Ρ€Π»Ρ‹ Π“Π΅Π»ΡŒΡ„Π°Π½Π΄
  7. Π—Π°ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅

Π’Π²Π΅Π΄Π΅Π½ΠΈΠ΅

Rectangling (ΠΏΡ€ΠΈΠΌ. ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄Ρ‡ΠΈΠΊΠ°, Π½Π΅ нашСл Π°Π΄Π΅ΠΊΠ²Π°Ρ‚Π½Ρ‹Ρ… Π²Π°Ρ€ΠΈΠ°Π½Ρ‚ΠΎΠ² ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄Π° этого Ρ‚Π΅Ρ€ΠΌΠΈΠ½Π°, поэтому оставим Π΅Π³ΠΎ ΠΊΠ°ΠΊ Π΅ΡΡ‚ΡŒ.) β€” это процСсс привСдСния Π½Π΅ структурированных Π΄Π°Π½Π½Ρ‹Ρ… с Π²Π»ΠΎΠΆΠ΅Π½Π½Ρ‹ΠΌΠΈ массивами ΠΊ Π΄Π²ΡƒΡ…ΠΌΠ΅Ρ€Π½ΠΎΠΉ Ρ‚Π°Π±Π»ΠΈΡ†Π΅, состоящСй ΠΈΠ· ΠΏΡ€ΠΈΠ²Ρ‹Ρ‡Π½Ρ‹Ρ… Π½Π°ΠΌ строк ΠΈ столбцов. Π’ tidyr Π΅ΡΡ‚ΡŒ нСсколько Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΏΠΎΠΌΠΎΠ³ΡƒΡ‚ Π²Π°ΠΌ Ρ€Π°Π·Π²Π΅Ρ€Π½ΡƒΡ‚ΡŒ Π²Π»ΠΎΠΆΠ΅Π½Π½Ρ‹Π΅ столбцы-списки ΠΈ привСсти Π΄Π°Π½Π½Ρ‹Π΅ ΠΊ ΠΏΡ€ΡΠΌΠΎΡƒΠ³ΠΎΠ»ΡŒΠ½ΠΎΠΉ, Ρ‚Π°Π±Π»ΠΈΡ‡Π½ΠΎΠΉ Ρ„ΠΎΡ€ΠΌΠ΅:

  • unnest_longer() Π±Π΅Ρ€Π΅Ρ‚ ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ элСмСнт списка-столбца ΠΈ создаСт Π½ΠΎΠ²ΡƒΡŽ строку.
  • unnest_wider() Π±Π΅Ρ€Π΅Ρ‚ ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ элСмСнт списка-столбца ΠΈ создаСт Π½ΠΎΠ²Ρ‹ΠΉ столбСц.
  • unnest_auto() автоматичСски опрСдСляСт ΠΊΠ°ΠΊΡƒΡŽ ΠΈΠ· Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ Π»ΡƒΡ‡ΡˆΠ΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ
    unnest_longer() ΠΈΠ»ΠΈ unnest_wider().
  • hoist() ΠΏΠΎΡ…ΠΎΠΆΠ° Π½Π° unnest_wider() Π½ΠΎ ΠΎΡ‚Π±ΠΈΡ€Π°Π΅Ρ‚ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΡƒΠΊΠ°Π·Π°Π½Π½Ρ‹Π΅ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ ΠΈ позволяСт Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ с нСсколькими уровнями влоТСнности.

Π‘ΠΎΠ»ΡŒΡˆΠΈΠ½ΡΡ‚Π²ΠΎ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌ связанных с ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ΠΌ Π½Π΅ структурированных Π΄Π°Π½Π½Ρ‹Ρ… с нСсколькими уровнями влоТСнности ΠΊ Π΄Π²ΡƒΡ…ΠΌΠ΅Ρ€Π½ΠΎΠΉ Ρ‚Π°Π±Π»ΠΈΡ†Π΅ ΠΌΠΎΠΆΠ½ΠΎ Ρ€Π΅ΡˆΠΈΡ‚ΡŒ, комбинируя пСрСчислСнныС Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ с dplyr.

Для дСмонстрации этих ΠΏΡ€ΠΈΠ΅ΠΌΠΎΠ², ΠΌΡ‹ Π±ΡƒΠ΄Π΅ΠΌ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΏΠ°ΠΊΠ΅Ρ‚ repurrrsive, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ прСдоставляСт нСсколько слоТных, ΠΌΠ½ΠΎΠ³ΠΎΡƒΡ€ΠΎΠ²Π½Π΅Π²Ρ‹Ρ… списков, ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½Π½Ρ‹Ρ… ΠΈΠ· Π²Π΅Π±-API.

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

ΠŸΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΠΈ GitHub

НачнСм с gh_users, списка, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ содСрТит ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ ΠΎ ΡˆΠ΅ΡΡ‚ΠΈ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡΡ… GitHub. Для Π½Π°Ρ‡Π°Π»Π° ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΡƒΠ΅ΠΌ список gh_users Π² tibble Ρ„Ρ€Π΅ΠΉΠΌ.:

users <-   tibble( user = gh_users ) 

Π­Ρ‚ΠΎ каТСтся Π½Π΅ΠΌΠ½ΠΎΠ³ΠΎ Π½Π΅Π»ΠΎΠ³ΠΈΡ‡Π½Ρ‹ΠΌ: Π·Π°Ρ‡Π΅ΠΌ ΠΏΡ€ΠΈΠ²ΠΎΠ΄ΠΈΡ‚ΡŒ список gh_users, ΠΊ Π±ΠΎΠ»Π΅Π΅ слоТной структурС Π΄Π°Π½Π½Ρ‹Ρ…? Но Ρƒ Π΄Π°Ρ‚Π° Ρ„Ρ€Π΅ΠΉΠΌΠ° Π΅ΡΡ‚ΡŒ большоС прСимущСство: ΠΎΠ½ ΠΎΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΠ΅Ρ‚ нСсколько Π²Π΅ΠΊΡ‚ΠΎΡ€ΠΎΠ², Ρ‚Π°ΠΊ Ρ‡Ρ‚ΠΎ всС отслСТиваСтся Π² ΠΎΠ΄Π½ΠΎΠΌ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π΅.

ΠšΠ°ΠΆΠ΄Ρ‹ΠΉ элСмСнт ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° users прСдставляСт собой ΠΈΠΌΠ΅Π½ΠΎΠ²Π°Π½Π½Ρ‹ΠΉ список, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ элСмСнт прСдставляСт столбСц.

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"

Π•ΡΡ‚ΡŒ Π΄Π²Π° способа ΠΏΡ€Π΅Π²Ρ€Π°Ρ‚ΠΈΡ‚ΡŒ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ списка Π² столбцы. unnest_wider() Π±Π΅Ρ€Π΅Ρ‚ ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ ΠΈ создаСт Π½ΠΎΠ²Ρ‹ΠΉ столбСц:

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.…
#> # … with 23 more variables: 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>

Π’ этом случаС ΠΌΡ‹ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠ»ΠΈ Ρ‚Π°Π±Π»ΠΈΡ†Ρƒ ΡΠΎΡΡ‚ΠΎΡΡ‰ΡƒΡŽ ΠΈΠ· 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() удаляСт ΡƒΠΊΠ°Π·Π°Π½Π½Ρ‹Π΅ ΠΈΠΌΠ΅Π½ΠΎΠ²Π°Π½Π½Ρ‹Π΅ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Ρ‹ ΠΈΠ· списка-столбца user, поэтому Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Ρ€Π°ΡΡΠΌΠ°Ρ‚Ρ€ΠΈΠ²Π°Ρ‚ΡŒ hoist() ΠΊΠ°ΠΊ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Ρ‰Π΅Π½ΠΈΠ΅ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ² ΠΈΠ· Π²Π½ΡƒΡ‚Ρ€Π΅Π½Π½Π΅Π³ΠΎ списка Π΄Π°Ρ‚Π° Ρ„Ρ€Π΅ΠΉΠΌΠ° ΠΊ Π΅Π³ΠΎ Π²Π΅Ρ€Ρ…Π½Π΅ΠΌΡƒ ΡƒΡ€ΠΎΠ²Π½ΡŽ.

Π Π΅ΠΏΠΎΠ·ΠΈΡ‚ΠΎΡ€ΠΈΠΈ Github

Π’Ρ‹Ρ€Π°Π²Π½ΠΈΠ²Π°Π½ΠΈΠ΅ списка gh_repos ΠΌΡ‹ Π½Π°Ρ‡ΠΈΠ½Π°Π΅ΠΌ Π°Π½Π°Π»ΠΎΠ³ΠΈΡ‡Π½ΠΎ, прСобразуя Π΅Π³ΠΎ Π² tibble:

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

На этот Ρ€Π°Π· элСмСнты user ΠΏΡ€Π΅Π΄ΡΡ‚Π°Π²Π»ΡΡŽΡ‚ собой список Ρ€Π΅ΠΏΠΎΠ·ΠΈΡ‚ΠΎΡ€ΠΈΠ΅Π², ΠΏΡ€ΠΈΠ½Π°Π΄Π»Π΅ΠΆΠ°Ρ‰ΠΈΡ… этому ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŽ. ΠšΠ°ΠΆΠ΄Ρ‹ΠΉ Ρ€Π΅ΠΏΠΎΠ·ΠΈΡ‚ΠΎΡ€ΠΈΠΉ являСтся ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΌ наблюдСниСм, поэтому согласно ΠΊΠΎΠ½Ρ†Π΅ΠΏΡ†ΠΈΠΈ Π°ΠΊΠΊΡƒΡ€Π°Ρ‚Π½Ρ‹Ρ… Π΄Π°Π½Π½Ρ‹Ρ… (ΠΏΡ€ΠΈΠΌ. 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() ΠΏΠΎΠΌΠ΅ΡΡ‚ΠΈΡ‚ΡŒ ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ Π΅Π³ΠΎ элСмСнт Π² столбСц:

repos %>% 
  hoist(repo, owner = "owner") %>% 
  unnest_wider(owner)
#> # A tibble: 176 x 18
#>    login     id avatar_url gravatar_id url   html_url followers_url
#>    <chr>  <int> <chr>      <chr>       <chr> <chr>    <chr>        
#>  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.…
#> # … with 166 more rows, and 11 more variables: 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>, repo <list>

ВмСсто Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎ Π±Ρ‹ Ρ€Π°Π·ΠΌΡ‹ΡˆΠ»ΡΡ‚ΡŒ Π½Π°Π΄ Π²Ρ‹Π±ΠΎΡ€ΠΎΠΌ Π½ΡƒΠΆΠ½ΠΎΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ unnest_longer() ΠΈΠ»ΠΈ unnest_wider() Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ unnest_auto(). Π­Ρ‚Π° функция ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ нСсколько эвристичСских ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΎΠ² для ΠΏΠΎΠ΄Π±ΠΎΡ€Π° Π½Π°ΠΈΠ±ΠΎΠ»Π΅Π΅ подходящСй Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ для трансформации Π΄Π°Π½Π½Ρ‹Ρ…, ΠΈ Π²Ρ‹Π²ΠΎΠ΄ΠΈΡ‚ сообщСниС ΠΎ Π²Ρ‹Π±Ρ€Π°Π½Π½ΠΎΠΌ способС.

tibble(repo = gh_repos) %>% 
  unnest_auto(repo) %>% 
  unnest_auto(repo)
#> Using `unnest_longer(repo)`; no element has names
#> Using `unnest_wider(repo)`; elements have 68 names in common
#> # A tibble: 176 x 67
#>        id name  full_name owner private html_url description fork  url  
#>     <int> <chr> <chr>     <lis> <lgl>   <chr>    <chr>       <lgl> <chr>
#>  1 6.12e7 after gaborcsa… <nam… FALSE   https:/… Run Code i… FALSE http…
#>  2 4.05e7 argu… gaborcsa… <nam… FALSE   https:/… Declarativ… FALSE http…
#>  3 3.64e7 ask   gaborcsa… <nam… FALSE   https:/… Friendly C… FALSE http…
#>  4 3.49e7 base… gaborcsa… <nam… FALSE   https:/… Do we get … FALSE http…
#>  5 6.16e7 cite… gaborcsa… <nam… FALSE   https:/… Test R pac… TRUE  http…
#>  6 3.39e7 clis… gaborcsa… <nam… FALSE   https:/… Unicode sy… FALSE http…
#>  7 3.72e7 cmak… gaborcsa… <nam… FALSE   https:/… port of cm… TRUE  http…
#>  8 6.80e7 cmark gaborcsa… <nam… FALSE   https:/… CommonMark… TRUE  http…
#>  9 6.32e7 cond… gaborcsa… <nam… FALSE   https:/… <NA>        TRUE  http…
#> 10 2.43e7 cray… gaborcsa… <nam… FALSE   https:/… R package … FALSE http…
#> # … with 166 more rows, and 58 more variables: forks_url <chr>,
#> #   keys_url <chr>, collaborators_url <chr>, teams_url <chr>,
#> #   hooks_url <chr>, issue_events_url <chr>, events_url <chr>,
#> #   assignees_url <chr>, branches_url <chr>, tags_url <chr>,
#> #   blobs_url <chr>, git_tags_url <chr>, git_refs_url <chr>,
#> #   trees_url <chr>, statuses_url <chr>, languages_url <chr>,
#> #   stargazers_url <chr>, contributors_url <chr>, subscribers_url <chr>,
#> #   subscription_url <chr>, commits_url <chr>, git_commits_url <chr>,
#> #   comments_url <chr>, issue_comment_url <chr>, contents_url <chr>,
#> #   compare_url <chr>, merges_url <chr>, archive_url <chr>,
#> #   downloads_url <chr>, issues_url <chr>, pulls_url <chr>,
#> #   milestones_url <chr>, notifications_url <chr>, labels_url <chr>,
#> #   releases_url <chr>, deployments_url <chr>, created_at <chr>,
#> #   updated_at <chr>, pushed_at <chr>, git_url <chr>, ssh_url <chr>,
#> #   clone_url <chr>, svn_url <chr>, size <int>, stargazers_count <int>,
#> #   watchers_count <int>, language <chr>, has_issues <lgl>,
#> #   has_downloads <lgl>, has_wiki <lgl>, has_pages <lgl>,
#> #   forks_count <int>, open_issues_count <int>, forks <int>,
#> #   open_issues <int>, watchers <int>, default_branch <chr>,
#> #   homepage <chr>

ΠŸΠ΅Ρ€ΡΠΎΠ½Π°ΠΆΠΈ Π˜Π³Ρ€Ρ‹ ΠŸΡ€Π΅ΡΡ‚ΠΎΠ»ΠΎΠ²

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_if(is.list)
#> # A tibble: 30 x 7
#>    titles    aliases    allegiances books     povBooks  tvSeries  playedBy 
#>    <list>    <list>     <list>      <list>    <list>    <list>    <list>   
#>  1 <chr [3]> <chr [4]>  <chr [1]>   <chr [3]> <chr [2]> <chr [6]> <chr [1]>
#>  2 <chr [2]> <chr [11]> <chr [1]>   <chr [2]> <chr [4]> <chr [6]> <chr [1]>
#>  3 <chr [2]> <chr [1]>  <chr [1]>   <chr [3]> <chr [2]> <chr [1]> <chr [1]>
#>  4 <chr [1]> <chr [1]>  <???>       <chr [1]> <chr [1]> <chr [1]> <chr [1]>
#>  5 <chr [1]> <chr [1]>  <chr [1]>   <chr [3]> <chr [2]> <chr [2]> <chr [1]>
#>  6 <chr [1]> <chr [1]>  <???>       <chr [2]> <chr [1]> <chr [1]> <chr [1]>
#>  7 <chr [1]> <chr [1]>  <???>       <chr [2]> <chr [1]> <chr [1]> <chr [1]>
#>  8 <chr [1]> <chr [1]>  <chr [1]>   <chr [4]> <chr [1]> <chr [1]> <chr [1]>
#>  9 <chr [5]> <chr [11]> <chr [1]>   <chr [1]> <chr [4]> <chr [6]> <chr [1]>
#> 10 <chr [4]> <chr [5]>  <chr [2]>   <chr [1]> <chr [3]> <chr [5]> <chr [1]>
#> # … with 20 more rows

Π’Π°ΡˆΠΈ дальнСйшиС дСйствия зависят ΠΎΡ‚ Ρ†Π΅Π»Π΅ΠΉ Π°Π½Π°Π»ΠΈΠ·Π°. Π’ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ, Π²Π°ΠΌ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ ΠΏΠΎΠΌΠ΅ΡΡ‚ΠΈΡ‚ΡŒ Π² строки ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ ΠΏΠΎ ΠΊΠ°ΠΆΠ΄ΠΎΠΉ ΠΊΠ½ΠΈΠ³Π΅ ΠΈ сСриалС, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ появляСтся пСрсонаТ:

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

Бписок, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ эта функция, довольно слоТСн:

houston <- geocode("Houston TX")
str(houston)
#> List of 2
#>  $ results:List of 1
#>   ..$ :List of 5
#>   .. ..$ address_components:List of 4
#>   .. .. ..$ :List of 3
#>   .. .. .. ..$ long_name : chr "Houston"
#>   .. .. .. ..$ short_name: chr "Houston"
#>   .. .. .. ..$ types     :List of 2
#>   .. .. .. .. ..$ : chr "locality"
#>   .. .. .. .. ..$ : chr "political"
#>   .. .. ..$ :List of 3
#>   .. .. .. ..$ long_name : chr "Harris County"
#>   .. .. .. ..$ short_name: chr "Harris County"
#>   .. .. .. ..$ types     :List of 2
#>   .. .. .. .. ..$ : chr "administrative_area_level_2"
#>   .. .. .. .. ..$ : chr "political"
#>   .. .. ..$ :List of 3
#>   .. .. .. ..$ long_name : chr "Texas"
#>   .. .. .. ..$ short_name: chr "TX"
#>   .. .. .. ..$ types     :List of 2
#>   .. .. .. .. ..$ : chr "administrative_area_level_1"
#>   .. .. .. .. ..$ : chr "political"
#>   .. .. ..$ :List of 3
#>   .. .. .. ..$ long_name : chr "United States"
#>   .. .. .. ..$ short_name: chr "US"
#>   .. .. .. ..$ types     :List of 2
#>   .. .. .. .. ..$ : chr "country"
#>   .. .. .. .. ..$ : chr "political"
#>   .. ..$ formatted_address : chr "Houston, TX, USA"
#>   .. ..$ geometry          :List of 4
#>   .. .. ..$ bounds       :List of 2
#>   .. .. .. ..$ northeast:List of 2
#>   .. .. .. .. ..$ lat: num 30.1
#>   .. .. .. .. ..$ lng: num -95
#>   .. .. .. ..$ southwest:List of 2
#>   .. .. .. .. ..$ lat: num 29.5
#>   .. .. .. .. ..$ lng: num -95.8
#>   .. .. ..$ location     :List of 2
#>   .. .. .. ..$ lat: num 29.8
#>   .. .. .. ..$ lng: num -95.4
#>   .. .. ..$ location_type: chr "APPROXIMATE"
#>   .. .. ..$ viewport     :List of 2
#>   .. .. .. ..$ northeast:List of 2
#>   .. .. .. .. ..$ lat: num 30.1
#>   .. .. .. .. ..$ lng: num -95
#>   .. .. .. ..$ southwest:List of 2
#>   .. .. .. .. ..$ lat: num 29.5
#>   .. .. .. .. ..$ lng: num -95.8
#>   .. ..$ place_id          : chr "ChIJAYWNSLS4QIYROwVl894CDco"
#>   .. ..$ types             :List of 2
#>   .. .. ..$ : chr "locality"
#>   .. .. ..$ : chr "political"
#>  $ status : chr "OK"

К ΡΡ‡Π°ΡΡ‚ΡŒΡŽ, ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ пошагово Ρ€Π΅ΡˆΠΈΡ‚ΡŒ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡƒ прСобразования этих Π΄Π°Π½Π½Ρ‹Ρ… Π² Ρ‚Π°Π±Π»ΠΈΡ‡Π½Ρ‹ΠΉ Π²ΠΈΠ΄ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ 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":

discs %>% unnest_wider(basic_information, names_repair = "unique")
#> New names:
#> * id -> id...6
#> * id -> id...14
#> # A 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 
#> # … with 145 more rows, and 7 more variables: formats <list>,
#> #   cover_image <chr>, resource_url <chr>, master_id <int>,
#> #   master_url <chr>, id...14 <int>, rating <int>

ΠŸΡ€ΠΎΠ±Π»Π΅ΠΌΠ° Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ basic_information повторяСт столбСц id ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Ρ‚Π°ΠΊΠΆΠ΅ хранится Π½Π° Π²Π΅Ρ€Ρ…Π½Π΅ΠΌ ΡƒΡ€ΠΎΠ²Π½Π΅, поэтому ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ просто ΡƒΠ΄Π°Π»ΠΈΡ‚ΡŒ Π΅Π³ΠΎ:

discs %>% 
  select(-id) %>% 
  unnest_wider(basic_information)
#> # A tibble: 155 x 14
#>    instance_id date_added          labels  year artists     id 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 
#> # … with 145 more rows, and 6 more variables: formats <list>,
#> #   cover_image <chr>, resource_url <chr>, master_id <int>,
#> #   master_url <chr>, rating <int>

Π’ качСствС Π°Π»ΡŒΡ‚Π΅Ρ€Π½Π°Ρ‚ΠΈΠ²Ρ‹, ΠΌΡ‹ ΠΌΠΎΠ³Π»ΠΈ Π±Ρ‹ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ hoist():

discs %>% 
  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
#>          <int> <dttm>              <chr> <int> <chr> <chr> 
#>  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 <list>,
#> #   id <int>, rating <int>

Π—Π΄Π΅ΡΡŒ я быстро извлСкаю имя ΠΏΠ΅Ρ€Π²ΠΎΠ³ΠΎ Π»Π΅ΠΉΠ±Π»Π° ΠΈ исполнитСля ΠΏΠΎ индСксу, ΠΏΠΎΠ³Ρ€ΡƒΠ·ΠΈΠ²ΡˆΠΈΡΡŒ Π²ΠΎ Π²Π»ΠΎΠΆΠ΅Π½Π½Ρ‹ΠΉ список.

Π‘ΠΎΠ»Π΅Π΅ систСматичСский ΠΏΠΎΠ΄Ρ…ΠΎΠ΄ Π·Π°ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ΡΡ Π² создании ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹Ρ… Ρ‚Π°Π±Π»ΠΈΡ† для исполнитСля ΠΈ Π»Π΅ΠΉΠ±Π»Π°:

discs %>% 
  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
#>       <int> <chr> <chr>       <chr> <chr>  <chr> <chr>                <int>
#>  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
#> # … with 157 more rows

discs %>% 
  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  
#>       <int> <chr>        <chr> <chr>    <chr>
#>  1  7496378 Numbered     Black Cassette 1    
#>  2  4490852 LP           <NA>  Vinyl    1    
#>  3  9827276 "7""        <NA>  Vinyl    1    
#>  4  9827276 45 RPM       <NA>  Vinyl    1    
#>  5  9827276 EP           <NA>  Vinyl    1    
#>  6  9769203 LP           <NA>  Vinyl    1    
#>  7  9769203 Album        <NA>  Vinyl    1    
#>  8  7237138 "7""        <NA>  Vinyl    1    
#>  9  7237138 45 RPM       <NA>  Vinyl    1    
#> 10 13117042 "7""        <NA>  Vinyl    1    
#> # … with 270 more rows

Π—Π°Ρ‚Π΅ΠΌ Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΏΡ€ΠΈΡΠΎΠ΅Π΄ΠΈΠ½ΠΈΡ‚ΡŒ ΠΈΡ… ΠΎΠ±Ρ€Π°Ρ‚Π½ΠΎ ΠΊ исходному Π½Π°Π±ΠΎΡ€Ρƒ Π΄Π°Π½Π½Ρ‹Ρ… ΠΏΠΎ ΠΌΠ΅Ρ€Π΅ нСобходимости.

Π—Π°ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅

Π’ ядро Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ tidyverse входят мноТСство ΠΏΠΎΠ»Π΅Π·Π½Ρ‹Ρ… ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ² ΠΎΠ±ΡŠΠ΅Π΄ΠΈΠ½Ρ‘Π½Π½Ρ‹Π΅ ΠΎΠ±Ρ‰Π΅ΠΉ философиСй ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ Π΄Π°Π½Π½Ρ‹Ρ….

Π’ этой ΡΡ‚Π°Ρ‚ΡŒΠ΅ ΠΌΡ‹ Ρ€Π°Π·ΠΎΠ±Ρ€Π°Π»ΠΈ сСмСйство Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ unnest_*(), ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π½Π°ΠΏΡ€Π°Π²Π»Π΅Π½Ρ‹ Π½Π° Ρ€Π°Π±ΠΎΡ‚Ρƒ с ΠΈΠ·Π²Π»Π΅Ρ‡Π΅Π½ΠΈΠ΅ΠΌ элСмСнтов ΠΈΠ· Π²Π»ΠΎΠΆΠ΅Π½Π½Ρ‹Ρ… списков. Π”Π°Π½Π½Ρ‹ΠΉ ΠΏΠ°ΠΊΠ΅Ρ‚ содСрТит мноТСство Π΄Ρ€ΡƒΠ³ΠΈΡ… ΠΏΠΎΠ»Π΅Π·Π½Ρ‹Ρ… Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΡƒΠΏΡ€ΠΎΡ‰Π°ΡŽΡ‚ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅ Π΄Π°Π½Π½Ρ‹Ρ… согласно ΠΊΠΎΠ½Ρ†Π΅ΠΏΡ†ΠΈΠΈ Tidy Data.

Π˜ΡΡ‚ΠΎΡ‡Π½ΠΈΠΊ: habr.com