R бумасы tidyr және оның жаңа функциялары pivot_longer және pivot_wider

Пакет ұқыпты R тіліндегі ең танымал кітапханалардың бірінің өзегіне енгізілген - ұқыптылық.
Пакеттің негізгі мақсаты – деректерді нақты пішінге келтіру.

Habré сайтында қазірдің өзінде қол жетімді жариялау осы пакетке арналған, бірақ ол 2015 жылдан басталады. Мен сізге бірнеше күн бұрын оның авторы Хедли Уикхэм жариялаған ең өзекті өзгерістер туралы айтқым келеді.

R бумасы tidyr және оның жаңа функциялары pivot_longer және pivot_wider

S.J.K.: gather() және spread() ескіреді ме?

Хэдли Уикхэм: Белгілі бір дәрежеде. Біз бұдан былай бұл функцияларды пайдалануды ұсынбаймыз және олардағы қателерді түзетеміз, бірақ олар ағымдағы күйінде пакетте болуын жалғастырады.

Мазмұны

Егер сіз деректерді талдауға қызығушылық танытсаңыз, сізді мені қызықтыруы мүмкін жеделхат и YouTube арналар. Мазмұнның көп бөлігі R тіліне арналған.

TidyData тұжырымдамасы

Максат ұқыпты — деректерді ұқыпты деп аталатын пішінге келтіруге көмектеседі. Таза деректер мына жердегі деректер:

  • Әрбір айнымалы бағанда орналасқан.
  • Әрбір бақылау жол болып табылады.
  • Әрбір мән ұяшық болып табылады.

Талдау жүргізген кезде жинақы деректерде берілген деректермен жұмыс істеу әлдеқайда жеңіл және ыңғайлы.

Tidyr пакетіне кіретін негізгі функциялар

tidyr кестелерді түрлендіруге арналған функциялар жиынтығын қамтиды:

  • fill() — бағандағы жетіспейтін мәндерді алдыңғы мәндермен толтыру;
  • separate() — бөлгіштің көмегімен бір өрісті бірнешеге бөледі;
  • unite() — бірнеше өрістерді бір жерге біріктіру операциясын, функцияның кері әрекетін орындайды separate();
  • pivot_longer() — деректерді кең форматтан ұзын форматқа түрлендіретін функция;
  • pivot_wider() - деректерді ұзын форматтан кең форматқа түрлендіретін функция. Функциямен орындалатын жұмыстың кері әрекеті pivot_longer().
  • gather()ескірген — деректерді кең форматтан ұзын форматқа түрлендіретін функция;
  • spread()ескірген - деректерді ұзын форматтан кең форматқа түрлендіретін функция. Функциямен орындалатын жұмыстың кері әрекеті gather().

Деректерді кең форматтан ұзын форматқа және керісінше түрлендірудің жаңа тұжырымдамасы

Бұрын мұндай түрлендіру үшін функциялар қолданылған gather() и spread(). Осы функциялардың өмір сүрген жылдарында көптеген пайдаланушылар үшін, соның ішінде пакет авторы үшін бұл функциялардың атаулары мен олардың дәлелдері анық емес екені белгілі болды және оларды табуда және осы функциялардың қайсысы түрлендіретінін түсінуде қиындықтар туғызды. кең пішімнен ұзын пішімге дейінгі күн шеңбері және керісінше.

Осыған байланысты, в ұқыпты Күн кадрларын түрлендіруге арналған екі жаңа маңызды функция қосылды.

Жаңа мүмкіндіктер pivot_longer() и pivot_wider() пакеттегі кейбір мүмкіндіктерден шабыттанды cдата, Джон Маунт пен Нина Зумель жасаған.

tidyr 0.8.3.9000 ең соңғы нұсқасын орнату

Буманың жаңа, ең соңғы нұсқасын орнату үшін ұқыпты 0.8.3.9000, жаңа мүмкіндіктер қолжетімді болса, келесі кодты пайдаланыңыз.

devtools::install_github("tidyverse/tidyr")

Жазу кезінде бұл функциялар GitHub-тағы пакеттің әзірлеуші ​​нұсқасында ғана қолжетімді.

Жаңа мүмкіндіктерге көшу

Шындығында, ескі сценарийлерді жаңа функциялармен жұмыс істеуге көшіру қиын емес, жақсы түсіну үшін мен ескі функциялардың құжаттамасынан мысал аламын және жаңаларын пайдалану арқылы бірдей әрекеттердің қалай орындалатынын көрсетемін. pivot_*() функциялары.

Кең пішімді ұзын форматқа түрлендіру.

Жинау функциясының құжаттамасындағы мысал код

# example
library(dplyr)
stocks <- data.frame(
  time = as.Date('2009-01-01') + 0:9,
  X = rnorm(10, 0, 1),
  Y = rnorm(10, 0, 2),
  Z = rnorm(10, 0, 4)
)

# old
stocks_gather <- stocks %>% gather(key   = stock, 
                                   value = price, 
                                   -time)

# new
stocks_long   <- stocks %>% pivot_longer(cols      = -time, 
                                       names_to  = "stock", 
                                       values_to = "price")

Ұзын форматты кең форматқа түрлендіру.

Спрэд функциясының құжаттамасындағы мысал код

# old
stocks_spread <- stocks_gather %>% spread(key = stock, 
                                          value = price) 

# new 
stock_wide    <- stocks_long %>% pivot_wider(names_from  = "stock",
                                            values_from = "price")

Өйткені жұмыс істеудің жоғарыдағы мысалдарында pivot_longer() и pivot_wider(), бастапқы кестеде акциялар аргументтер тізімінде ешқандай баған жоқ атаулары и мәндері_ олардың аттары тырнақшаға алынуы керек.

Жаңа тұжырымдамамен жұмыс істеуге қалай ауысу керектігін анықтауға көмектесетін кесте ұқыпты.

R бумасы tidyr және оның жаңа функциялары pivot_longer және pivot_wider

Автордан ескерту

Төмендегі мәтіннің барлығы бейімделген, тіпті тегін аударма дер едім виньеткалар tidyverse кітапханасының ресми веб-сайтынан.

Деректерді кең форматтан ұзын форматқа түрлендірудің қарапайым мысалы

pivot_longer () — бағандар санын азайту және жолдар санын көбейту арқылы деректер жиынын ұзартады.

R бумасы tidyr және оның жаңа функциялары pivot_longer және pivot_wider

Мақалада келтірілген мысалдарды іске қосу үшін алдымен қажетті пакеттерді қосу керек:

library(tidyr)
library(dplyr)
library(readr)

Бізде (басқа нәрселермен қатар) адамдардың діні мен жылдық табысы туралы сұраған сауалнама нәтижелері бар кесте бар делік:

#> # A tibble: 18 x 11
#>    religion `<$10k` `$10-20k` `$20-30k` `$30-40k` `$40-50k` `$50-75k`
#>    <chr>      <dbl>     <dbl>     <dbl>     <dbl>     <dbl>     <dbl>
#>  1 Agnostic      27        34        60        81        76       137
#>  2 Atheist       12        27        37        52        35        70
#>  3 Buddhist      27        21        30        34        33        58
#>  4 Catholic     418       617       732       670       638      1116
#>  5 Don’t k…      15        14        15        11        10        35
#>  6 Evangel…     575       869      1064       982       881      1486
#>  7 Hindu          1         9         7         9        11        34
#>  8 Histori…     228       244       236       238       197       223
#>  9 Jehovah…      20        27        24        24        21        30
#> 10 Jewish        19        19        25        25        30        95
#> # … with 8 more rows, and 4 more variables: `$75-100k` <dbl>,
#> #   `$100-150k` <dbl>, `>150k` <dbl>, `Don't know/refused` <dbl>

Бұл кесте респонденттердің дін деректерін жолдар бойынша қамтиды және кіріс деңгейлері баған атаулары бойынша шашыраңқы. Әрбір санаттағы респонденттердің саны дін мен кіріс деңгейінің қиылысындағы ұяшық мәндерінде сақталады. Кестені ұқыпты, дұрыс пішімге келтіру үшін оны пайдалану жеткілікті pivot_longer():

pew %>% 
  pivot_longer(cols = -religion, names_to = "income", values_to = "count")

pew %>% 
  pivot_longer(cols = -religion, names_to = "income", values_to = "count")
#> # A tibble: 180 x 3
#>    religion income             count
#>    <chr>    <chr>              <dbl>
#>  1 Agnostic <$10k                 27
#>  2 Agnostic $10-20k               34
#>  3 Agnostic $20-30k               60
#>  4 Agnostic $30-40k               81
#>  5 Agnostic $40-50k               76
#>  6 Agnostic $50-75k              137
#>  7 Agnostic $75-100k             122
#>  8 Agnostic $100-150k            109
#>  9 Agnostic >150k                 84
#> 10 Agnostic Don't know/refused    96
#> # … with 170 more rows

Функция аргументтері pivot_longer()

  • Бірінші аргумент қамыт, қандай бағандарды біріктіру керектігін сипаттайды. Бұл жағдайда басқа барлық бағандар уақыт.
  • дәлел атаулары біз біріктірген бағандардың атауларынан жасалатын айнымалының атын береді.
  • мәндері_ біріктірілген бағандардың ұяшықтарының мәндерінде сақталған деректерден жасалатын айнымалының атын береді.

Ерекшеліктер

Бұл пакеттің жаңа функционалдығы ұқыпты, ол бұрынғы функциялармен жұмыс істеу кезінде бұрын қол жетімді емес еді.

Спецификация - бұл деректер жақтауы, оның әрбір жолы жаңа шығыс күн жақтауындағы бір бағанға және келесіден басталатын екі арнайы бағанға сәйкес келеді:

  • аты бастапқы баған атауын қамтиды.
  • .мән ұяшық мәндерін қамтитын баған атауын қамтиды.

Спецификацияның қалған бағандары жаңа бағанның қысылған бағандардың атауын қалай көрсететінін көрсетеді аты.

Спецификация баған атауында сақталған метадеректерді сипаттайды, әрбір баған үшін бір жол және әр айнымалы үшін бір баған бар, баған атауымен біріктірілген, бұл анықтама қазіргі уақытта түсініксіз болып көрінуі мүмкін, бірақ бірнеше мысалдарды қарағаннан кейін ол көп болады. анық.

Сипаттаманың мәні мынада: түрлендірілетін деректер кадры үшін жаңа метадеректерді шығарып алуға, өзгертуге және анықтауға болады.

Кестені кең пішімнен ұзын пішімге түрлендіру кезінде сипаттамалармен жұмыс істеу үшін функцияны пайдаланыңыз pivot_longer_spec().

Бұл функция қалай жұмыс істейді, ол кез келген күн кадрын алады және оның метадеректерін жоғарыда сипатталған тәсілмен жасайды.

Мысал ретінде пакетпен қамтамасыз етілген who деректер жинағын алайық ұқыпты. Бұл деректер жинағында туберкулез ауруы туралы халықаралық денсаулық сақтау ұйымы ұсынған ақпарат бар.

who
#> # A tibble: 7,240 x 60
#>    country iso2  iso3   year new_sp_m014 new_sp_m1524 new_sp_m2534
#>    <chr>   <chr> <chr> <int>       <int>        <int>        <int>
#>  1 Afghan… AF    AFG    1980          NA           NA           NA
#>  2 Afghan… AF    AFG    1981          NA           NA           NA
#>  3 Afghan… AF    AFG    1982          NA           NA           NA
#>  4 Afghan… AF    AFG    1983          NA           NA           NA
#>  5 Afghan… AF    AFG    1984          NA           NA           NA
#>  6 Afghan… AF    AFG    1985          NA           NA           NA
#>  7 Afghan… AF    AFG    1986          NA           NA           NA
#>  8 Afghan… AF    AFG    1987          NA           NA           NA
#>  9 Afghan… AF    AFG    1988          NA           NA           NA
#> 10 Afghan… AF    AFG    1989          NA           NA           NA
#> # … with 7,230 more rows, and 53 more variables

Оның спецификациясын құрастырайық.

spec <- who %>%
  pivot_longer_spec(new_sp_m014:newrel_f65, values_to = "count")

#> # A tibble: 56 x 3
#>    .name        .value name        
#>    <chr>        <chr>  <chr>       
#>  1 new_sp_m014  count  new_sp_m014 
#>  2 new_sp_m1524 count  new_sp_m1524
#>  3 new_sp_m2534 count  new_sp_m2534
#>  4 new_sp_m3544 count  new_sp_m3544
#>  5 new_sp_m4554 count  new_sp_m4554
#>  6 new_sp_m5564 count  new_sp_m5564
#>  7 new_sp_m65   count  new_sp_m65  
#>  8 new_sp_f014  count  new_sp_f014 
#>  9 new_sp_f1524 count  new_sp_f1524
#> 10 new_sp_f2534 count  new_sp_f2534
#> # … with 46 more rows

өрістер ел, iso2, iso3 қазірдің өзінде айнымалылар. Біздің міндетіміз - бағандарды аудару new_sp_m014 туралы newrel_f65.

Бұл бағандардың атаулары келесі ақпаратты сақтайды:

  • Префикс new_ бағанда туберкулездің жаңа жағдайлары туралы деректер бар екенін көрсетеді, ағымдағы күндік жақтауда тек жаңа аурулар туралы ақпарат бар, сондықтан ағымдағы контексте бұл префикс ешқандай мағына бермейді.
  • sp/rel/sp/ep ауруды диагностикалау әдісін сипаттайды.
  • m/f науқастың жынысы.
  • 014/1524/2535/3544/4554/65 пациенттің жас диапазоны.

Біз бұл бағандарды функция арқылы бөле аламыз extract()тұрақты өрнекті қолдану.

spec <- spec %>%
        extract(name, c("diagnosis", "gender", "age"), "new_?(.*)_(.)(.*)")

#> # A tibble: 56 x 5
#>    .name        .value diagnosis gender age  
#>    <chr>        <chr>  <chr>     <chr>  <chr>
#>  1 new_sp_m014  count  sp        m      014  
#>  2 new_sp_m1524 count  sp        m      1524 
#>  3 new_sp_m2534 count  sp        m      2534 
#>  4 new_sp_m3544 count  sp        m      3544 
#>  5 new_sp_m4554 count  sp        m      4554 
#>  6 new_sp_m5564 count  sp        m      5564 
#>  7 new_sp_m65   count  sp        m      65   
#>  8 new_sp_f014  count  sp        f      014  
#>  9 new_sp_f1524 count  sp        f      1524 
#> 10 new_sp_f2534 count  sp        f      2534 
#> # … with 46 more rows

Бағанға назар аударыңыз аты өзгеріссіз қалуы керек, себебі бұл біздің бастапқы деректер жиынының баған атауларының индексі.

Жынысы мен жасы (бағандар жыныс и жас) тұрақты және белгілі мәндерге ие, сондықтан бұл бағандарды факторларға түрлендіру ұсынылады:

spec <-  spec %>%
            mutate(
              gender = factor(gender, levels = c("f", "m")),
              age = factor(age, levels = unique(age), ordered = TRUE)
            ) 

Соңында, біз жасаған спецификацияны бастапқы күн шеңберіне қолдану үшін кім аргумент қолдануымыз керек ерекшелігі функцияда pivot_longer().

who %>% pivot_longer(spec = spec)

#> # A tibble: 405,440 x 8
#>    country     iso2  iso3   year diagnosis gender age   count
#>    <chr>       <chr> <chr> <int> <chr>     <fct>  <ord> <int>
#>  1 Afghanistan AF    AFG    1980 sp        m      014      NA
#>  2 Afghanistan AF    AFG    1980 sp        m      1524     NA
#>  3 Afghanistan AF    AFG    1980 sp        m      2534     NA
#>  4 Afghanistan AF    AFG    1980 sp        m      3544     NA
#>  5 Afghanistan AF    AFG    1980 sp        m      4554     NA
#>  6 Afghanistan AF    AFG    1980 sp        m      5564     NA
#>  7 Afghanistan AF    AFG    1980 sp        m      65       NA
#>  8 Afghanistan AF    AFG    1980 sp        f      014      NA
#>  9 Afghanistan AF    AFG    1980 sp        f      1524     NA
#> 10 Afghanistan AF    AFG    1980 sp        f      2534     NA
#> # … with 405,430 more rows

Біз жасаған барлық әрекеттерді схемалық түрде келесідей бейнелеуге болады:

R бумасы tidyr және оның жаңа функциялары pivot_longer және pivot_wider

Бірнеше мәндерді қолданатын спецификация (.value)

Жоғарыдағы мысалда спецификация бағаны .мән тек бір мәнді қамтиды, көп жағдайда солай болады.

Бірақ кейде мәндерде әртүрлі деректер түрлері бар бағандардан деректерді жинау қажет болғанда жағдай туындауы мүмкін. Бұрынғы функцияны пайдалану spread() мұны істеу өте қиын болар еді.

Төмендегі мысалдан алынған виньеткалар пакетке деректер кестесі.

Жаттығу деректер қорын жасайық.

family <- tibble::tribble(
  ~family,  ~dob_child1,  ~dob_child2, ~gender_child1, ~gender_child2,
       1L, "1998-11-26", "2000-01-29",             1L,             2L,
       2L, "1996-06-22",           NA,             2L,             NA,
       3L, "2002-07-11", "2004-04-05",             2L,             2L,
       4L, "2004-10-10", "2009-08-27",             1L,             1L,
       5L, "2000-12-05", "2005-02-28",             2L,             1L,
)
family <- family %>% mutate_at(vars(starts_with("dob")), parse_date)

#> # A tibble: 5 x 5
#>   family dob_child1 dob_child2 gender_child1 gender_child2
#>    <int> <date>     <date>             <int>         <int>
#> 1      1 1998-11-26 2000-01-29             1             2
#> 2      2 1996-06-22 NA                     2            NA
#> 3      3 2002-07-11 2004-04-05             2             2
#> 4      4 2004-10-10 2009-08-27             1             1
#> 5      5 2000-12-05 2005-02-28             2             1

Жасалған күн шеңбері әр жолда бір отбасының балалары туралы деректерді қамтиды. Отбасында бір немесе екі бала болуы мүмкін. Әрбір бала үшін деректер туған күні мен жынысы бойынша беріледі, ал әрбір балаға арналған деректер жеке бағандарда беріледі, біздің міндетіміз - бұл деректерді талдау үшін дұрыс пішімге келтіру.

Бізде әр бала туралы ақпарат бар екі айнымалы мән бар екенін ескеріңіз: олардың жынысы және туған күні (префиксі бар бағандар Доп туған күні, префиксі бар бағандар бар жыныс баланың жынысын қамтиды). Күтілетін нәтиже - олар бөлек бағандарда пайда болуы керек. Біз мұны баған болатын спецификацияны жасау арқылы жасай аламыз .value екі түрлі мағынаға ие болады.

spec <- family %>%
  pivot_longer_spec(-family) %>%
  separate(col = name, into = c(".value", "child"))%>%
  mutate(child = parse_number(child))

#> # A tibble: 4 x 3
#>   .name         .value child
#>   <chr>         <chr>  <dbl>
#> 1 dob_child1    dob        1
#> 2 dob_child2    dob        2
#> 3 gender_child1 gender     1
#> 4 gender_child2 gender     2

Сонымен, жоғарыдағы кодпен орындалатын әрекеттерді кезең-кезеңімен қарастырайық.

  • pivot_longer_spec(-family) — отбасы бағанынан басқа барлық бар бағандарды қысатын спецификация жасаңыз.
  • separate(col = name, into = c(".value", "child")) - бағанды ​​бөлу аты, онда астын сызу арқылы және алынған мәндерді бағандарға енгізу арқылы бастапқы өрістердің атаулары бар .мән и бала.
  • mutate(child = parse_number(child)) — өріс мәндерін түрлендіру бала мәтіннен сандық деректер түріне дейін.

Енді алынған спецификацияны бастапқы деректер фрейміне қолданып, кестені қажетті пішінге келтіре аламыз.

family %>% 
    pivot_longer(spec = spec, na.rm = T)

#> # A tibble: 9 x 4
#>   family child dob        gender
#>    <int> <dbl> <date>      <int>
#> 1      1     1 1998-11-26      1
#> 2      1     2 2000-01-29      2
#> 3      2     1 1996-06-22      2
#> 4      3     1 2002-07-11      2
#> 5      3     2 2004-04-05      2
#> 6      4     1 2004-10-10      1
#> 7      4     2 2009-08-27      1
#> 8      5     1 2000-12-05      2
#> 9      5     2 2005-02-28      1

Біз аргументті қолданамыз na.rm = TRUE, себебі деректердің ағымдағы пішіні жоқ бақылаулар үшін қосымша жолдарды жасауға мәжбүр етеді. Өйткені 2-отбасында бір ғана бала бар, na.rm = TRUE 2-отбасының шығысында бір жол болатынына кепілдік береді.

Күн жиектерін ұзын пішімнен кең пішімге түрлендіру

pivot_wider() - кері түрлендіру болып табылады және керісінше жолдар санын азайту арқылы күн кадрының бағандарының санын көбейтеді.

R бумасы tidyr және оның жаңа функциялары pivot_longer және pivot_wider

Трансформацияның бұл түрі деректерді нақты пішінге келтіру үшін өте сирек қолданылады, дегенмен бұл әдіс презентацияларда пайдаланылатын жиынтық кестелерді құру немесе кейбір басқа құралдармен біріктіру үшін пайдалы болуы мүмкін.

Іс жүзінде функциялар pivot_longer() и pivot_wider() симметриялы және бір-біріне кері әрекеттер жасайды, яғни: df %>% pivot_longer(spec = spec) %>% pivot_wider(spec = spec) и df %>% pivot_wider(spec = spec) %>% pivot_longer(spec = spec) бастапқы df қайтарады.

Кестені кең форматқа түрлендірудің қарапайым мысалы

Функцияның қалай жұмыс істейтінін көрсету үшін pivot_wider() деректер жинағын қолданамыз балықтармен кездесулер, ол әртүрлі станциялар өзен бойындағы балықтардың қозғалысын қалай тіркейтіні туралы ақпаратты сақтайды.

#> # A tibble: 114 x 3
#>    fish  station  seen
#>    <fct> <fct>   <int>
#>  1 4842  Release     1
#>  2 4842  I80_1       1
#>  3 4842  Lisbon      1
#>  4 4842  Rstr        1
#>  5 4842  Base_TD     1
#>  6 4842  BCE         1
#>  7 4842  BCW         1
#>  8 4842  BCE2        1
#>  9 4842  BCW2        1
#> 10 4842  MAE         1
#> # … with 104 more rows

Көп жағдайда бұл кесте ақпаратты әр станцияға арналған ақпаратты бөлек бағанда ұсынсаңыз, пайдалану оңайырақ болады.

fish_encounters %>% pivot_wider(names_from = station, values_from = seen)

fish_encounters %>% pivot_wider(names_from = station, values_from = seen)
#> # A tibble: 19 x 12
#>    fish  Release I80_1 Lisbon  Rstr Base_TD   BCE   BCW  BCE2  BCW2   MAE
#>    <fct>   <int> <int>  <int> <int>   <int> <int> <int> <int> <int> <int>
#>  1 4842        1     1      1     1       1     1     1     1     1     1
#>  2 4843        1     1      1     1       1     1     1     1     1     1
#>  3 4844        1     1      1     1       1     1     1     1     1     1
#>  4 4845        1     1      1     1       1    NA    NA    NA    NA    NA
#>  5 4847        1     1      1    NA      NA    NA    NA    NA    NA    NA
#>  6 4848        1     1      1     1      NA    NA    NA    NA    NA    NA
#>  7 4849        1     1     NA    NA      NA    NA    NA    NA    NA    NA
#>  8 4850        1     1     NA     1       1     1     1    NA    NA    NA
#>  9 4851        1     1     NA    NA      NA    NA    NA    NA    NA    NA
#> 10 4854        1     1     NA    NA      NA    NA    NA    NA    NA    NA
#> # … with 9 more rows, and 1 more variable: MAW <int>

Бұл деректер жинағы станциямен балық анықталған кезде ғана ақпаратты жазады, яғни. егер қандай да бір станция қандай да бір балықты тіркемеген болса, онда бұл деректер кестеде болмайды. Бұл шығыс NA толтырылатынын білдіреді.

Дегенмен, бұл жағдайда біз жазбаның болмауы балықтың көрмегенін білдіретінін білеміз, сондықтан біз аргументті пайдалана аламыз. мәндерді_толтыру функцияда pivot_wider() және осы жетіспейтін мәндерді нөлдермен толтырыңыз:

fish_encounters %>% pivot_wider(
  names_from = station, 
  values_from = seen,
  values_fill = list(seen = 0)
)

#> # A tibble: 19 x 12
#>    fish  Release I80_1 Lisbon  Rstr Base_TD   BCE   BCW  BCE2  BCW2   MAE
#>    <fct>   <int> <int>  <int> <int>   <int> <int> <int> <int> <int> <int>
#>  1 4842        1     1      1     1       1     1     1     1     1     1
#>  2 4843        1     1      1     1       1     1     1     1     1     1
#>  3 4844        1     1      1     1       1     1     1     1     1     1
#>  4 4845        1     1      1     1       1     0     0     0     0     0
#>  5 4847        1     1      1     0       0     0     0     0     0     0
#>  6 4848        1     1      1     1       0     0     0     0     0     0
#>  7 4849        1     1      0     0       0     0     0     0     0     0
#>  8 4850        1     1      0     1       1     1     1     0     0     0
#>  9 4851        1     1      0     0       0     0     0     0     0     0
#> 10 4854        1     1      0     0       0     0     0     0     0     0
#> # … with 9 more rows, and 1 more variable: MAW <int>

Бірнеше бастапқы айнымалылардан баған атауын жасау

Бізде өнімнің, елдің және жылдың тіркесімін қамтитын кесте бар деп елестетіп көріңіз. Сынақ күні шеңберін жасау үшін келесі кодты іске қосуға болады:

df <- expand_grid(
  product = c("A", "B"), 
  country = c("AI", "EI"), 
  year = 2000:2014
) %>%
  filter((product == "A" & country == "AI") | product == "B") %>% 
  mutate(value = rnorm(nrow(.)))

#> # A tibble: 45 x 4
#>    product country  year    value
#>    <chr>   <chr>   <int>    <dbl>
#>  1 A       AI       2000 -2.05   
#>  2 A       AI       2001 -0.676  
#>  3 A       AI       2002  1.60   
#>  4 A       AI       2003 -0.353  
#>  5 A       AI       2004 -0.00530
#>  6 A       AI       2005  0.442  
#>  7 A       AI       2006 -0.610  
#>  8 A       AI       2007 -2.77   
#>  9 A       AI       2008  0.899  
#> 10 A       AI       2009 -0.106  
#> # … with 35 more rows

Біздің міндетіміз - бір баған өнімнің және елдің әрбір тіркесімі үшін деректерді қамтитындай деректер шеңберін кеңейту. Бұл әрекетті орындау үшін, дәлелдеуге жеткілікті атаулары біріктірілетін өрістердің атауларын қамтитын вектор.

df %>% pivot_wider(names_from = c(product, country),
                 values_from = "value")

#> # A tibble: 15 x 4
#>     year     A_AI    B_AI    B_EI
#>    <int>    <dbl>   <dbl>   <dbl>
#>  1  2000 -2.05     0.607   1.20  
#>  2  2001 -0.676    1.65   -0.114 
#>  3  2002  1.60    -0.0245  0.501 
#>  4  2003 -0.353    1.30   -0.459 
#>  5  2004 -0.00530  0.921  -0.0589
#>  6  2005  0.442   -1.55    0.594 
#>  7  2006 -0.610    0.380  -1.28  
#>  8  2007 -2.77     0.830   0.637 
#>  9  2008  0.899    0.0175 -1.30  
#> 10  2009 -0.106   -0.195   1.03  
#> # … with 5 more rows

Сондай-ақ, спецификацияларды функцияға қолдануға болады pivot_wider(). Бірақ тапсырылған кезде pivot_wider() спецификация қарама-қарсы түрлендіруді жасайды pivot_longer(): ішінде көрсетілген бағандар аты, мәнін пайдалану .мән және басқа бағандар.

Бұл деректер жиыны үшін әрбір ықтимал ел мен өнім комбинациясының деректерде барлар ғана емес, өз бағандары болуын қаласаңыз, теңшелетін спецификацияны жасай аласыз:

spec <- df %>% 
  expand(product, country, .value = "value") %>% 
  unite(".name", product, country, remove = FALSE)

#> # A tibble: 4 x 4
#>   .name product country .value
#>   <chr> <chr>   <chr>   <chr> 
#> 1 A_AI  A       AI      value 
#> 2 A_EI  A       EI      value 
#> 3 B_AI  B       AI      value 
#> 4 B_EI  B       EI      value

df %>% pivot_wider(spec = spec) %>% head()

#> # A tibble: 6 x 5
#>    year     A_AI  A_EI    B_AI    B_EI
#>   <int>    <dbl> <dbl>   <dbl>   <dbl>
#> 1  2000 -2.05       NA  0.607   1.20  
#> 2  2001 -0.676      NA  1.65   -0.114 
#> 3  2002  1.60       NA -0.0245  0.501 
#> 4  2003 -0.353      NA  1.30   -0.459 
#> 5  2004 -0.00530    NA  0.921  -0.0589
#> 6  2005  0.442      NA -1.55    0.594

Жаңа tidyr тұжырымдамасымен жұмыс істеудің бірнеше жетілдірілген мысалдары

Мысал ретінде АҚШ-тағы халық санағының кірісі мен жалдау деректер жинағын пайдаланып деректерді тазалау.

Деректер жинағы бізге_ренттен_кіріс 2017 жылға арналған АҚШ-тағы әрбір штат үшін орташа табыс пен жалдау туралы ақпаратты қамтиды (деректер жиынтығы пакетте қол жетімді реттік санақ).

us_rent_income
#> # A tibble: 104 x 5
#>    GEOID NAME       variable estimate   moe
#>    <chr> <chr>      <chr>       <dbl> <dbl>
#>  1 01    Alabama    income      24476   136
#>  2 01    Alabama    rent          747     3
#>  3 02    Alaska     income      32940   508
#>  4 02    Alaska     rent         1200    13
#>  5 04    Arizona    income      27517   148
#>  6 04    Arizona    rent          972     4
#>  7 05    Arkansas   income      23789   165
#>  8 05    Arkansas   rent          709     5
#>  9 06    California income      29454   109
#> 10 06    California rent         1358     3
#> # … with 94 more rows

Деректер жиынында деректер сақталатын пішінде бізге_ренттен_кіріс олармен жұмыс істеу өте ыңғайсыз, сондықтан біз бағандары бар деректер жинағын жасағымыз келеді: жалға алу, rent_moe, келу, кіріс_мое. Бұл спецификацияны жасаудың көптеген жолдары бар, бірақ бастысы - біз айнымалы мәндердің әрбір комбинациясын жасауымыз керек және бағалау/мсодан кейін баған атауын жасаңыз.

  spec <- us_rent_income %>% 
    expand(variable, .value = c("estimate", "moe")) %>% 
    mutate(
      .name = paste0(variable, ifelse(.value == "moe", "_moe", ""))
    )

#> # A tibble: 4 x 3
#>   variable .value   .name     
#>   <chr>    <chr>    <chr>     
#> 1 income   estimate income    
#> 2 income   moe      income_moe
#> 3 rent     estimate rent      
#> 4 rent     moe      rent_moe

Осы спецификацияны қамтамасыз ету pivot_wider() біз іздеген нәтижені береді:

us_rent_income %>% pivot_wider(spec = spec)

#> # A tibble: 52 x 6
#>    GEOID NAME                 income income_moe  rent rent_moe
#>    <chr> <chr>                 <dbl>      <dbl> <dbl>    <dbl>
#>  1 01    Alabama               24476        136   747        3
#>  2 02    Alaska                32940        508  1200       13
#>  3 04    Arizona               27517        148   972        4
#>  4 05    Arkansas              23789        165   709        5
#>  5 06    California            29454        109  1358        3
#>  6 08    Colorado              32401        109  1125        5
#>  7 09    Connecticut           35326        195  1123        5
#>  8 10    Delaware              31560        247  1076       10
#>  9 11    District of Columbia  43198        681  1424       17
#> 10 12    Florida               25952         70  1077        3
#> # … with 42 more rows

Дүниежүзілік банк

Кейде деректер жинағын қажетті пішінге келтіру бірнеше қадамдарды қажет етеді.
Деректер жинағы әлемдік_банк_поп Дүниежүзілік банктің 2000-2018 жылдар аралығындағы әр елдің халқы туралы мәліметтерін қамтиды.

#> # A tibble: 1,056 x 20
#>    country indicator `2000` `2001` `2002` `2003`  `2004`  `2005`   `2006`
#>    <chr>   <chr>      <dbl>  <dbl>  <dbl>  <dbl>   <dbl>   <dbl>    <dbl>
#>  1 ABW     SP.URB.T… 4.24e4 4.30e4 4.37e4 4.42e4 4.47e+4 4.49e+4  4.49e+4
#>  2 ABW     SP.URB.G… 1.18e0 1.41e0 1.43e0 1.31e0 9.51e-1 4.91e-1 -1.78e-2
#>  3 ABW     SP.POP.T… 9.09e4 9.29e4 9.50e4 9.70e4 9.87e+4 1.00e+5  1.01e+5
#>  4 ABW     SP.POP.G… 2.06e0 2.23e0 2.23e0 2.11e0 1.76e+0 1.30e+0  7.98e-1
#>  5 AFG     SP.URB.T… 4.44e6 4.65e6 4.89e6 5.16e6 5.43e+6 5.69e+6  5.93e+6
#>  6 AFG     SP.URB.G… 3.91e0 4.66e0 5.13e0 5.23e0 5.12e+0 4.77e+0  4.12e+0
#>  7 AFG     SP.POP.T… 2.01e7 2.10e7 2.20e7 2.31e7 2.41e+7 2.51e+7  2.59e+7
#>  8 AFG     SP.POP.G… 3.49e0 4.25e0 4.72e0 4.82e0 4.47e+0 3.87e+0  3.23e+0
#>  9 AGO     SP.URB.T… 8.23e6 8.71e6 9.22e6 9.77e6 1.03e+7 1.09e+7  1.15e+7
#> 10 AGO     SP.URB.G… 5.44e0 5.59e0 5.70e0 5.76e0 5.75e+0 5.69e+0  4.92e+0
#> # … with 1,046 more rows, and 11 more variables: `2007` <dbl>,
#> #   `2008` <dbl>, `2009` <dbl>, `2010` <dbl>, `2011` <dbl>, `2012` <dbl>,
#> #   `2013` <dbl>, `2014` <dbl>, `2015` <dbl>, `2016` <dbl>, `2017` <dbl>

Біздің мақсатымыз - әр айнымалы өз бағанында ұқыпты деректер жинағын жасау. Қандай қадамдар қажет екені белгісіз, бірақ біз ең айқын мәселеден бастаймыз: жыл бірнеше бағандарға таралады.

Мұны түзету үшін функцияны пайдалану керек pivot_longer().

pop2 <- world_bank_pop %>% 
  pivot_longer(`2000`:`2017`, names_to = "year")

#> # A tibble: 19,008 x 4
#>    country indicator   year  value
#>    <chr>   <chr>       <chr> <dbl>
#>  1 ABW     SP.URB.TOTL 2000  42444
#>  2 ABW     SP.URB.TOTL 2001  43048
#>  3 ABW     SP.URB.TOTL 2002  43670
#>  4 ABW     SP.URB.TOTL 2003  44246
#>  5 ABW     SP.URB.TOTL 2004  44669
#>  6 ABW     SP.URB.TOTL 2005  44889
#>  7 ABW     SP.URB.TOTL 2006  44881
#>  8 ABW     SP.URB.TOTL 2007  44686
#>  9 ABW     SP.URB.TOTL 2008  44375
#> 10 ABW     SP.URB.TOTL 2009  44052
#> # … with 18,998 more rows

Келесі қадам - ​​индикатор айнымалысын қарау.
pop2 %>% count(indicator)

#> # A tibble: 4 x 2
#>   indicator       n
#>   <chr>       <int>
#> 1 SP.POP.GROW  4752
#> 2 SP.POP.TOTL  4752
#> 3 SP.URB.GROW  4752
#> 4 SP.URB.TOTL  4752

Мұндағы SP.POP.GROW - халық санының өсуі, SP.POP.TOTL - жалпы халық саны және SP.URB. * бірдей нәрсе, бірақ тек қалалық жерлер үшін. Бұл мәндерді екі айнымалыға бөлейік: аудан - аудан (жалпы немесе қалалық) және нақты деректерді қамтитын айнымалы (халық немесе өсім):

pop3 <- pop2 %>% 
  separate(indicator, c(NA, "area", "variable"))

#> # A tibble: 19,008 x 5
#>    country area  variable year  value
#>    <chr>   <chr> <chr>    <chr> <dbl>
#>  1 ABW     URB   TOTL     2000  42444
#>  2 ABW     URB   TOTL     2001  43048
#>  3 ABW     URB   TOTL     2002  43670
#>  4 ABW     URB   TOTL     2003  44246
#>  5 ABW     URB   TOTL     2004  44669
#>  6 ABW     URB   TOTL     2005  44889
#>  7 ABW     URB   TOTL     2006  44881
#>  8 ABW     URB   TOTL     2007  44686
#>  9 ABW     URB   TOTL     2008  44375
#> 10 ABW     URB   TOTL     2009  44052
#> # … with 18,998 more rows

Енді бізге айнымалы мәнді екі бағанға бөлу ғана қалды:

pop3 %>% 
  pivot_wider(names_from = variable, values_from = value)

#> # A tibble: 9,504 x 5
#>    country area  year   TOTL    GROW
#>    <chr>   <chr> <chr> <dbl>   <dbl>
#>  1 ABW     URB   2000  42444  1.18  
#>  2 ABW     URB   2001  43048  1.41  
#>  3 ABW     URB   2002  43670  1.43  
#>  4 ABW     URB   2003  44246  1.31  
#>  5 ABW     URB   2004  44669  0.951 
#>  6 ABW     URB   2005  44889  0.491 
#>  7 ABW     URB   2006  44881 -0.0178
#>  8 ABW     URB   2007  44686 -0.435 
#>  9 ABW     URB   2008  44375 -0.698 
#> 10 ABW     URB   2009  44052 -0.731 
#> # … with 9,494 more rows

Байланыс тізімі

Соңғы мысал, сізде веб-сайттан көшіріп, қойған контактілер тізімі бар деп елестетіңіз:

contacts <- tribble(
  ~field, ~value,
  "name", "Jiena McLellan",
  "company", "Toyota", 
  "name", "John Smith", 
  "company", "google", 
  "email", "[email protected]",
  "name", "Huxley Ratcliffe"
)

Бұл тізімді кестелеу өте қиын, себебі қандай деректер қай контактіге тиесілі екенін анықтайтын айнымалы жоқ. Мұны әрбір жаңа контактінің деректері «атаудан» басталатынын ескеру арқылы түзете аламыз, осылайша біз бірегей идентификатор жасай аламыз және өріс бағанында «аты» мәні болған сайын оны бір есе арттыра аламыз:

contacts <- contacts %>% 
  mutate(
    person_id = cumsum(field == "name")
  )
contacts

#> # A tibble: 6 x 3
#>   field   value            person_id
#>   <chr>   <chr>                <int>
#> 1 name    Jiena McLellan           1
#> 2 company Toyota                   1
#> 3 name    John Smith               2
#> 4 company google                   2
#> 5 email   [email protected]          2
#> 6 name    Huxley Ratcliffe         3

Енді бізде әрбір контакт үшін бірегей идентификатор бар, біз өріс пен мәнді бағандарға айналдыра аламыз:

contacts %>% 
  pivot_wider(names_from = field, values_from = value)

#> # A tibble: 3 x 4
#>   person_id name             company email          
#>       <int> <chr>            <chr>   <chr>          
#> 1         1 Jiena McLellan   Toyota  <NA>           
#> 2         2 John Smith       google  [email protected]
#> 3         3 Huxley Ratcliffe <NA>    <NA>

қорытынды

Менің жеке пікірім - бұл жаңа тұжырымдама ұқыпты шынымен интуитивті және бұрынғы функцияларға қарағанда функционалдығы жағынан айтарлықтай жоғары spread() и gather(). Бұл мақала сізге түсінуге көмектесті деп үміттенемін pivot_longer() и pivot_wider().

Ақпарат көзі: www.habr.com

пікір қалдыру